Skill v1.0.0
currentLLM-judged scan90/100version: "1.0.0" name: tts-from-script description: Use when the user has a narration script (script.json) and needs voiceover audio plus per-line timing data — synthesizes each line with edge-tts, probes durations, and writes timing.json + a merged narration.wav. Triggers on "做配音 / TTS / 文案配音 / 生成口播". Skip when the user already has their own narration audio (then use align-narration instead, planned for v0.4).
tts-from-script
What this does
Turns a script.json (see shared/schemas/script.schema.json) into:
<out>/tts/<id>.mp3— one MP3 per line, id =<section_id>_<line_idx:02><out>/timing.json— Timing data (per-linestart/end/duration, plustotal_duration)<out>/narration.wav— single merged audio track with line / section silences inserted
The Timing JSON is the contract every downstream skill reads.
When to use
Trigger when the user:
- has finished writing the narration and wants voiceover
- says "make TTS / 配音 / 口播 / 生成 narration"
- needs a
timing.jsonto feed intonarration-cutor futureburn-subtitles-cn
Do NOT use when:
- the user already has their own recorded voiceover — that path is
align-narration(v0.4, not yet built) - the user only wants to test a voice — point them at
edge-tts --list-voicesdirectly
How to call
vlog-cut-tts --script /path/to/script.json --out /path/to/project_dir
Optional:
--gap-line 0.25— override per-line silence--gap-section 0.6— override per-section silence
Defaults come from the script file (gap_line_sec, gap_section_sec), then fall back to 0.25 / 0.6.
Inputs (script.json)
{"voice": "zh-CN-XiaoyiNeural","rate": "-5%","gap_line_sec": 0.25,"gap_section_sec": 0.6,"sections": [{ "id": "intro", "title": "引子", "lines": ["第一句。", "第二句。"] },{ "id": "body", "title": "正片", "lines": ["第三句。"] }]}
Outputs
<out>/├── tts/│ ├── intro_00.mp3│ ├── intro_01.mp3│ └── body_00.mp3├── timing.json└── narration.wav
timing.json matches shared/schemas/timing.schema.json. Each line carries start/end measured against the merged narration, so downstream tools can align cuts without re-probing.
Checkpoint (when called from vlog-cut-pipeline)
After this skill returns, stop and ask the user to listen to `narration.wav`. Common reasons to re-run:
- voice / rate sounds wrong → edit
script.json, rerun - a line has a wrong word or weird pronunciation → edit that line's text, rerun (cached MP3s only re-synth for changed lines if the file is missing — to force a re-synth, delete that one MP3)
Mark state.checkpoints.narration_approved = true before continuing.
Idempotency
If an MP3 already exists for a given line id, it is reused (no re-synth). Delete the file to force regeneration. timing.json and narration.wav are always rewritten.
Dependencies
edge-tts(Python, listed inpyproject.toml)ffmpeg/ffprobeon PATH (used to probe durations and build the merged WAV)