$npx -y skills add calesthio/OpenMontage --skill doubao-ttsGenerate Mandarin and multilingual narration with Volcengine Doubao Speech 2.0. Use when creating Chinese voiceovers, when the user prefers Doubao/Volcengine/火山引擎/豆包 TTS, or when narration needs character-level timestamp metadata for subtitles.
| 1 | # Doubao TTS |
| 2 | |
| 3 | Requires `DOUBAO_SPEECH_API_KEY` in `.env`. |
| 4 | Set `DOUBAO_SPEECH_VOICE_TYPE` for the default voice, or pass `voice_id` to the tool. |
| 5 | |
| 6 | ## Current API |
| 7 | |
| 8 | Use the new-console API key flow: |
| 9 | |
| 10 | ```text |
| 11 | X-Api-Key: ${DOUBAO_SPEECH_API_KEY} |
| 12 | X-Api-Resource-Id: seed-tts-2.0 |
| 13 | ``` |
| 14 | |
| 15 | Do not use `X-Api-App-Id` and `X-Api-Access-Key` with a new-console API Key. If the API returns `load grant: requested grant not found`, the key type or auth header is probably wrong. |
| 16 | |
| 17 | For long-form video narration, prefer the async endpoint: |
| 18 | |
| 19 | ```text |
| 20 | POST https://openspeech.bytedance.com/api/v3/tts/submit |
| 21 | POST https://openspeech.bytedance.com/api/v3/tts/query |
| 22 | ``` |
| 23 | |
| 24 | This returns `audio_url` plus `sentences[].words[]` timing metadata that can be used to build subtitles. |
| 25 | |
| 26 | ## OpenMontage Usage |
| 27 | |
| 28 | Generate with the TTS selector: |
| 29 | |
| 30 | ```python |
| 31 | from tools.audio.tts_selector import TTSSelector |
| 32 | |
| 33 | result = TTSSelector().execute({ |
| 34 | "preferred_provider": "doubao", |
| 35 | "text": "如果 AI 真的会改变未来,普通人到底该怎么参与?", |
| 36 | "voice_id": "zh_female_vv_uranus_bigtts", |
| 37 | "output_path": "projects/my-video/assets/audio/narration.mp3", |
| 38 | "speech_rate": 0, |
| 39 | "enable_timestamp": True, |
| 40 | }) |
| 41 | ``` |
| 42 | |
| 43 | Or call the provider directly: |
| 44 | |
| 45 | ```python |
| 46 | from tools.audio.doubao_tts import DoubaoTTS |
| 47 | |
| 48 | result = DoubaoTTS().execute({ |
| 49 | "text": "短样本试听文本。", |
| 50 | "voice_id": "zh_female_vv_uranus_bigtts", |
| 51 | "output_path": "projects/my-video/assets/audio/doubao_sample.mp3", |
| 52 | }) |
| 53 | ``` |
| 54 | |
| 55 | The provider writes: |
| 56 | |
| 57 | - `output_path`: downloaded audio file |
| 58 | - `metadata_path`: full query response JSON, defaulting to `<output_path>.json` |
| 59 | |
| 60 | ## Recommended Workflow |
| 61 | |
| 62 | 1. Generate a 10-15 second sample before a full paid narration. |
| 63 | 2. Ask the user to approve voice naturalness, accent, and speed. |
| 64 | 3. Generate the full narration only after approval. |
| 65 | 4. Keep the query JSON. It is the source of truth for subtitle timing. |
| 66 | 5. Build captions from `sentences[].words[]`, not from estimated text length. |
| 67 | 6. Group captions by Chinese semantic phrases before applying timestamps. Do not split only by fixed character count; it can break phrases like "在不押单个公司的情况下" or "可能会被慢慢稀释" and hurt comprehension. |
| 68 | 7. Let the video duration follow the approved voice rhythm unless the user explicitly asks to match a prior runtime. |
| 69 | |
| 70 | ## Parameters |
| 71 | |
| 72 | - `voice_id`: Doubao `speaker` / voice type. Defaults to `DOUBAO_SPEECH_VOICE_TYPE`. |
| 73 | - `resource_id`: use `seed-tts-2.0` for Doubao Speech 2.0 voices. |
| 74 | - `speech_rate`: `0` is normal, `100` is 2x, `-50` is 0.5x. |
| 75 | - `sample_rate`: default `24000`. |
| 76 | - `enable_timestamp`: default `true`. |
| 77 | - `return_usage`: default `true`, requests usage metadata when available. |
| 78 | |
| 79 | Do not pass `additions.explicit_language` by default. Some endpoint/key combinations reject `zh-cn` with `unsupported additions explicit language zh-cn`. |
| 80 | |
| 81 | For calm Mandarin explainers, start with `speech_rate: 0`. If the result is too long for the approved format, make a short comparison sample with `speech_rate: 25` or `50` before regenerating the full narration. Do not speed up only to match a previous provider's duration if the user prefers Doubao's natural pace. |
| 82 | |
| 83 | ## Troubleshooting |
| 84 | |
| 85 | - `load grant: requested grant not found`: wrong key type or wrong auth header. Use `X-Api-Key` for new-console API Keys. |
| 86 | - `speaker permission denied`: voice id is wrong or not authorized for the selected resource. |
| 87 | - `quota exceeded`: quota, lifetime characters, or concurrency exceeded. |
| 88 | - Missing timestamps: verify `enable_timestamp: true`, keep the query JSON, and confirm the selected endpoint returned `sentences`. |
| 89 | |
| 90 | ## Safety |
| 91 | |
| 92 | Never print or write the API key to logs, metadata, patches, or project artifacts. `.env.example` should contain only empty variable names. |