agentleFS
lizliz404lizliz404/agent-skills/skills/doubao-tts/SKILL.md

doubao-tts

Skill0 starsChanged 26 days agoMITView on GitHub

Use for Doubao/Volcengine article audio (TTS), dual-speaker podcasts, ASR transcripts, or 语音妙记/智能妙记 for separate interview recordings. Covers text cleaning, V1/V3 endpoints, Flash/Standard ASR, native minutes with timestamps/summaries/chapters/todo/Q&A, private delivery and query-only recovery, lizliz.xyz publish paths, and ElevenLabs fallback routing.

  • Reads credentials

9 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use hyperframes-cli.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • OpenAISkill

    hyperframes-cli

    HyperFrames CLI tool — hyperframes init, lint, inspect, preview, render, transcribe, tts, doctor, browser, info, upgrade, compositions, docs, benchmark. Use when scaffolding a project, linting, validating, inspecting visual layout in compositions, previewing in the studio, rendering to video, transcribing audio, generating TTS, or troubleshooting the HyperFrames environment.

    Also in 3 projects that use this

The file

Show its rules and text

We split this skill into the rules it gives an agent

18 rules. 0 are common, 8 are distinctive, and 10 are very specific to this project.

  • 0

    Common

    Most of the 6 edited versions we read keep these.

  • 8

    Distinctive

    This author's own choices. Worth a look.

  • 10

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Do not start on the old console for new setups — it is harder to navigate.

    line 26
  2. Distinctive:

    Create or copy a single API Key from the new console's API Key management.

    line 30
  3. Very specific:

    One key, many services: After topping up on the new console, that API Key is the credential for TTS, ASR (speech→text), Podcast generation, …

    line 34
  4. Very specific:

    Do not narrate References / Footnotes by default: Stop before References / 参考资料 / Footnotes / 脚注 / Sources / 引用.

    line 54
  5. Distinctive:

    Skip multi-voice smoke tests: when Liz already chose the default.

    line 56
  6. Very specific:

    Start from this skill: when Liz mentions Doubao speech / TTS / ASR / 妙记 — read this checkout's SKILL.md and route to the relevant reference …

    line 61
  7. Very specific:

    Best practice: put the real secret once under ~/.agents/secrets/ so Cursor / Claude / Codex / other agents sharing ~/.agents/skills can all …

    line 82
  8. Very specific:

    Deprecated for new setups: Keep populated while tts-generate.py, podcast-generate.py, and asr-transcribe.py still expect them.

    line 103
  9. Very specific:

    Do not put the API Key into the V1 Bearer.

    line 118
  10. Very specific:

    If neither DOUBAO_API_KEY (or aliases) nor legacy App ID / Access Token is set: stop.

    line 136
  11. Distinctive:

    Prefer for realtime / streaming text.

    line 183
  12. Very specific:

    Place site audio: public/audio/articles/<slug>/<slug>.mp3 (or project convention).

    line 248
  13. Distinctive:

    Verify size, duration, link.

    line 250
  14. Very specific:

    Prefer native Doubao bitrate (~160 kbps).

    line 261
  15. Very specific:

    Default speakers: zh_male_dayixiansheng_v2_saturn_bigtts + zh_female_mizaitongxue_v2_saturn_bigtts.

    line 299
  16. Distinctive:

    Keep requested recordings separate.

    line 393
  17. Distinctive:

    Default to transcription + automatic speaker IDs + word timestamps + summary + chapters + todo/Q&A.

    line 394
  18. Distinctive:

    No minutes client is bundled yet.

    line 399

“Common” is measured: kept by at least 6 in 10 of the 6 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Doubao TTS (TTS + Podcast + ASR + Voice Minutes)

Overview

Doubao / Volcengine(豆包语音)is widely regarded as top-tier Chinese speech AI and is the quality-default provider for Liz's writing pipeline. Prefer 火山引擎豆包 over generic TTS alternatives unless blocked.

