歌詞動画標準パイプライン
検証済みの固定スタイルです。ユーザーはオーディオファイルとアーティスト名のみを提供すればよく、残りはすべて本標準に従って実行し、ビジュアルを再設計しないでください。 公式歌詞はオプションです:提供された場合は 3A 高速パス(テキストの推測なし)を、提供されない場合は 3B 再構築パスを実行します。両方のパスでタイムスタンプは実測値である必要があります。
入力 / 出力
| 入力 | 説明 |
|---|---|
| オーディオ | 必須。任意の MP3/WAV/FLAC、長さ制限なし |
| アーティスト名 | 必須。タイトルカード、常駐ウォーターマーク、エンドクレジットに使用 |
| 公式歌詞(オプション) | ユーザーが公式歌詞を持っている場合、優先的に使用:テキストの推測なし、タイムスタンプはすべて実測ベースで再解決(3A 参照)。ない場合は Whisper で再構築(3B) |
| 曲名(オプション) | デフォルトはファイル名。Artist - Title.mp3 からアーティストプレフィックスが自動削除されます |
| テーマ文(オプション) | タイトルカードのタイトル下に表示される1行の中国語文。デフォルトでは非表示 |
出力:<project>/renders/video.mp4 + renders/contact-sheet.jpg + transcript.json + NOTES.md。
固定仕様(変更不可)
- 縦型 1080 × 1920、30 fps、総時間はオーディオの実際の長さと等しい(切り取り、伸縮、速度変更なし)。
- オーディオは元のファイルを使用し、レンダリング時にフレームワークで一律にゲイン調整(
data-volume="0.9")。 - 背景:完全な黒から非常に深い青紫へ、2 つのグループのオフセットされた光のスポットがゆっくりとクロスフェード。全画面 CSS フィルターは使用しない(継ぎ目が残るため)。
- メイン要素:1 つだけの透明ガラス体、8 種類の角丸幾何学プロファイル(球/横楕円/縦楕円/角丸四角形/菱形/三角形/五角形/六角形)。画面端に衝突すると法線方向に 11% 圧縮 → 0.94 秒以内に別のプロファイルへ変形 → 跳ね返って漂い続ける。曲全体で単一のタイムライン、歌詞の切り替え時にリセットしない。
- 下部:小さな動物バンド(猫/熊/ペンギン/キツネ)4.5417 秒のシームレスループ。下部に配置、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 = このスキルディレクトリ。
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 が 1 つの言語に固定され、別の言語が最初の言語として誤って書き起こされます。結果は読みやすいですが完全に間違っており、解釈できないよりも危険です。代わりにウィンドウ単位の自動言語判別を使用:
"$PY" "$SK/scripts/transcribe_mixed.py" "<project>" --model "C:/Users/Admin/.cache/whisper-manual/large-v3-turbo"
14 秒ウィンドウ / 10 秒ステップでデコードし、各ウィンドウが自身の言語を判別、ウィンドウのコア部分の単語のみを保持(重複領域は破棄、重複なし)、言語マップを表示し whisper_mixed.json に書き込みます。まず言語マップを確認:言語が切り替わる位置が通常、セクションの境界です。.en モデル(medium.en / small.en)は純粋な英語モデルであり、物理的に日本語を出力できないため、混言語曲は多言語モデルに変更する必要があります。
3A(公式歌詞あり)パスではこのステップはオプションです:タイムスタンプはプロンプトベースの再解決に依存しますが、混言語曲では transcribe_mixed.py を先に実行して言語マップを確認し、各ウィンドウで --lang en と --lang ja のどちらを使用するかを決定することをお勧めします。
3. 歌詞ソースファイルの作成(このステップは自分で行う必要があります)
最初にどのパスを使用するかを判断し、次に <project>/lyrics_source.json を作成します。
3A ユーザーが公式歌詞を提供(推奨パス)
- 公式歌詞を1行も変更せずに使用:
enスロットは公式の原文(英文は英語、日文は日本語、漢字/仮名はそのまま)、zhは逐文翻訳。 - タイムラインは全曲書き起こしを使用しない:公式歌詞を
initial_promptとしてセクションごとに再解決し、ワードレベルのタイムスタンプを取得(方法は 3.5 参照)。各行に明示的なstart/endを記述し、align_lyrics.pyはマニュアルチャネルを介して行ごとにアンカーします。 - 公式歌詞と再解決結果が一致しない場合 → 一律に公式歌詞を採用し、差異を NOTES.md にリストアップしてユーザーに確認を求める。一般的な3つのタイプ:標準語形 vs 書き間違い(不甲斐ない / 不甲埋ない)、発音が似ている単語(束の間の / 明日の間の)、無声子音の誤認識(smiling / falling)。
- 公式歌詞で一息で歌われているが、分割された各行が1秒未満の2行の場合 → 字幕は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": "呼吸していることに神に感謝する"}
]
}
両方のパスに共通する要件:
- 行 = 実際に歌われた1つのフレーズ、公式の文節に従う。Whisper がマージしすぎた長い文は分割する。
- 英語のスペルは公式歌詞に従って校正する(
'Cause/I'veなどはアポストロフィを保持)、Whisper の誤字をそのままコピーしない。 - 中国語は逐文翻訳し、曲の雰囲気と一致させる。文を省略しない、マージしない、プレースホルダーテキストを使用しない。
- 繰り返されるコーラスは毎回記述する(「同上」は使用しない)。
- あるフレーズのボーカルが伴奏に埋もれて自動アライメントが明らかにずれている場合は、明示的な時間を与える(オーディオを聞いてから記入):
{"en": "...", "zh": "...", "start": 13.22, "end": 16.80}。 - 中国語の曲 / インストゥルメンタル:中国語の曲は
enに原文を入れ、zhは空文字列にする。画面には1行のみ表示。インストゥルメンタルにはこのスキルは適用されない。 - 混言語曲:
enスロットにはその行の実際の言語の原文を入れる(英文は英語、日文は日本語、漢字/仮名はそのまま)、zhには中国語訳を入れる。画面は元々「原文 + 中国語」の2行であるため、混在してもレイアウトは崩れない。テンプレートの英語行には既に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 秒のウィンドウに分割、ウィンドウ間の重なり約 0.5 秒、ウィンドウごとに再解決。
large-v3-turboCPU int8 で1ウィンドウあたり約 5〜10 秒。 - 混言語曲では各ウィンドウを en/ja の両方で1回ずつ解決:両方のパスで一致したワードレベルのタイムスタンプのみを採用し、片方のパスにしか現れない単語はもう一方のパスで再確認。
- 早取りや開始点が不明瞭な文には、2 秒の狭いウィンドウを追加してロックをかける(
--from 37.2 --to 39.2で1文の開始点のみをロック)。セクションウィンドウの開始点は前の文の末尾の音に引きずられやすい。 - 幻覚処理:再解決では、同じ文全体が 15 回以上繰り返し出力されることがある → そのウィンドウは破棄し、別の言語チャネルに切り替えるか、ウィンドウを狭めて再解決し、クリーンな単一のタイムスタンプだけを保持する。幻覚タイムスタンプを歌詞ソースに書き込まないこと。
- 各再解決で
rescan_<from>-<to>.jsonを保存し、ウィンドウ内の各単語の開始と終了を表示する。これは2回目のデコードであり、推定ではない。数値を直接lyrics_source.jsonのstart/endに書き込む。 - 伴奏に埋もれている、
oohとして処理されている、1つの大きなブロックにマージされている、繰り返し文が飲み込まれているセクションも、まずこの手段を使用してから上書き値を記入する。モデルを変更する(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 は行ごとのタイムテーブルを表示し、2 つの厳格なチェックを実行します:
- 開始/終了の文が完全に一致しない場合 → 直接エラーで終了し、該当する文をリストアップする(推測された時間でごまかさない)。
- 途中の文が一致しない、または 2 つの文の開始点が同じ、またはある文が 0.5 秒未満に圧縮されている場合 →
REVIEWを表示し、終了コード 2 で終了する。
これらのいずれかのケースが発生した場合は、ステップ 3.5 に戻って上書き値を追加し、OK: every line anchored to a real sung timestamp が出力されるまで繰り返す。このステップをスキップしてレンダリングしないこと。3A パスの行はすべて明示的な start/end を持ち(マニュアルチャネル)、すべてアンカーされ、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 は解像度/フレームレート/長さのずれをチェックし(1フレームを超えるとエラー)、コンタクトシートを生成します。必ずコンタクトシートを確認し、開始、ヴァース、コーラス、繰り返しセクション、終了のすべてに映像があり、字幕に空白やずれがないことを確認します。
最後に 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 秒、1ウィンドウ 5〜10 秒)。 - ffmpeg / ffprobe が PATH に含まれている必要があります。
既知の問題点
- 動物バンドレイヤーに
<video>を使用しない:このマシンのhyperframes renderは Windows で、抽出されたフレームディレクトリをコンパイルディレクトリにリンクした後、読み取りに失敗します(ENOENT ... __hyperframes_video_frames/*/frame_00001.jpg)。スプライトシートを使用すること。 - 全画面 CSS
filter: hue-rotate()はレンダリング時に縦方向の継ぎ目を残すため、代わりに2層の光のスポットのクロスフェードを使用すること。 data-composition-idを持つテンプレート HTML はプロジェクトルートディレクトリに置かないでください(multiple_root_compositionsをトリガーするため)。build/に置いてください。- 中国語フォントは明示的に
@font-faceでlocal("SimSun")を宣言する必要があります。そうしないと lint がfont_family_without_font_faceを報告します。 - 再解決の幻覚:一部のウィンドウで、同じ文全体が 15 回以上繰り返し出力されることがあります(例:「永遠の行方はどこにある?」×15)→ そのウィンドウは破棄し、交差する en チャネルに切り替えるか、ウィンドウを狭めて再解決し、幻覚タイムスタンプを歌詞ソースに書き込まないこと。
- 公式歌詞と再解決結果の不一致:公式歌詞を採用し、NOTES.md に対照表を列挙してユーザーに確認を求める。公式テキストを自分で変更しないこと。
- 早口のマージ行:公式歌詞で一息に歌われているが、分割された各行が1秒未満の2行の場合、字幕は1行に統合して表示する(テキストは変更せず、単に並べる)。統合対応表を NOTES.md に記述する。
- ヘッドレスフォント読み込み失敗(フレーム抽出時に Yu Gothic UI が FAILED と報告しても)慌てる必要はありません:
src: local()のフォントは、システムにインストールされていればブラウザは通常見つけられ、次のフォールバックフォントも適用されます。まずスクリーンショットを確認してから、対応するかどうかを決定してください。