歌詞影片標準流水線
一套已經驗證過的固定風格。使用者只需要給音訊檔案和歌手名字,其餘全部按本標準執行,不要重新設計視覺。 官方歌詞是可選項:給了走 3A 快路徑(文字零猜測),不給就走 3B 重建路徑,兩條路的時間軸都必須是實測。
輸入 / 產出
| 輸入 | 說明 |
|---|---|
| 音訊 | 必需。任意 MP3/WAV/FLAC,時長不限 |
| 歌手名 | 必需。用於片頭、常駐角標、片尾署名 |
| 官方歌詞(可選) | 使用者手頭有官方歌詞時優先採用:文字零猜測,時間軸仍全部走實測重解(見 3A)。不給則用 Whisper 重建(3B) |
| 歌名(可選) | 預設取檔名;Artist - Title.mp3 會自動去掉歌手前綴 |
| 主題句(可選) | 片頭標題下的一行中文,預設不顯示 |
產出:<project>/renders/video.mp4 + renders/contact-sheet.jpg + transcript.json + NOTES.md。
固定規格(不可擅自更改)
- 豎屏 1080 × 1920,30 fps,總時長 等於音訊實際時長(不裁切、不拉伸、不變速)。
- 音訊用原始檔案,渲染時由框架統一增益(
data-volume="0.9")。 - 背景:純黑到極深藍紫,兩組錯位光斑緩慢交叉淡入;不使用全螢幕 CSS 濾鏡(會留分塊接縫)。
- 主體:只有一個透明玻璃體,8 種圓角幾何輪廓(球/橫橢圓/豎橢圓/圓角矩形/菱形/三角/五邊形/六邊形),撞螢幕邊緣時沿法線壓縮 11% → 0.94 s 內變形為另一種輪廓 → 反彈繼續飄移。整曲單時間軸,不在歌詞切換時重置。
- 底部:小動物樂隊(貓/熊/企鵝/狐狸)4.5417 s 無縫循環,貼底 1080×526,層級在背景光斑之上、玻璃體之下,
mix-blend-mode: screen。 - 字幕:整塊以畫面垂直中心 y≈960 為光學中心;英文/原文在上(Inter,字號按行寬自適應),中文在下(宋體 SimSun,暖棕
#DDA97D),同組淡入淡出。 - 署名統一用歌手名,畫面裡不出現任何 VERSE / CHORUS / BRIDGE 之類段落標籤。
細節參數、顏色、字號、坑位見 references/style-spec.md。
流程
設 HF = HyperFrames 安裝根目錄(預設 G:\hyperframes),
PY = 帶 faster-whisper 的 Python(預設 C:\Users\Admin\.workbuddy-ai\binaries\python\envs\hf\Scripts\python.exe),
SK = 本 skill 目錄。
1. 建專案
"$PY" "$SK/scripts/new_project.py" "<音訊路徑>" "<歌手名>" [--title "歌名"] [--tagline "一行中文"] [--root G:/hyperframes/videos]
輸出專案絕對路徑,務必記下。它會:建唯一目錄 → 複製音訊 → 轉 16 kHz 單聲道 WAV → 跑官方
analyze-beatgrid.py 生成 audiomap.json → 複製樂隊雪碧圖與 GSAP → 寫 project.json。
絕不覆蓋已有專案目錄;修改已交付作品必須新建專案。
2. 轉寫
"$PY" "$SK/scripts/transcribe.py" "<project>" --model medium.en --lang en
CPU int8 跑 3–4 分鐘的歌約 3–6 分鐘。非英語歌把 --lang 換成對應語言、--model 去掉 .en。
產出 whisper_raw.json(段 + 詞級時間戳)。
混語言歌(英語+日語、英語+韓語等)不要用 transcribe.py:--lang 會鎖定一種語言,
另一種語言會被強行聽寫成第一種語言 —— 結果讀起來通順但全是錯的,比解不出來更危險。
改用逐窗自動判語種:
"$PY" "$SK/scripts/transcribe_mixed.py" "<project>" --model "C:/Users/Admin/.cache/whisper-manual/large-v3-turbo"
它按 14 s 視窗 / 10 s 步進解碼,每窗自己判語種,只保留視窗核心的詞(重疊區丟棄,不會重複),
列印語言地圖並寫 whisper_mixed.json。先看語言地圖:語種翻轉的位置通常就是段落邊界。
注意 .en 模型(medium.en / small.en)是純英語模型,物理上無法輸出日語,混語言歌必須換多語言模型。
走 3A(有官方歌詞)時本步可選:時間軸以提示詞重解為準,但混語言歌仍建議先跑一遍 transcribe_mixed.py
看語言地圖,用於確定每窗該用 --lang en 還是 --lang ja。
3. 寫歌詞來源檔案(這一步必須自己做)
先判斷走哪條路徑,再寫 <project>/lyrics_source.json。
3A 使用者提供了官方歌詞(首選路徑)
- 文字一行不改地採用官方歌詞:
en槽即官方原文(英文句放英文,日文句放日語,漢字/假名照寫),zh逐句翻譯。 - 時間軸不走全曲轉寫:用官方歌詞作
initial_prompt分區重解拿詞級時間戳(做法見 3.5),每行寫顯式start/end,align_lyrics.py會走 manual 通道逐行錨定。 - 官方歌詞與複解聽到的不一致 → 一律按官方採用,把差異列進 NOTES.md 請使用者確認。常見三類:標準詞形 vs 筆誤(不甲斐ない / 不甲埋ない)、發音相近詞(束の間の / 明日の間の)、清輔音誤聽(smiling / falling)。
- 官方歌詞裡一口氣唱完、拆開每行不足 1 秒的兩行 → 字幕合併為一行顯示(文字未改、僅並排),合併對照表寫進 NOTES.md。
- 官方歌詞中沒有的擬聲/即興段("Yeah,"、哼唱、口哨)→ 不配字幕,不要自己編。
- 結構照此寫:
{
"audio": "Artist - Title.mp3",
"models": ["large-v3-turbo — prompted window re-scans, official lyrics as initial_prompt"],
"lines": [
{"en": "Oh my god, they're coming again", "zh": "哦天哪,他們又來了", "start": 6.36, "end": 9.10, "lang": "en", "conf": "high"}
]
}
3B 沒有官方歌詞(重建路徑)
讀 whisper_raw.json(或混語言歌的 whisper_mixed.json)寫出歌詞來源:
{
"audio": "Artist - Title.mp3",
"models": ["faster-whisper medium.en — full track, word timestamps"],
"lines": [
{"en": "Sometimes I lay under the moon", "zh": "有時我躺臥在月光之下"},
{"en": "And thank God I'm breathing", "zh": "感謝上天讓我仍在呼吸"}
]
}
兩條路徑共同的要求:
- 行 = 實際演唱的一句,按官方斷句;Whisper 合併過長的句子要拆開。
- 英文拼寫按官方歌詞校對(
'Cause/I've等保留撇號),不要照抄 Whisper 的錯字。 - 中文逐句翻譯,語氣與歌曲一致,不要漏句、不要合併、不要佔位文字。
- 重複的副歌要逐次寫出(不要用「同上」)。
- 如果某句人聲被伴奏蓋住、自動對齊明顯偏移,給它加顯式時間(聽完音訊再填):
{"en": "...", "zh": "...", "start": 13.22, "end": 16.80}。 - 中文歌/純音樂:中文歌把
en填原文、zh留空字串,畫面只顯示一行;純音樂不適用本 skill。 - 混語言歌:
en欄位放該句實際語言的原文(英文句放英文,日文句放日語,漢字/假名照寫),zh放中文翻譯。畫面本來就是「原文 + 中文」兩行,混排不會破壞版式; 範本的英文行已帶Yu Gothic UI / Yu Gothic / Meiryo兜底,假名和漢字能正常出字。
3.5 提示詞重解:時間軸精度的核心手段
全曲轉寫對快歌、混唱、快嘴句普遍不準。用已知歌詞作 initial_prompt 分區重解是精度上限最高的手段——
提示詞品質直接決定複解精度:官方歌詞 > 猜的歌詞 > 無提示詞。可寫進 rescan_all.sh 批次跑完整首:
"$PY" "$SK/scripts/rescan.py" "<project>" --from 6.0 --to 20.0 \
--model "C:/Users/Admin/.cache/whisper-manual/large-v3-turbo" \
--lang en --prompt "<該視窗的官方歌詞原文>"
要點:
- 全曲切成 20–26 s 視窗、窗間重疊約 0.5 s,逐窗重解;
large-v3-turboCPU int8 單窗約 5–10 s。 - 混語言歌每窗 en/ja 雙路各解一遍:兩路一致的詞級時間才採用,只在一路出現的詞用另一路複核。
- 搶拍/起點不明的句子加 2 s 窄窗補鎖(
--from 37.2 --to 39.2只鎖一句的起點);分區窗起點容易被前一句尾音帶偏。 - 幻覺處理:複解偶發把同一整句重複輸出 15+ 次 → 該窗作廢,換另一語言通道或縮小視窗重解,只取乾淨的單次時間戳,別把幻覺寫進歌詞來源。
- 每次重解儲存
rescan_<from>-<to>.json並列印視窗內每個詞的起止。這是二次解碼,不是估算;數字直接寫進lyrics_source.json的start/end。 - 被伴奏蓋住、處理成
ooh、合併成一大塊、重複句被吞掉的段落,同樣先用本手段再寫覆蓋值;換模型(small.en/medium.en)也有效。
4. 對齊 + 生成
"$PY" "$SK/scripts/align_lyrics.py" "<project>"
"$PY" "$SK/scripts/motion.py" "<project>"
"$PY" "$SK/scripts/gen_storyboard.py" "<project>"
"$PY" "$SK/scripts/build_frame.py" "<project>"
"$PY" "$SK/scripts/make_index.py" "<project>"
align_lyrics.py 會列印逐行時間表,並做兩道硬檢查:
- 開頭/結尾有句子完全對不上 → 直接報錯退出,並列出是哪幾句(不會用猜的時間糊過去)。
- 中間有句子對不上、或兩句起點相同、或某句被壓縮到 0.5 s 以下 → 列印
REVIEW並退出碼 2。
出現這兩種情況就回到 3.5 步補覆蓋值,直到輸出 OK: every line anchored to a real sung timestamp。
不要跳過這一步去渲染。3A 路徑的行全部帶顯式 start/end(manual 通道),應全部錨定、0 gap-filled;
3B 路徑靠詞匹配,對不上的行按 3.5 補時間。
motion.py 的隨機種子由「歌手名+歌名」決定 —— 同一首歌每次重跑路徑完全一致,不同歌不同路徑。
5. 校驗
cd "<project>"
node "$HF/packages/cli/bin/hyperframes.mjs" check .
node "$HF/packages/cli/bin/hyperframes.mjs" snapshot . --at "3,20,60,120" --no-end -o build/shots
必須做到:lint / runtime / layout / motion 0 error,contrast 全部通過 WCAG AA。
然後實際看截圖:玻璃體是否完整、歌詞是否居中、樂隊是否在底部、有沒有多餘的泡泡或段落標籤。
composition_file_too_large 是單幀檔案超過 300 行的風格提示,可接受(單時間軸設計必然如此)。
6. 渲染 + 驗收
node "$HF/packages/cli/bin/hyperframes.mjs" render . --skill=music-to-video -q delivery -o renders/video.mp4 --fps 30
"$PY" "$SK/scripts/verify.py" "<project>"
verify.py 會核對解析度/幀率/時長偏差(超過一幀即報錯)並生成聯繫表。必須看聯繫表,
確認開頭、主歌、副歌、重複段、結尾都有畫面,字幕沒有空檔或錯位。
最後寫 NOTES.md(規格、時間軸來源、復現命令、校驗記錄),把成片和聯繫表交付給使用者。
硬性紀律
- 不得用 BPM/節拍網格推算歌詞時間;時間戳只能來自 Whisper 實測(含提示詞重解)或人工聽音覆蓋。
- 使用者提供的官方歌詞優先於任何模型重建結果;兩者衝突時按官方採用,並把差異寫進 NOTES.md 請使用者確認。
- 不得因為「看起來更好」而改解析度、幀率、時長、署名或字幕位置。
- 不得在未驗證的情況下宣稱音畫同步;每首歌都要抽幀看。
- 素材缺失、工具不可用、規格衝突 → 明確報告,不用估算資料冒充結果。
- 已交付專案與其原始檔視為唯讀;改版必須新建目錄。
環境依賴
- HyperFrames:
node <HF>/packages/cli/bin/hyperframes.mjs(含skills/music-to-video/scripts/analyze-beatgrid.py)。 - Python:
faster-whisper、librosa、soundfile、numpy、scipy、pillow。 缺失時python -m venv <env> && <env>/Scripts/pip install faster-whisper librosa soundfile numpy scipy pillow。 - Whisper 模型:直接傳模型名會自動下載;也可指向本機目錄(本機常用
C:\Users\Admin\.cache\whisper-manual\medium.en;提示詞重解首選C:\Users\Admin\.cache\whisper-manual\large-v3-turbo,CPU int8 整曲約 48 s、單窗 5–10 s)。 - ffmpeg / ffprobe 需在 PATH。
已知坑
- 不要用
<video>做樂隊圖層:本機hyperframes render會在 Windows 上把提取幀目錄連結進編譯目錄後 讀取失敗(ENOENT ... __hyperframes_video_frames/*/frame_00001.jpg)。用雪碧圖。 - 全螢幕 CSS
filter: hue-rotate()會在渲染裡留下豎向接縫,改用兩層光斑交叉淡入。 - 帶
data-composition-id的範本 HTML 不能放專案根目錄(會觸發multiple_root_compositions),放build/。 - 中文字型必須顯式
@font-face宣告local("SimSun"),否則 lint 報font_family_without_font_face。 - 複解幻覺:某幾窗會把同一整句重複輸出 15+ 次(如「永遠の行方はどこにある?」×15)→ 該窗作廢, 換交叉的 en 通道或縮窗重解,別把幻覺時間戳寫進歌詞來源。
- 官方歌詞 vs 複解不一致:按官方採用並在 NOTES.md 列對照表請使用者確認,別自作主張改官方文字。
- 快嘴合併行:官方歌詞裡一口氣唱完、拆開不足 1 秒的兩行,字幕合併為一行顯示(文字不改,僅並排), 合併對照表寫進 NOTES.md。
- headless 字型載入失敗(抽幀時 Yu Gothic UI 報 FAILED)不必緊張:
src: local()的字型系統裝了瀏覽器一般能找到, 下一順位字型也會兜底,先看截圖再決定要不要處理。