auto-subtitle — 音視訊自動轉寫出 SubtitleCue
一條命令產出字幕:音視訊檔案輸入,<同名>.cues.json + <同名>.srt 雙產物輸出。資料契約與 video-motion SubtitleCue 逐字對齊:{start, end, text},秒、3 位小數、單行文字(長句已拆分)——subtitles 陣列可直接匯入 video-motion 時間軸。
Step 1 · 確認素材與語種
- mp4 / wav / flac 皆可(PyAV 直接解碼)。解碼報錯 → 先轉碼再餵:
ffmpeg -i in.mp4 -vn -ac 1 -ar 16000 out.wav - 確認語種並傳
--lang:zh(預設)/en等 whisper 語種代碼 - 純音樂/音效素材不用跑:VAD 會濾出空白或極短產物(這是特性非故障)
- 素材有已知文字(口播稿 / 台詞 / 原文)先留存 UTF-8——Step 3 L2 比對的基準,杜絕基準漂移
Step 2 · 執行轉寫
venv 不入庫(284 MB 級建構產物,.gitignore 的 .venv/ 已涵蓋)。本倉庫約定 skill 模板不帶建構產物,與模板不帶 node_modules 同理,所以 venv 建立在倉庫外,一次建立供所有專案共用:
python -m venv "$env:USERPROFILE\.cache\vibe-studio\asr-venv"
& "$env:USERPROFILE\.cache\vibe-studio\asr-venv\Scripts\python.exe" -m pip install -r skills/auto-subtitle/templates/asr/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
cd skills/auto-subtitle/templates/asr
& "$env:USERPROFILE\.cache\vibe-studio\asr-venv\Scripts\python.exe" transcribe.py <輸入.mp4|wav> --outdir <輸出目錄>
- 模型預設
large-v3-turbo(≈1.6GB 首次自動下載,中文品質線);快速驗證可加--model small(≈484MB)。模型快取在~/.cache/huggingface,下載一次全域共用 - 模型下載失敗時設定
HF_ENDPOINT換源:預設官方直連(2026-08 實測可行);備用如$env:HF_ENDPOINT="https://hf-mirror.com"(注意:hub 1.x 下該鏡像存在 308 回源相容問題,優先使用官方) - stdout 一行英文摘要
segments=N cues=M total_audio=... model=... lang=... out=...;exit 0 成功、1 失敗
Step 3 · 三級核查(必做,不可跳過)
L1 程式碼級:JSON 可 json.load;subtitles 是陣列且每筆恰好有 start/end/text 三欄位;start < end 且跨筆單調不減;數值 3 位小數;最後一筆 end ≤ ffprobe 時長 + 1s。SRT 時間戳行符合 HH:MM:SS,mmm --> HH:MM:SS,mmm,序號從 1 連續。
L2 準確性:有已知文字 → difflib.SequenceMatcher 比對(雙方先去除標點與空白正規化),整體相似度 ≥0.85、逐句 ≥0.70(對連續 cue 拼接視窗取 max,涵蓋分割/合併);無已知文字 → 抽聽首 / 中 / 尾三段核對。
L2.5 時間軸(常規檢查):字幕視窗必須對齊詞級語音視窗,句間靜音不得有字幕——審計相鄰 cue 的間隙:句間應出現 >1s 的真實靜音間隙(句內分割 gap=0 屬正常);不得存在 <0.3s 的閃現碎片;第一筆 start 對齊語音起點、最後一筆 end 不吞尾音靜音。腳本內部已使用詞級時間戳(首詞 start / 末詞 end)決定視窗,此步驟是產物級驗證。
L3 結論行:全部通過 = ALL GREEN;有紅項 → 修正分割 / VAD 參數重新執行重新檢查,連續 2 輪紅 → 停止並報告,禁止盲目調整。
Step 4 · 交付
- 報告:
cues.json絕對路徑 + cue 數量 + 音訊時長 + 模型/語種 + 三級核查結論 - video-motion 對接:
subtitles陣列直接貼進 video-motion 專案src/cues.ts的cues.subtitles即可使用,欄位零轉換 - 明確不做(後續站點):說話人分離、詞級時間戳匯出、翻譯、TTS 配音
Step 5 · 複製執行命令留存
交付報告末尾附上完整複製執行命令(輸入路徑 / --lang / --outdir / --model),確保下個會話或他人可精確複現;產物(cues.json / srt)存放於產出區(本倉庫 products/,跨倉庫用專案根目錄 output/)不進入 git,命令即為資產。
邊界與注意事項
- GBK 主控台:腳本 print 全英文;寫檔案一律明確指定
encoding="utf-8",JSON 使用ensure_ascii=False - 分割規則:單筆 >20 字在標點(。!?;,、)處分割,視窗內無標點則硬切且尾段保底 3 字(防止 1 字碎片);<0.3s 碎片合併至前一筆,合併不超過 20 字上限
- 詞級時間戳是字幕視窗的唯一正確來源——段級時間戳會吞掉句間靜音導致字幕提前約一個靜音段落(已修正,請勿退回
word_timestamps=False) - CPU int8 推論:28 秒音訊 ≈1 分鐘內出結果,長音訊按比例估算時間;large-v3-turbo 首次執行含下載,請預留充足逾時時間
- 中文辨識中數字常轉為阿拉伯數字(「兩百毫秒」→「200毫秒」),L2 比對時的正常差異,不算辨識錯誤
交付對接
最終 SRT/cues 與原始音軌來源、模型版本一起歸檔;不要只保留燒錄字幕的 mp4。交付影片時使用 media-qc 檢查字幕視窗與實際時長,準確性仍依已知稿或抽聽核對。預設模型下載與本地推論不取代人工配音。