This skill covers four 豆包语音 products: TTS (text→speech for article audio), Podcast (AI dual-speaker conversation), ASR (speech→text with optional diarization), and Voice Minutes / 语音妙记 (transcription plus native meeting summaries). On the new console, one API Key authenticates across these services via X-Api-Key. Endpoints and resource IDs still differ per product.

ElevenLabs has a cleaner HTTP API but weaker preferred voice/model quality for this workflow — last-resort fallback only (elevenlabs-tts). Do not choose it for convenience.

Onboarding (new console — preferred)

Do not start on the old console for new setups — it is harder to navigate. Use the new 豆包语音 console:

  1. Open the 火山引擎豆包语音新版控制台.
  2. Top up / activate the speech products you need (TTS, ASR, Podcast, etc.).
  3. Create or copy a single API Key from the new console's API Key management.
  4. Store it as DOUBAO_API_KEY (canonical) in the writing-profile secrets path below. Alias DOUBAO_SPEECH_API_KEY / legacy DOUBAO_TTS2_API_KEY are accepted.
  5. Hand the key to the agent. If auth or product routing is unclear, also hand the 豆包语音产品简介 / 能力总览文档 (or the relevant API page from References / 参考文献).

One key, many services: After topping up on the new console, that API Key is the credential for TTS, ASR (speech→text), Podcast generation, and related 豆包语音 calls that accept X-Api-Key. You no longer need a separate App ID + Access Token pair for new-console workflows.

Existing bundled scripts (tts-generate.py, podcast-generate.py, asr-transcribe.py) still read the legacy App ID / Access Token env vars and old-console header shapes. Keep those vars populated until scripts are migrated; for new agent code prefer DOUBAO_API_KEY + X-Api-Key.

When to Use

  • TTS: Liz asks to turn a writing project, final.md, essay, or lizliz.xyz post into spoken audio (豆包 / 火山引擎 / ByteDance TTS).
  • Podcast: Liz asks to turn an article, TXT, URL, or topic into a dual-speaker AI podcast (豆包语音播客大模型). Separate product — activate via the new console (legacy activation deep-link also listed in References).
  • ASR: Liz asks only for verbatim MP3 / WAV / OGG / voice memo / video-audio text (prefer Flash ASR).
  • Voice Minutes: Liz asks for 豆包语音妙记 / 智能妙记, interview/meeting transcription plus native summaries, chapters, todo or Q&A, or to repeat the established separate-recording workflow. Read references/doubao-minutes.md; do not substitute plain Flash ASR.
  • Debugging Doubao voices, payloads, article-audio placement, lizliz.xyz audio links, or ASR quality.

Don't use for:

  • ElevenLabs-first generation → elevenlabs-tts
  • Music tagging / source separation / MIDI / beat detection → separate SAMI / 智能K歌 product lines (see references/volcengine-audio-ecosystem.md)
  • Real-time S2S voice agents → 端到端实时语音大模型 (out of scope; see References)

Core rules

  1. Do not read Markdown aloud. Strip YAML, heading markers, emphasis, footnotes, table pipes, HRs, raw URLs, images, code fences unless the content itself must be spoken.
  2. Do not narrate References / Footnotes by default. Stop before References / 参考资料 / Footnotes / 脚注 / Sources / 引用. Source appendix audio only if Liz asks.
  3. Keep the article voice. Preserve Chinese punctuation rhythm, paragraph breaks, quotes, and English technical terms.
  4. Skip multi-voice smoke tests when Liz already chose the default.
  5. Default voice: zh_female_vv_uranus_bigtts (Vivi2.0) unless Liz picks another or quota blocks.
  6. Production TTS route: verified V1 https://openspeech.bytedance.com/api/v1/tts with cluster: volcano_tts. V3 streaming is the migration/realtime path, not the article default.
  7. Prefer new-console DOUBAO_API_KEY for new work; keep legacy App ID / Access Token only for existing scripts or V1 Bearer payloads until migrated.
  8. ElevenLabs last resort only — quota/auth/platform failure, or explicit request. Keep provider visible in filenames/manifests.
  9. Start from this skill when Liz mentions Doubao speech / TTS / ASR / 妙记 — read this checkout's SKILL.md and route to the relevant reference before broad-searching old notes. Reusable playbooks belong here; recordings, transcripts, credentials and run receipts do not.

