真实时间戳字幕
Use the final audio stream as the only timing source. Never estimate final subtitle timing from character count, scene duration, TTS segment duration, or fixed delays.
Required workflow
- Finish and concatenate narration first. If the user recorded or merged a video, use that final merged media instead.
- Run
scripts/generate_subtitles.pyagainst the final media and the exact narration script. - Inspect phrase segmentation. Keep English product/model tokens intact,
merge isolated one-word fragments, and place connectors such as
比如说,但是, and只是with the phrase they introduce. - Render captions from
captions.json; exportcaptions.srtfor Bilibili, YouTube, editing software, and archive. - Require
caption-qc.jsonto reportstatus: passbefore final render or delivery. The gate includes alignment, overlap, fragments, connector splits, caption duration, and reading speed. - If ASR fails or alignment coverage is below the gate, stop. A character- count estimate may be used only for an explicitly labeled scratch preview.
Commands
Project with narration_segments.json:
bashpython3 .claude/skills/ra-audio-to-subtitles/scripts/generate_subtitles.py \ <project>/media/final-voiceover.mp3 \ --script <project>/narration_segments.json \ --out-dir <project>/media/captions
Recorded or merged video with a Markdown handoff containing - 口播: lines:
bashpython3 .claude/skills/ra-audio-to-subtitles/scripts/generate_subtitles.py \ <project>/merged.mp4 \ --script <project>/handoff.md \ --out-dir <project>/media/captions
Health check:
bashpython3 .claude/skills/ra-audio-to-subtitles/scripts/generate_subtitles.py --doctor
Offline regression test with an existing Volcengine response:
bashpython3 .claude/skills/ra-audio-to-subtitles/scripts/generate_subtitles.py \ <audio> --script <script> --asr-result <volcengine-result.json> \ --out-dir <output>
Output contract
The output directory must contain:
asr-result.json: raw Volcengine responsecaptions_words.json: word/character timestamps and detected gapscaptions.json: phrase captions consumed by HyperFrames or Remotioncaptions.srtandcaptions.vtt: portable subtitle filescaption-qc.json: alignment coverage and timing validation
Read references/artifact-contract.md before integrating another renderer or delivery checker.
Hard rules
- Transcribe the exact final audio used by the MP4. Do not transcribe an earlier segment, draft voice, or a differently trimmed file.
- Use the original narration text for display and ASR only for timing. This preserves names, English terms, punctuation, and intentional wording.
- Align the original script to ASR tokens before grouping phrases. Do not scale boundaries by total character count.
- Phrase captions remain the default. Word timestamps are the timing substrate, not a requirement to show karaoke-style one-character captions.
- Preserve meaningful spaces inside English names such as
Claude Max; never split an ASCII product/model token across captions. - Reject captions shorter than 0.5 seconds, isolated fragments, split discourse connectors, and reading speeds above 12 units/s. Treat speeds above 9 units/s as a review warning.
- Keep one canonical caption timeline. Scene changes, keyword reveals, and component cues should look up caption text or timestamps from that timeline.
VOLCENGINE_API_KEYcomes from the workspace root.envor the environment. Never print or copy it into an artifact.- Default resource ID is
volc.seedasr.auc; override only withVOLCENGINE_RESOURCE_IDwhen the account uses a different enabled resource. - Final delivery requires alignment coverage at least 0.90 unless a stricter project contract is set. Lower coverage is a failure, not a warning.

