vox-video-director について
vox-video-directorは、トピック、トーク動画、静止画からVox風の紙コラージュ動画を作るスキルです。Bailian CLIとffmpegを使い、構成、ビジュアル生成、アニメーション、編集を案内します。
主な機能
- 01トピックから動画を作るワークフロー
- 02トーク動画の加工と写真モード
- 03ナレーションの計時とビート設計
- 04コラージュポスターの生成とアニメーション
- 05字幕と音声の編集
活用シーン
- 01トピックからナレーション付き解説動画を制作
- 02出演者の演技を保ってトーク動画を加工
- 03商品写真を軸にコラージュ動画を作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ modelstudioai/ skills --skill vox-video-directorインストール後、Claude Code で/vox-video-directorを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlexamples/content-timing.beats.jsonreferences/beat-layer.mdlocal-engine.mdmodels-and-gotchas.mdprompt-guide.mdvoices.mdscripts/aroll_assemble.pyaroll_clips.pyasr_beats.pyassemble.pyatlas_cloud.pyaudio.pyclips.pyconfetti.pycroll_keyframes.pyextract_elements.pykenburns.pykeyframes.pymg_scrapbook.pymotion.pyprovider.pystyle_bakeoff.pystyles.pytext_overlay.pytiming.py詳細
Vox ビデオディレクター
1 行のトピックから、完成した Vox スタイルのペーパークラフトコラージュ動画を作成します。大胆で歯切れのよいナレーション付きの解説・広告動画で、破いた紙のコラージュポスターがビートごとに生き生きと動き出します。ナレーション、任意の音楽、字幕にも対応します。認証済みの Bailian CLI(bl) とローカルの ffmpeg を使用します。
Stav Zilber や rom1trs などのクリエイターによる Vox の解説動画で広まった、現代的なエディトリアル・ペーパークラフトコラージュのスタイルです。手で切り抜いた紙片、破れた縁、テープ、網点、新聞の切り抜き、ビートごとの大胆でフラットな色、大きく切り抜かれた見出しが特徴です。
基本的な考え方(まずこちらをお読みください)
Vox コラージュの見た目とコラージュの動きは、別々の 2 つの工程です。
- 見た目は画像の工程で生まれます。 各ビートは、テキストから画像を生成するモデルで作成する、完成したコラージュ ポスター です。コラージュらしさを生む要素(破れた紙、切り抜き、網点、大胆な色、見出しの文字)はすべて、その画像に含まれます。画像が豊かなコラージュになっていなければ、その後の工程で取り戻すことはできません。
- 動きはその後に加えます。 デフォルトでは、AI 動画モデルがポスター全体に動きを加えます(「動くポスター」方式。シンプルで自動化されています)。ドラマチックな パーツごとの 組み立てには、ポスターをパーツに分割し、ローカルのキーフレームエンジンで動かします(上級者向けの方式)。
すべてはプロンプトにかかっています。画像や動画のプロンプトを書く前に、必ず references/prompt-guide.md を読んでください。そこには「本物の Vox コラージュ」と「動く PowerPoint」を分ける、正確なプロンプトの構成が記載されています。
前提条件(確認を省略しないでください)
bl --version— Bailian CLI 1.14.3 以降が必要です。bl auth status— 未認証の場合は、bl auth login --api-key <key>を実行し、ログインに成功するまで先へ進まないでください。command -v ffmpeg ffprobe— 組み立てに必要です(macOS ではbrew install ffmpeg)。python3 -c "import PIL"— 字幕・ウォーターマークのオーバーレイに必要な Pillow です。
標準ワークフロー(トピック → 動画)
これはデフォルトの、最も自動化された手順です。プロジェクトごとの out/<project>/ にある単一の
beats.json を使い、各段階をそれぞれ 1 つのスクリプトで実行します。
-
トピック → ビートマップ。 まずストーリー層の
references/beat-layer.mdを読んでください。次に、トピックに合う物語のarcを選びます(歴史にはtimeline、広告にはpas/bab、解説にはhow_it_works、変化を描く場合にはman_in_holeなど)。その後、そのarcに沿ってout/<project>/beats.jsonを作成します。ビート 1 では、3 秒以内に視聴者の関心を引いてください。 デフォルトでは、1 ビート = 生成する動画セグメント 1 つ = 1 ショットとします。各セグメントの長さは固定のテンプレートではなく、ナレーションの長さをもとに決めてください。目安は5~10 秒です。python3 scripts/timing.py out/<project> --estimatedを使い、推定時間が 10 秒を超えるナレーションは分割します。60 秒の動画は通常、内容に合わせた 7~10 ビートで構成し、固定の 10 秒ブロックを 6 つ、または固定の 5 秒ショットを 12 個並べるものではありません。隣接するビートではcamera_moveを変え(繰り返さず、見せ場ではstaticを使用)、豊かなelement_motionを記述してください。各ビートにはnarration、title_cn/title_en、scene、bg、feel、hook、およびdurを省略できるshots項目 1 つが必要です。推定時間を含めたこの草案が、最初の必須承認ゲートです。デフォルトのスキーマ例としてexamples/content-timing.beats.jsonを使用してください。 -
ビジュアルスタイルを選びます(ハイブリッド方式 — キーフレームより先に行います)。 すべてのトピックに同じ定番スタイルを使い回さないでください。
references/prompt-guide.md(§5 テーマプリセット)を読み、トピックの時代・文化・トーンに合うテーマプリセット(styles.THEME_PRESETS:american-retro、swiss-modern、punk-zine、soviet-constructivist、wpa-propaganda、70s-groovy、chinese-ink、atomic-age、newsprint-editorial)を3〜4個選ぶか、どれも合わない場合は、プロンプトガイドの要素 (medium/era/palette/type/finish)を組み合わせてカスタムテーマを作成します。言語ではなくトピックに合わせてください(中国の歴史を扱う英語の映画は、中国風に見えるようにします)。テーマには LOOK レイヤー全体(idiom+palette+type+finish+mood+motion)が含まれます。比較テストを行い、ユーザーに見た目で選んでもらいます — AI が提案し、ライブラリが品質の下限を保証し、最終判断は人が行います。選んだスタイルを"theme"に設定します:python3 scripts/style_bakeoff.py out/<project> american-retro,swiss-modern,punk-zine,atomic-age選んだ名前を beats.json の"collage_style"に設定します(keyframes.py が読み込みます)。 -
音声と実測タイミング。
python3 scripts/audio.py out/<project>は、bl speech synthesize+ cosyvoice-v3-flash を使って一貫性のあるナレーターを生成し、 テキストからの推定値を、実測した音声の長さと短い編集用の余白に置き換えます。 新しいセグメントの長さは5〜10秒に制限されます。timing_issuesが空でない場合は、該当するナレーションのビートを分割し、画像や動画に費用をかける前に音声を再生成します。トピックと言語に応じてvoice_idを選びます。references/voices.mdを参照してください。Bailian CLI 1.14.x には音楽生成コマンドがありません。ローカルのbgm_pathを指定するか、音楽なしで組み立ててください。 -
キーフレーム(コラージュの見た目)。
python3 scripts/keyframes.py out/<project>は、bl image generate+ qwen-image-3.0 を使い、見出しテキストを埋め込んだコラージュポスターをビート/ショットごとに1枚生成します。プロンプトはreferences/prompt-guide.mdの5部構成で作成します。アニメーション化する前に、各ポスターが本物のレイヤードコラージュに見えることを確認します — ここでは安価($0.08)に再生成できます。弱い画像のアニメーション化に費用をかけるより、ここで作り直してください。 -
モーション。
python3 scripts/clips.py out/<project>各ポスターをbl video generate+ happyhorse-1.1-i2v でアニメーション化します。独立した軸が2つあります (references/beat-layer.md§3 を参照。自分たちのスタックで検証済みです)。 •camera_move— ショットごとに動きは1つだけです。安全なデフォルト値:{static, push_in, pull_out, pan, tilt, parallax}。大胆な実験的オプション{orbit, dolly_zoom, roll, whip}も 使用可能で、禁止ではありません。フラットなアートが歪むことがあるため、constraints: looseと組み合わせて 再生成 してください。 カスタムのフレーズもそのまま通ります。 •element_motion— 動きの主役となる要素です。AI がシーンに合わせてビートごとに記述します(テンプレートではありません)。複数の要素を動かすなど、豊かな動きにしてください。大胆に表現しましょう。画面を横切って飛ぶ主役の要素(紙の鳥/飛行機/コインなど)は、重要なビートで 時折 インパクトを与えるのに最適ですが、すべてのショットに入れるものではありません(毎フレームに飛ぶものがあると、型どおりに見えます)。motion_style= 振幅calm | punchy | max(テーマによってデフォルトが設定されます)。constraints=strict(デフォルト:欠陥防止機能が有効 — フラットな2D、一方向、変形なし。テキスト主体のすっきりした解説動画に最適)またはloose(モデルに3Dや大胆な動きを試させ、うまくいかないものは再生成します)。見出しテキストが強く保護されるのは、タイトルがあるショットだけです(見出しのない詳細ショットでは自由に大胆な表現ができます)。Bailian のデフォルトはhappyhorse-1.1-i2vです。本番実行の前に、実在人物やブランドの使用が選択したモデルの最新ポリシーに準拠していることを確認してください。 アスペクト比のルーティング(styles.resolve_video_aspect、2つ目の承認ゲート):clips.pyはdoc["aspect"]を、選択したvideo_modelがサポートする比率と照合します。一致する比率があればそれを優先します。Omni は 16:9/9:16 のみ、Kling のリファレンス動画生成は 1:1 にも対応し、Kling の画像から動画生成/動画編集と Seedance は入力/比率パラメーターに従います。一致する比率がない場合は最も近い比率を選びますが、動画の画角を黙って変更するのではなく、停止して確認を求めます(確認後に"aspect_approx_confirmed": trueを設定してください)。1回の実行内ではすべてのクリップで同じ比率が使われるため、完成した動画で比率が混在することはありません。 -
組み立て。
python3 scripts/assemble.py out/<project>ffmpeg で、すべてのショットのフォーマットを統一して連結し、ナレーション1本を音楽の下にダッキングして配置し、ビートごとのタイミングに合わせて字幕を焼き込み、ウォーターマークを追加します。出力先はout/<project>/final.mp4です。 -
確認。 mp4 を直接読むことはできません。フレームを jpg に抽出して確認してください。
ffmpeg -ss <t> -i final.mp4 -vf "scale=640:-1,format=yuvj420p" -frames:v 1 f.jpg
テンポ — 尺はコンテンツに合わせる
- デフォルトでは、セグメントごとにナレーションのビートを1つ、生成クリップを1つ用意します。各セグメントはモデルが安全に扱える 5~10 秒 の範囲に収めてください。
- 生成前にテキストの長さから尺を推定します。TTS の後は、実測した
narration_durを確定値として扱い、約 0.45 秒の編集用余白を加えて、次の 0.5 秒単位に切り上げます。 - 動画 API には次の整数秒を指定します(例:6.5 秒 → 7 秒をリクエスト)。組み立て時に返されたクリップを編集上の正確な尺にトリミングするため、ナレーションが途切れることはありません。
- 短いテキストでも、内容が伝わるように 5 秒を確保します。長いテキストには最大 10 秒を割り当てます。ナレーションと余白の合計が 10 秒を超える場合は、文または節の区切りで分割してください。早口で読んだり、モデルの上限を超えてクリップを黙って引き延ばしたりしないでください。
- 60 秒の動画は通常、長さに変化をつけた 7~10 個のセグメントで構成されます。元の内容が実際に同じ長さのビートで構成されている場合を除き、動画全体で尺を同一にするのは避けてください。
- 1つのビート内で複数のショットを使うのは、編集上の明確な意図がある場合に限ります。従来の複数ショットのプロジェクトも引き続きサポートされますが、新しいコンテンツ主導のプロジェクトでは、ナレーションをビートごとに分割し、生成する各クリップに独立した 5~10 秒のコンテンツ単位を持たせてください。
Aロールモード(トーキングヘッド → コラージュ)
上記の標準的なワークフローは Bロール です。トピックをAI生成のコラージュポスターにし、それをアニメーション化します。Aロールはその逆のケース です。ユーザーはすでに実際に撮影したトーキングヘッド動画(カメラに向かって話すプレゼンター)を持っており、本人のパフォーマンス(顔、唇の動き、ジェスチャー)をそのまま保ちながら、動画自体をコラージュ風にしたいと考えています。ポスターは生成しません。「キーフレーム」となるのはプレゼンター自身の映像です。ゼロから文章を作成するトピックではなく、ユーザーが自分自身またはプレゼンターが話している動画ファイルを渡した場合にAロールを使います。
-
文字起こしと自動セグメント分割。
python3 scripts/asr_beats.py <project_dir> <source.mp4>ソース音声に対してbl speech recognize(fun-asr)を実行し、文末の句読点または自然なポーズの間隔でビートに分割します(Omni/Kling のビデオ編集で1回の呼び出しに設定されている上限10秒を下回るよう、約9.5秒を超えないようにします)。各ビートのstart/end/textを含むbeats.jsonを書き出します。これはBロールのビートマップと同じく、必須の承認ゲートです。内容を確認し、"theme"を設定し(同じ方法でstyle_bakeoff.pyを実行します。ベイクオフのソースにはプレゼンターのセグメントを問題なく使えます)、何かを生成する前に、必要に応じて各ビートに重ねるステッカーやスタンプのアイデアをcontent_beats文字列として入力してください。 -
生成。
python3 scripts/aroll_clips.py <project_dir> [only_ids]ソースから各ビートの時間範囲を切り出してアップロードし、プレゼンターに写真のような紙の切り抜きステッカーの加工を施します。本人の実際の容姿、唇の動き、視線、ジェスチャーはソースのフレームに忠実に保たれ、紙のコラージュになるのはシルエットの輪郭と周囲の世界だけです。デフォルトのモデルはbl video edit経由のhappyhorse-1.0-video-editです(beats.jsonのvideo_model/video_model_fallbackで設定します)。モデルに顔自体の描き直しやハーフトーン加工を指示してはいけません。プロンプトの言い回しにかかわらず拒否されます(強い表現と、和らげた表現の両方を試しましたが、どちらも失敗しました)。clips.pyと同じアスペクト比のルーティング確認ゲートを使います。 -
組み立て。
python3 scripts/aroll_assemble.py <project_dir>生成した各クリップに、対応するビートの元の音声を多重化します(ビデオモデルが生成した音声は使いません)。そのため、どのモデルがビートを処理した場合でもリップシンクが保証されます。各ビートを同じキャンバスサイズに正規化し、結合してfinal.mp4を作成します。
C-roll モード(写真 1 枚 → コラージュ)
3 つ目の入力モダリティである「カットアウトロール」です。A-roll はトークヘッド動画のスタイルを変更し、B-roll はトピックからすべてを生成します。C-roll は 1 枚の静止写真(自撮り写真、アバターカード、商品写真)を使い、その写真をコラージュの世界に組み込みます。被写体は写真そのもののステッカーとして切り抜かれ、描き直されることはありません。各ビートのポスターは画像編集モデルで周囲に生成され、その後、通常のクリップ工程でアニメーション化されます。ユーザーから写真 1 枚とトピックが提供された場合に C-roll を使用します。たとえば、本人の顔を前面に出した個人向け解説動画や、実際の商品写真を中心にしたコラージュ広告などです(2026-07-17 に両方で検証済み)。
-
ビートマップ。 B-roll と同じです(
references/beat-layer.md、承認ゲートも同じ)。加えて、beats.json に C-roll 用のフィールドを設定します。"mode": "croll"、"anchor_photo"、"croll_subject"(portrait|product)、およびsubject_wardrobe(ポートレートの場合。衣装を固定しないとペーパードールの体が変化します)またはsubject_desc(商品用)です。C-roll のポスターには見出しを入れず、テキストはキャプションに配置するため、ショットでは"title": falseに設定します。独立したスクリプトがない場合は、まずナレーションを文字起こし/作成し、音声の ASR タイムスタンプでビートを定義します(A-roll と同じ音声優先で、B-roll のようなテキスト優先ではありません)。 -
アンカー付きキーフレーム。
python3 scripts/croll_keyframes.py <project_dir>写真を一度アップロードし、bl image edit経由でqwen-image-3.0を使って、ショットごとにアンカー付きポスターを 1 枚生成します。ポートレートでは、写真の顔とイラスト調のペーパードールの体を組み合わせます。商品では、ラベルのタイポグラフィをそのまま保った、ピクセル単位で忠実なステッカーを生成します。プロンプトには、実行し直して学ぶことになる次の 3 つのルールが組み込まれています。ポーズや表情の指示は体にのみ適用します。ウインクを指示すると顔が描き直されます。ハーフトーンは背景にのみ適用しないと、肌にも影響します。ポートレートの服装は明示的に固定する必要があります。このスクリプトは beats.json にanchor_freezeも書き込みます。 -
音声のタイミング調整+アニメーション化+組み立て。 標準の
audio.py→clips.py→assemble.pyを使用します。clips.pyはすべてのモーションプロンプトにanchor_freezeガードを挿入します。これがないと、動画工程で商品ラベルの文字が変わったり(確認された例:「PARFUM」→「PAREUM」)、顔のタイミングが変わったりする可能性があります。被写体本人の声でナレーションを行うには、voice.clone_refを設定します(上記の「音声+音楽」を参照)。スタンプやスナップズームのタイミングは、ナレーションの ASR 単語タイムスタンプから導き出します(asr_beats.pyは A-roll の映像に限らず、あらゆる音声で動作します)。
beats.json スキーマ
{
"project": "my-film", "topic": "...", "language": "en",
"aspect": "9:16", // 16:9 | 9:16 | 1:1 | 3:4
"style": "collage",
"provider": "bailian_cli", // default; invokes authenticated `bl` child processes
"theme": "american-retro", // THEME_PRESET (styles.THEME_PRESETS) — the LOOK layer
"arc": "timeline", // narrative arc (beat-layer.md) — the STORY skeleton
"video_model": "happyhorse-1.1-i2v",
"image_model": "qwen-image-3.0",
"image_resolution": "1k", // 1k (default) | 2k | 4k
"video_resolution": "720p", // 720p (default); Seedance also 480p/1080p (Omni is 720p-only)
"motion_style": "punchy", // amplitude: calm | punchy | max (theme sets a default)
"constraints": "strict", // strict = defect guards on | loose = let AI explore + re-roll
"timing_mode": "content", // default: text estimate, then measured TTS duration
"timing": {"min_segment": 5, "max_segment": 10, "tail": 0.45},
"voice": {"voice_id": "longtian_v3", "language": "zh", "speed": 1.0}, // see references/voices.md
// + optional "clone_ref": "path/to/sample.mp3" (clone that voice via seed-audio)
// and "persona": "YouTube tutorial creator" (delivery style for cloned VO)
"bgm_path": "path/to/instrumental.mp3", // optional; omit to assemble without music
"mix": {"music": 0.6, "voice": 1.25}, // audio balance — optional; these are the defaults (BGM ducks under the VO)
"caption_style": "white", // white (default: clean white subtitle) | paper (cream cut-out collage look)
"captions": true, // false = no burned-in captions (deliver clean, subtitle in post)
"watermark": "Made By 阿里云百炼CLI",
"mode": "croll", // C-roll only — plus the four fields below
"anchor_photo": "path/to/photo.png", // C-roll: the still to anchor (person or product)
"croll_subject": "portrait", // C-roll: portrait | product
"subject_wardrobe": "a cream knitted sweater and charcoal trousers", // C-roll portrait: outfit lock
"subject_desc": "the perfume bottle", // C-roll product: short noun phrase for the sticker
"beats": [
{
"id": 1, "title_cn": "", "title_en": "BEFORE MONEY",
"bg": "earthy clay tan", "feel": "ancient, humble", "hook": "surprising_stat",
"narration": "For most of history, there was no money...",
"shots": [
// Omit dur: timing.py/audio.py sets a content-driven 5-10s duration.
{"id": "a", "title": true, "shot_size": "WIDE", "camera_move": "push_in",
"scene": "...wide establishing collage...",
"element_motion": "traders gesture, goat bobs, a paper bird crosses, coins scatter"}
]
}
]
}
theme+arc は 2 つの大きなレイヤーを設定し、ショットごとの element_motion はエネルギーを決めます(以下を参照し、豊かな表現にしてください)。motion/collage_style/era は後方互換性のため、引き続き読み込まれます。
Bailian モデルの選択
ID の確認や上書きが必要な場合は、bl model list を使用します。このエディションのデフォルトは次のとおりです。
| 用途 | モデル | 備考 |
|---|---|---|
| キーフレーム/コラージュポスター | qwen-image-3.0 | bl image generate 経由で呼び出します |
| アンカー付き画像編集 | qwen-image-3.0 | bl image edit 経由で呼び出します |
| アニメーション化/画像から動画への変換 | happyhorse-1.1-i2v | bl video generate 経由で呼び出します |
| トークヘッドのスタイル変更 | happyhorse-1.0-video-edit | bl video edit 経由で呼び出します |
| ナレーション | cosyvoice-v3-flash | bl speech synthesize 経由で呼び出します |
| ASR | fun-asr | bl speech recognize 経由で呼び出します |
| 音楽 | ローカルファイル | bgm_path を設定します。省略可能です |
モデル選択の詳細な理由と、API/ffmpeg に関する注意点(認証ヘッダー、curl によるダウンロード、libass を使わないキャプション、コンテンツブロックなど)は references/models-and-gotchas.md を参照してください。問題のデバッグを始める前に必ず読んでください。ほとんどの問題はすでに記載されています。
バックエンドは差し替え可能です。 すべての生成呼び出しは scripts/provider.py を経由します。デフォルトの bailian_cli は、API キーをプロジェクトに公開せずに、bl の子プロセスを並列で起動します。atlas_cloud は、明示的に指定する互換バックエンドとして引き続き利用できます。失敗した CLI ジョブは再試行されることがあります。実行中の CLI ジョブは、停止時に重複課金が発生する可能性があるため、決して重複実行されません。
上級:要素単位のモーションコラージュ
標準的な方法では、ポスター全体にアニメーションを適用します(優れた自動処理による「動くポスター」です)。ドラマチックなパーツが飛び込んで組み上がるモーションコラージュ(cr7v2 風)や、コンテンツフィルターなしで完全に制御しながら実在の人物をアニメーション化する場合は、各ポスターを独立した要素に切り分け、ローカルのキーフレームエンジンで動かします(動画モデルは不要です)。
references/local-engine.md をお読みください。概要:extract_elements.py(切り抜き+背景除去+残留物の消去・修正)→ motion.py(Layer+キーフレーム、fly_in/slap/drop/pop_settle のイージング、手続き型の紙吹雪・スターバースト、カメラのズーム+揺れ+素早いパン、フレームのレンダリング)。パーツはぼかしたプレースホルダーの背景上で元の位置に戻るため、組み上がったフレームで元のポスターが再現されます。
エディション
- 自動エディション(このスキル):トピックを入力し、Bailian CLI を使って動画を生成します。
- 手動プロンプトパック:ユーザーが Bailian CLI を実行できない場合は、ビートマップ+ビートごとの画像プロンプト+クリップごとのモーションプロンプト+ナレーションスクリプトを作成するだけです。これらを任意の生成ツールに貼り付けてもらいます。クリエイティブエンジン(プロンプト)は同じです。