Environment contract

Secrets stay out of this file. Record variable names and paths only.

Canonical secrets + lookup order (first hit wins):

# Windows / multi-agent hub (preferred on this machine)
%USERPROFILE%\.agents\secrets\doubao-tts.env
%USERPROFILE%\.agents\secrets\elevenlabs.env

# Hermes writing-profile path (Linux / Hermes agents; keep as mirror)
~/.hermes/secrets/doubao-tts.env
~/.hermes/secrets/elevenlabs.env
~/.hermes/profiles/writing/.env.d/*.env -> ~/.hermes/secrets/*.env
~/.hermes/profiles/trading/.env.d/*.env -> ~/.hermes/secrets/*.env
~/.hermes/.env.d/*.env -> ~/.hermes/secrets/*.env

Best practice: put the real secret once under ~/.agents/secrets/ so Cursor / Claude / Codex / other agents sharing ~/.agents/skills can all find it; mirror the same file to ~/.hermes/secrets/ if Hermes scripts still hard-code that path. Do not commit secrets into the skill folder.

Also mirror into profile .env when convenient (older scripts only source .env). New scripts should load .env and .env.d/*.env, and should also try ~/.agents/secrets/*.env before failing.

Writing-profile home: /home/ubuntu/.hermes/profiles/writing/.env

Preferred: single API Key (new console)

DOUBAO_API_KEY=...                 # canonical — X-Api-Key for TTS / ASR / Podcast (new console)
# accepted aliases (same value):
DOUBAO_SPEECH_API_KEY=...
DOUBAO_TTS2_API_KEY=...            # historical name from TTS 2.0 samples; keep as alias

Resolution order for new code: DOUBAO_API_KEY → DOUBAO_SPEECH_API_KEY → DOUBAO_TTS2_API_KEY.

Optional (shared): DOUBAO_TTS_CLUSTER=volcano_tts, DOUBAO_TTS_VOICE_TYPE=zh_female_vv_uranus_bigtts.

Legacy auth (old console) — existing scripts / V1 HTTP

Deprecated for new setups. Keep populated while tts-generate.py, podcast-generate.py, and asr-transcribe.py still expect them.

DOUBAO_TTS_APP_ID=...              # old console App ID → X-Api-App-Key / X-Api-App-Id / V1 app.appid
DOUBAO_TTS_ACCESS_TOKEN=...        # old Access Token → X-Api-Access-Key / V1 Authorization: Bearer; …
DOUBAO_TTS_SECRET_KEY=...          # optional; some SDK variants

Aliases (compat): VOLCENGINE_TTS_*, VOLC_TTS_*.

PathAuth shape
New consoleX-Api-Key: $DOUBAO_API_KEY alone (ASR Flash, TTS V3, and related new-console APIs)
Old console / current scriptsX-Api-App-Key/X-Api-App-Id + X-Api-Access-Key, or V1 Authorization: Bearer; <token> + JSON app.appid/app.token

Do not put the API Key into the V1 Bearer; header or the Access Token into X-Api-Key interchangeably — formats differ.

Shell export gotcha — plain source .env may not export to child Python:

set -a; . /home/ubuntu/.hermes/profiles/writing/.env; set +a

Presence check (no secret dump):

python3 - <<'PY'
import os, re
for name in sorted(k for k in os.environ if re.search(r'(DOUBAO|VOLC|TTS)', k)):
    print(f"{name}=<set>")
PY

If neither DOUBAO_API_KEY (or aliases) nor legacy App ID / Access Token is set: stop. Do not fall back to Edge/OpenAI or claim Doubao audio was generated.


TTS (文字→语音)

V1 HTTP — production default

Verified working for article audio. Official docs now list this under historical/小模型 docs, but the endpoint remains active and is Liz's reliable route from this server. Full parameter notes: V1 HTTP API.

This path still uses legacy App ID + Access Token in the JSON body and Authorization: Bearer; <AccessToken> — not DOUBAO_API_KEY / X-Api-Key. Bundled tts-generate.py matches this shape.

POST https://openspeech.bytedance.com/api/v1/tts
Authorization: Bearer; <AccessToken>
Content-Type: application/json

(Bearer; with semicolon is intentional — official format.)

{
  "app": {"appid": "APPID", "token": "TOKEN", "cluster": "volcano_tts"},
  "user": {"uid": "unique_user_identifier"},
  "audio": {
    "voice_type": "zh_female_vv_uranus_bigtts",
    "encoding": "mp3",
    "speed_ratio": 1.0,
    "volume_ratio": 1.0,
    "pitch_ratio": 1.0
  },
  "request": {
    "reqid": "uuid",
    "text": "plain text",
    "text_type": "plain",
    "operation": "query",
    "with_frontend": 1
  }
}

Success: code == 3000; audio in base64 data. Unique reqid per call (UUID).

Limits: Official small-model docs cite ~1024 UTF-8 bytes per request; HTTP also has a ~60s RPC timeout. For Liz's bigtts App, practical safe chunk size is ~1800–2000 characters. Chunks of 5000+ often fail with code:3031 / RPC timeout.

V3 / TTS 2.0 streaming — migration & realtime

Prefer for realtime / streaming text; keep V1 for batch article audio until a protocol helper is wired into scripts.

EndpointRole
wss://openspeech.bytedance.com/api/v3/tts/bidirectionBidirectional stream (LLM token → audio)
wss://openspeech.bytedance.com/api/v3/tts/unidirectional/streamFull text in, audio stream out (WS)
https://openspeech.bytedance.com/api/v3/tts/unidirectionalHTTP Chunked unidirectional
https://openspeech.bytedance.com/api/v3/tts/unidirectional/sseHTTP SSE unidirectional

Bidirectional headers (new console):

X-Api-Key: $DOUBAO_API_KEY
X-Api-Resource-Id: seed-tts-2.0
X-Api-Connect-Id: <uuid>
X-Control-Require-Usage-Tokens-Return: *

(DOUBAO_SPEECH_API_KEY / DOUBAO_TTS2_API_KEY aliases resolve to the same header value.)

Resource IDs: seed-tts-2.0 / seed-tts-1.0 / seed-tts-1.0-concurr / seed-icl-2.0 / seed-icl-1.0 (+ concurr). Full payload, additions (disable_markdown_filter, subtitles, dialects), and async long-text (/api/v3/tts/submit|query) → references/tts-streaming-v3.md. Official pages: 双向流式 TTS 2.0, V3 HTTP Chunked/SSE.

Known voices

Smoke-test voices on the current App rather than trusting a guide blindly. Common comparison set:

voice_typeNotes
zh_female_vv_uranus_bigttsDefault Vivi2.0 — model doubao-seed-tts-2.0; do not send emotion/neutral (ignored)
zh_female_xueayi_saturn_bigtts薛艾依 / 绘本艾依 — observed working on V1
zh_female_wanwanxiaohe_moon_bigttsPrior auth/resource mismatch — retest after package change
zh_female_shuangkuaisisi_moon_bigttsPrior auth/resource mismatch — retest after package change

Vivi defaults: speed 1.0, volume 1.0, sample rate 24000, format mp3. If too lively, try speed 0.98 after a baseline at 1.0.

Discover voices via console or OpenAPI ListSpeakers / ListBigModelTTSTimbres.

Text cleaning checklist

MP3 is baked — clean before synthesize. Work in memory or /tmp; never modify the source manuscript for TTS.

  1. Strip YAML frontmatter (---\n...\n---).
  2. Cut from ## References / 参考资料 / Footnotes / 脚注 / Sources / 引用 / Claim Check onward.
  3. Strip all HTML (<a id>, <span>, etc.). Leakage was read as "IA Intro".
  4. Strip citation links entirely: [N](#ref-N) → remove (not bare N).
  5. Strip MD: #, **, *, [text](url)→text, images, ---, backticks, >, [^N].
  6. Strip top audio links ([收听音频版...](...)).
  7. Save cleaned text under /tmp for audit.

Automated: scripts/strip-for-tts.py.

Article audio workflow

Skill dir:

SKILL_DIR="$HOME/.hermes/profiles/writing/skills/media/doubao-tts"
VENV_PY="/home/ubuntu/.hermes/hermes-agent/venv/bin/python3"
  1. Clean: python3 "$SKILL_DIR/scripts/strip-for-tts.py" <final.md> /tmp/<slug>-tts.txt
  2. Generate (chunk → 2 parts under CF 25 MiB):
    python3 "$SKILL_DIR/scripts/tts-generate.py" /tmp/<slug>-tts.txt /tmp/<slug>-tts/ <slug>
    → <slug>-part1.mp3, <slug>-part2.mp3. Merge if total < 25 MiB:
    ffmpeg -y -i "concat:...-part1.mp3|...-part2.mp3" -c copy /tmp/<slug>-tts/<slug>.mp3
  3. Place site audio: public/audio/articles/<slug>/<slug>.mp3 (or project convention).
  4. Link near top: [收听音频版](/audio/articles/<slug>/<slug>.mp3).
  5. Verify size, duration, link; push writing + site repos (writing Action syncs Markdown, not arbitrary local audio).

Audio-first stub (正文 not ready): minimal final.md with frontmatter + placeholder + audio link; copy MP3 into site public/audio/articles/; light sync checks only — not a full publish audit.

Multi-part source narration: boundary files tts-part-N.txt; text_type: plain; one MP3 + manifest per segment; ffprobe every file.

Chunking & quality

  • Max ~2000 chars / request; split on \n\n.
  • Concat: ffmpeg -f concat -safe 0 -i list.txt -c copy out.mp3.
  • Group into 2+ parts for CF Pages 25 MiB/file limit.
  • Prefer native Doubao bitrate (~160 kbps). Floor for publish: 96 kbps. Re-encode only if over limit: ffmpeg -i in.mp3 -codec:a libmp3lame -b:a 96k -ac 1 out.mp3. See references/cf-pages-size-limit.md.

Podcast (AI 播客)

Separate product from TTS. Full protocol: references/podcast-api.md. Session traps: references/podcast-session-learnings.md. Publish: references/lizliz.xyz-podcast-page.md. Official WS protocol: 播客 API websocket-v3.

wss://openspeech.bytedance.com/api/v3/sami/podcasttts

New console (preferred for new clients):

X-Api-Key: $DOUBAO_API_KEY
X-Api-Resource-Id: volc.service_type.10050
X-Api-App-Key: aGjiRDfUWi   # fixed product key (still required by protocol docs)
X-Api-Request-Id: <uuid>

Legacy / current podcast-generate.py headers:

X-Api-App-Id / X-Api-Access-Key / X-Api-Resource-Id: volc.service_type.10050
X-Api-App-Key: aGjiRDfUWi   # fixed

Binary frame message_type = 0b0001 (header byte1 0x14). Do not use TTS bidirectional 0b0011 → "unsupported message type (3)".

actionMode
0Long-text / URL summarize → dual dialogue (default)
3Direct nlp_texts dialogue synthesize
4prompt_text web-search summarize

Liz defaults (2026-07): action=0, mp3/24000/speech_rate=0, speakers dayi+mizai, random_order=false (male first), head+tail music on, AIGC watermarks off, strip MD first.

Default speakers: zh_male_dayixiansheng_v2_saturn_bigtts + zh_female_mizaitongxue_v2_saturn_bigtts. Alt pair: liufei + xiaolei. Official update (2026-03): TTS/ICL voices also allowed (same App as podcast); use speaker_info.speaker_additions for ICL model switches. New (2026-05): input_info.strict_audit.

Generate: $VENV_PY "$SKILL_DIR/scripts/podcast-generate.py" input.txt out.mp3
NLP-only transcript: scripts/extract-transcript.py (only_nlp_text). Prefer Flash ASR on the finished MP3 for subtitles (separate quota, matches actual audio).


ASR (语音→文字)

New console: same DOUBAO_API_KEY as TTS/Podcast (X-Api-Key). Legacy scripts: still use DOUBAO_TTS_APP_ID / DOUBAO_TTS_ACCESS_TOKEN with old header names.

Flash ASR — preferred ≤2h

One-shot; no submit/poll. Docs: 录音文件识别极速版 HTTP.

POST https://openspeech.bytedance.com/api/v3/auc/bigmodel/recognize/flash

New console headers:

X-Api-Key: $DOUBAO_API_KEY
X-Api-Resource-Id: volc.bigasr.auc_turbo
X-Api-Request-Id: <uuid>
X-Api-Sequence: -1

Legacy / current asr-transcribe.py headers:

X-Api-App-Key / X-Api-Access-Key / X-Api-Resource-Id: volc.bigasr.auc_turbo
X-Api-Request-Id: <uuid> / X-Api-Sequence: -1
{
  "user": {"uid": "<APP_ID>"},
  "audio": {"data": "<base64>"},
  "request": {
    "model_name": "bigmodel",
    "enable_itn": true,
    "enable_punc": true,
    "enable_ddc": false,
    "enable_speaker_info": true,
    "show_utterances": true
  }
}

URL mode: "audio": {"url": "https://..."} instead of data.

ParamVerbatim 逐字稿Clean reading
enable_ddcfalse (keep 嗯/啊/是吧)true
enable_punctruetrue
enable_itntruetrue
enable_speaker_infotrue for podcastsas needed

Limits: ≤2h, ≤100 MB; WAV/MP3/OGG OPUS. Base64 inflates ~33% — prefer URL if raw > ~50 MB. Binary upload recommendation: keep under ~20 MB when possible.

Success header: X-Api-Status-Code: 20000000. Speaker in utterances[].additions.speaker.

CodeMeaning
20000000Success
20000003Silent audio
45000001Invalid params
45000002Empty audio
45000151Unsupported format
55000031Server busy
550xxxxInternal error

Script: scripts/asr-transcribe.py (maps ASR "1"/"2" → dayi/mizai for default podcast order).

Flash does not support customer-service extras: enable_emotion_detection, enable_gender_detection, enable_lid, show_volume, show_speech_rate (removed from Flash; use Standard).

Standard ASR — >2h or emotion / gender / LID

POST .../api/v3/auc/bigmodel/submit
POST .../api/v3/auc/bigmodel/query

Resource IDs: volc.seedasr.auc (model 2.0) or volc.bigasr.auc (model 1.0). URL required (no base64). Docs: 录音文件识别标准版 HTTP. Feature matrix (emotion, diarization, ITN, etc.): 大模型录音文件识别能力表.

Emotion detection (enable_emotion_detection: true): Standard / streaming nostream / bidirectional-optimized ASR only. Labels: angry / happy / neutral / sad / surprise on utterance additions.emotion. Also: enable_gender_detection, enable_lid, show_volume, show_speech_rate.


Voice Minutes / 语音妙记

For separate interview recordings with native minutes, read the minutes playbook. It covers volc.lark.minutes, submit/query, the established Chinese-only parameters, bounded source delivery, duplicate-billing prevention and output review.

  • Keep requested recordings separate. Preserve originals; distinguish remuxed originals from lossy recognition copies.
  • Default to transcription + automatic speaker IDs + word timestamps + summary + chapters + todo/Q&A; no translation.
  • AllActivate selects bundled billing, not all features. Set each feature explicitly; retain the established billing choice unless an evidence-backed cost comparison justifies changing it.
  • Save task IDs and result files. A submit receipt is not completion; recover existing successful tasks by query/download, never by resubmission.
  • Deliver separate readable Markdown and retain reviewed raw result JSON privately. Do not generate ZIP/SRT/TXT or publish/archive recordings by default.

No minutes client is bundled yet; the reference is the reusable contract, not a claim that the legacy ASR script implements minutes.


Failure signatures

SignatureMeaning / action
requested resource not grantedApp lacks voice/resource — change package or voice
resource ID is mismatched with speaker related resourceV3 resource/voice mismatch — use granted pair or V1
DNS fail speech.volcengineapi.comWrong host from this server — use openspeech.bytedance.com
quota exceeded for types: text_words_lifetimeLifetime words gone — stop retries; refresh package or ElevenLabs
Podcast: event 150 then silenceQuota exhaustion (no error frame) — do not retry
code:3031 / RPC timeoutChunk too large — shrink under ~2000 chars
40200002 DeniedAccess:IllegalToken on SAMIWrong product line — need SAMI token, not TTS token
websockets extra_headers TypeErrorUse additional_headers (websockets ≥14)

Quota APIs exist in console OpenAPI (QuotaMonitoring, UsageMonitoring, ResourcePacksStatus) — not wired in scripts; treat runtime quota errors as authoritative.


Beyond this skill

豆包语音 products here: TTS, Podcast, ASR, Voice Minutes (playbook; no bundled client). Adjacent (separate auth / out of default scripts):

  • 声音复刻 ICL 1.0/2.0 (seed-icl-*)
  • 异步长文本 TTS (/api/v3/tts/submit|query)
  • 端到端实时语音大模型, 语音同传
  • SAMI MusicTagging / 音源分离, 智能K歌, 豆包音乐模型

Details: references/volcengine-audio-ecosystem.md. Search Volcengine docs before assuming credential reuse.


Common Pitfalls

Text & cleaning

  1. Feeding raw final.md → reads MD/HTML/refs aloud.
  2. HTML <a id> leakage (#1 artifact) — strip all tags.
  3. Citation [N](#ref-N) left as bare numbers (#2) — remove entirely.
  4. Partial-TTS requests still fed full article — trim first, then strip.

Auth & protocol

  1. Swapping DOUBAO_API_KEY with V1 Access Token (or putting Access Token in X-Api-Key) — formats are not interchangeable.
  2. Starting new setups on the old console when the new console is available.
  3. Podcast message_type=0b0011 copied from TTS bidirectional samples.
  4. ASR headers ≠ TTS V1 Authorization: Bearer; — use X-Api-* (new: Key alone; legacy: App-Key + Access-Key).
  5. Wrong ASR resource ID (volc.bigasr.auc_turbo vs volc.seedasr.auc vs volc.bigasr.auc).
  6. Assuming Flash ASR supports emotion detection — it does not.
  7. SAMI/MusicTagging with TTS credentials → 40200002.

Runtime & publish

  1. Scripts path: use $SKILL_DIR/scripts/, not writing-repo scripts/.
  2. Podcast/ASR need Hermes venv Python (websockets).
  3. Regenerating good audio only for provenance without being asked.
  4. Claiming deploy before site has both MP3 + Markdown link and CF Pages actually succeeded (CI green ≠ Pages deployed; 25 MiB trap).
  5. Expecting bundled scripts to read DOUBAO_API_KEY already — they still use legacy App ID / Access Token until migrated.

Verification Checklist

  • Correct product chosen (TTS vs Podcast vs ASR vs Voice Minutes); for minutes also run the reference's completion checks
  • Env present: prefer DOUBAO_API_KEY (or alias); legacy App ID / Access Token if using bundled scripts (<set> check)
  • Cleaned /tmp text audited — no YAML/HTML/citations/References
  • Voice / resource ID matches granted package
  • Every MP3: non-trivial size, ffprobe duration plausible, each file < 25 MiB
  • Article Markdown has intended audio link only
  • Podcast: correct message_type, event 150 not followed by silent hang
  • ASR: status 20000000; verbatim uses enable_ddc: false
  • Provider name visible if ElevenLabs fallback used
  • After push: live URL or CF Pages deployment status checked if 404

Scripts & local references

SKILL_DIR="$HOME/.hermes/profiles/writing/skills/media/doubao-tts"
VENV_PY="/home/ubuntu/.hermes/hermes-agent/venv/bin/python3"
PathRole
scripts/strip-for-tts.pyMD → speakable plain text
scripts/tts-generate.pyV1 chunked TTS → 2-part MP3 (legacy App ID / token)
scripts/podcast-generate.pyDual-speaker podcast WS (legacy headers)
scripts/extract-transcript.pyPodcast NLP-only transcript JSON
scripts/asr-transcribe.pyFlash ASR → subtitle JSON (legacy headers)
references/doubao-minutes.mdSeparate-recording native minutes, Chinese-only parameters, source delivery and safe recovery
references/podcast-api.mdPodcast API + Liz defaults
references/podcast-session-learnings.mdProtocol/quota/venv traps
references/tts-streaming-v3.mdV3/TTS 2.0 streaming matrix
references/volcengine-audio-ecosystem.mdSAMI / emotion / product boundaries
references/cf-pages-size-limit.md25 MiB diagnostic
references/lizliz.xyz-podcast-page.mdSite podcast publish
references/2026-06-17-prigogine-audio.mdHistorical session notes

Split from doubao-elevenlabs-tts. Fallback skill: elevenlabs-tts.


References / 参考文献

Console & onboarding

TTS

ASR

Podcast


Change log

2026-10-26 → v1.3.0

  • Added the established separate-recording Voice Minutes playbook and entry routing; existing TTS/Podcast/Flash code paths unchanged.
  • Made Chinese-only useful features, billing-versus-feature semantics, bounded source delivery and query-only recovery explicit.
  • Kept private recordings, transcripts, credentials and per-run receipts outside the reusable skill.

2026-07-30 nuance → v1.2.0

  • Added Onboarding for new console: top up → single API Key → one key for TTS/ASR/Podcast; prefer new console over old.
  • Promoted canonical DOUBAO_API_KEY (DOUBAO_SPEECH_API_KEY / DOUBAO_TTS2_API_KEY aliases); moved App ID / Access Token under Legacy auth.
  • Overview: 豆包语音 framed as top-tier Chinese speech AI.
  • Replaced bare doc bookmarks with annotated References / 参考文献; linked console + product overview + API pages inline where cited.
  • Documented new-console header shapes alongside legacy script headers; noted scripts not yet migrated off legacy env vars.
  • Pitfalls/checklist updated for single-key vs legacy mismatch.

2026-07-30 audit → v1.1.0

  • Restructured to Hermes best-practice shape: Overview, When to Use (+ don'ts), product sections, organized Pitfalls, Verification Checklist.
  • Completed frontmatter: version, author, license, tags, related_skills; description now starts with Use when.
  • Verified V1/Flash/Standard/Podcast endpoints against official docs; confirmed Bearer; and Flash resource volc.bigasr.auc_turbo.
  • Added V3 streaming matrix (bidirectional / unidirectional WS / HTTP Chunked / SSE) + references/tts-streaming-v3.md.
  • Corrected emotion detection: Standard/streaming only — not Flash ASR.
  • Documented new vs old console auth (X-Api-Key alone vs App-Key + Access-Key).
  • Podcast: noted strict_audit, aigc_metadata, TTS/ICL speakers + speaker_additions (official 2026-03/05 updates).
  • Noted V1 listed under historical docs but remains production path; official 1024-byte small-model limit vs observed ~2k-char chunk practice.
  • Flagged QuotaMonitoring/UsageMonitoring OpenAPI existence; adjacent products (async long-text, S2S, 同传, 妙记, ICL).
  • Script paths confirmed under media/doubao-tts; venv path documented; strip script aligned to multi-name References cut.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.