| name | videoup |
| description | Use when コレクションの音声ファイルが揃い、動画生成が必要なとき。マスター音源生成(yt-generate-master)とマスター動画生成(generate_videos.sh)の実行案内。動画変換、音声から動画への変換、generate_videos、MP3→MP4、videoup など、動画ファイル生成に関わる場面で必ず使用すること |
Overview
.claude/skills/ 配下の共有スクリプト(yt-skills sync で配布)を使ってマスター音源と動画を生成します。
スクリプトは毎回生成せず、既存の汎用スクリプトを実行します。
設定読み込みゲート
Quick Reference や対象コレクション確認に入る前に、以下を必ず Read(Codex では同等のファイル閲覧)で開く。SKILL.md の説明や記憶から設定値を推測しない。
.claude/skills/videoup/config.default.yaml
config/skills/videoup.yaml(存在する場合)
読み込み後は youtube_automation.utils.skill_config.load_skill_config("videoup") と同じ deep-merge 前提で、チャンネル上書きを優先して扱う。存在しない override は未設定として扱い、勝手に作成しない。このスキルが masterup や loop-video の skill-config を直接参照する段階では、それぞれの config.default.yaml と config/skills/<skill>.yaml も同じ手順で読む。
Scripts
| スクリプト | 役割 | 場所 |
|---|
yt-generate-master | 個別 MP3 → クロスフェード結合 → マスター MP3 | Python CLI (skill-config masterup 参照) |
generate_videos.sh | 音声 + テキストなし動画背景 (main.png/jpg or loop.mp4) → MP4 動画 | .claude/skills/videoup/references/generate_videos.sh |
Quick Reference
| コマンド | 説明 |
|---|
yt-generate-master | CWD のコレクションでマスター音源生成 |
yt-generate-master <path> | 指定コレクションでマスター音源生成 |
bash "$(git rev-parse --show-toplevel)/.claude/skills/videoup/references/generate_videos.sh" | CWD のコレクションで全動画生成(コレクションディレクトリ内で実行) |
bash "$(git rev-parse --show-toplevel)/.claude/skills/videoup/references/generate_videos.sh" <path> | 指定コレクションで全動画生成 |
Instructions
対象コレクション
$ARGUMENTS
引数が指定されている場合、そのコレクションを対象とします。
未指定の場合、collections/planning/ から music.approved = true かつ production.generated = false のコレクションを自動検出します。
ステップ
- 対象コレクション確認:
workflow-state.json で状態確認
- マスター音源:
master-mix.{wav,m4a,aac,mp3,flac} または master.{wav,m4a,aac,mp3,flac} が既にあればスキップ。なければ /masterup または /lyria でのマスター音源生成を案内(DAW バウンス済みの場合は master-mix.m4a をそのまま配置可、/lyria / /masterup の自動生成出力は master.{wav,mp3} で配置される)
- ループ動画背景:
10-assets/loop.mp4 が既にあればスキップ。
config/skills/loop-video.yaml::enabled: false のチャンネルではループ動画化が無効化されているため、/loop-video を案内せず textless 10-assets/main.png または main.jpg を静止背景として使用する。
この場合、既存の 10-assets/loop.mp4 が残っていても generate_videos.sh は無視し、静止背景に切り替える。
それ以外(enabled 未指定 or true)で loop.mp4 が無ければ /loop-video でのループ動画生成を案内。
loop.mp4 があると generate_videos.sh が自動的に動画背景を使用(静止画の代わり)
- 動画生成:
generate_videos.sh の実行コマンドを案内
- workflow-state.json 更新:
production.generated = true に更新
自動検出される要素
スクリプトはコレクションのディレクトリ構造から以下を自動検出します:
- コレクション名: ディレクトリ名から(
YYYYMMDD-xxx-theme-collection → Theme-Name)
- マスター音声:
master-mix.{wav,m4a,aac,mp3,flac} → master.{wav,m4a,aac,mp3,flac} の順に検出(m4a/aac は -c:a copy で再エンコード回避)。master-mix.* は DAW バウンス・手動配置、master.* は /lyria / /masterup(yt-generate-master)の自動生成出力(#507)
- 動画背景:
10-assets/main.png 優先、main.jpg フォールバック。thumbnail.jpg/png は YouTube アップロード用のテキスト付きサムネイルなので動画背景には使わない
- 個別音楽:
02-Individual-music/*.mp3(アルファベット順)
重要
- スクリプトを毎回生成しない —
.claude/skills/ 配下の共有スクリプトを使用
- ユーザーが DAW でミックスした
master-mix.{wav,m4a} がある場合、yt-generate-master は不要
set -e は使用しない(明示的エラーハンドリング)
opt-in: 短尺 master の動画長指定再生 (#545)
audio.target_duration_min を小さく (例: 30 分) 保ちつつ動画は長尺で出したい場合、config.default.yaml::audio.target_video_duration_min (分) を設定すると generate_videos.sh が音声入力にも -stream_loop -1 を適用し -t <target> で動画長を強制する。下流チャンネルの finalize encode 時間 (loudnorm + 雨音重ね 等) を短縮できる。
| 設定方法 | 例 | 優先 |
|---|
| 環境変数 | VIDEOUP_AUDIO_TARGET_VIDEO_DURATION_MIN=120 bash .../generate_videos.sh ... | 高 |
| チャンネル override | config/skills/videoup.yaml に audio: { target_video_duration_min: 120 } | 中 |
| 未設定 | (既定) | 従来動作 |
- master 尺 ≥
target_video_duration_min × 60 のときは無視され従来動作になる (master 尺が支配)
- 音声 loop seam の crossfade は本機能のスコープ外 (将来拡張)
設定: config/skills/videoup.yaml (v14)
generate_videos.sh のチューニング値は すべて下流チャンネルの config/skills/videoup.yaml から取得する(新規 env override は追加しない config 駆動)。全キー省略可で、省略時は現行の固定値にフォールバックする(=無回帰)。
audio:
target_video_duration_min: 120
video:
still_fps: 1
still_crf: 28
still_gop: 300
loop_maxrate: "6000k"
loop_bufsize: "12000k"
effect:
type: none
intensity: subtle
shrink:
enabled: false
maxrate: ""
crf: ""
- 最終ファイルサイズ ≒ ベイク/正規化ビットレート × 尺。容量を絞りたいときは
loop_maxrate を下げるのが最も効く(YouTube 側で再トランスコードされるため、source を 4000-4500k へ下げても最終画質はほぼ不変)。
effect.type / effect.intensity は config が一次ソース。既存の VIDEOUP_EFFECT / VIDEOUP_EFFECT_INTENSITY env は #648 互換の legacy fallback としてのみ残る。
生成後の容量最適化(shrink, opt-in)
shrink.enabled: true かつ shrink.maxrate か shrink.crf を指定すると、生成済み出力を 2 パス目で再エンコードして置換する。
- トレードオフ: 全尺を再エンコードするため、effect ベイク / stream copy の速度メリットは相殺される(長尺で数分〜十数分)。容量を最小化したい最終版のみに使う。
- 本来は
loop_maxrate を下げて上流で容量制御するのが推奨。
- アップロード確認後にファイルを消すディスク運用は
/live-clean が担当。
映像エフェクト (#648 / v14 でループ・ベイク化)
ループ動画背景・静止画背景のどちらでも、画面に 光の粒子・ボケ・グラデーション流れ などのエフェクトを重ねられる。動画編集ソフトの「画面を彩るレイヤー効果」を ffmpeg filtergraph だけで再現する機構。v14 でエフェクト込み 1 周期だけを焼いて stream copy する「ループ・ベイク」方式に刷新し、エフェクト有効時も高速になった。
エフェクト一覧
VIDEOUP_EFFECT | 効果 | 想定用途 |
|---|
none (デフォルト) | エフェクトなし。ループは stream copy、静止画は従来 libx264 経路 | 既存挙動の温存。コスト・容量を最小化したいとき |
particles | 光の粒子(淡い白点が画面をゆっくり流れる) | 落ち着いた BGM・夜景・キラキラ系のサムネ |
bokeh | ボケ(柔らかな円形グラデーションがゆらぐ) | カフェ系・暖色系ジャズ・ロウソク系のサムネ |
gradient | グラデーション流れ(半透明のカラーグラデーションが上下にうごく) | ローファイヒップホップ・シティポップ・夜の街並み |
強度は effect.intensity で subtle / medium / strong から選ぶ(デフォルト subtle)。BGM 視聴の邪魔をしないよう subtle 推奨。strong は短時間のテイスター動画やショート向け。
使い方
config/skills/videoup.yaml に書くだけ(env 指定は不要):
effect:
type: particles
intensity: subtle
あとは通常どおり generate_videos.sh を回すと自動でエフェクトが乗る。既存の VIDEOUP_EFFECT=... bash .../generate_videos.sh env 指定も legacy fallback として動く。
挙動と注意点
- v14: エフェクト有効時も高速。エフェクト込みで 1 周期分だけ
fx_baked.mp4 に焼き、あとは -stream_loop -1 -c:v copy で連結する。従来の全尺再エンコード(loop/静止画ともに 8〜15 分)が 約 1〜2 分になり、継ぎ目は closed GOP の stream copy で原理的に無損失
- エフェクト周期は整数固定: particles=36s / bokeh=60s / gradient=72s。背景が
loop.mp4 のときは lcm(loop 尺, 周期) の長さを焼いて背景・エフェクト双方の継ぎ目を揃える
- ベイク尺が動画尺以上、または上限(
BAKE_MAX_LEN=900s)超のときは従来の全尺再エンコードへ 自動フォールバックする(短尺動画など)
fx_baked.mp4 は fx_baked.params(effect / intensity / 周期 / 元画像 mtime / maxrate)でキャッシュ。サムネ差し替え時のみ再ベイク(10〜40 秒)するので「画像差し替え→再生成」が軽い
- ファイルサイズは
loop_maxrate(既定 6000k)で制御。stream copy 出力のサイズはベイクのビットレート × 尺で決まる。容量を絞るなら loop_maxrate を 4000-4500k へ
- 不正な値(例:
effect.type: sparkle)は fail-loud で停止。ffmpeg が走り始める前にエラーとなる
- 値検証は bash で完結しているため、
set -e を使わずとも安全
動作確認
実コレクションで生成した動画は YouTube Studio のプレビュー(モバイル・PC)と実機 YouTube 視聴で粒子・ボケ・グラデーションが音楽の邪魔にならない強度で乗っているかを必ず確認すること。BGM チャンネルのコア視聴体験を壊さないことが優先事項。
Overlays(#511, v13)
config/channel/youtube.json::overlays で audio visualizer + subscribe popup の合成を有効化できる。overlays.enabled: true のときだけ generate_videos.sh は x264 再エンコード経路 に分岐し、filter_complex で背景の上に visualizer / popup を重ねる。overlays.enabled: false(既定)または overlays キー欠落時は従来の stream copy / 静止画 1fps 経路を 100% 維持する(後方互換)。
設定例(youtube.json)
{
"overlays": {
"enabled": true,
"audio_visualizer": {
"enabled": true,
"mode": "bar",
"size": "1280x180",
"rate": "24",
"fscale": "log",
"colors": "white",
"position": "(W-w)/2:H-h-40",
"opacity": 0.85,
"glow_enabled": true,
"glow_sigma": 12.0,
"glow_opacity": 0.45
},
"subscribe_popup": {
"enabled": true,
"image": "subscribe-popup.png",
"start_sec": 5.0,
"duration_sec": 8.0,
"fade_sec": 0.6,
"position": "W-w-40:40"
},
"encoder": {
"preset": "medium",
"crf": 20,
"maxrate": "4M",
"bufsize": "8M",
"framerate": 24
}
}
}
自動検出と前提
- jq 必須:
jq が PATH に無いときは overlays は自動 disable され既存経路で動く。
- 設定ファイル探索順:
OVERLAYS_CONFIG 環境変数 → CHANNEL_DIR/config/channel/youtube.json → コレクションディレクトリの祖先探索。
- popup 画像探索順: 絶対パス →
10-assets/<image> → <collection-dir>/<image>。見つからない場合は popup のみスキップして visualizer は実行する。
- 再エンコード固定: overlays 経路は
-c:v copy 不可。encoder.crf / maxrate / bufsize で品質とサイズを制御する(DeepFocus365 で 70 分マスター = 約 1.0 GB / 2 Mbps 実績)。
動作実証メモ
- DeepFocus365 で実装済み: 70 分マスター動画を約 2 分弱で生成、visualizer + popup ともに正常合成(#511 背景)。
- visualizer は
showfreqs=mode=bar + gblur の 2 パス glow で淡い発光を演出。glow_enabled: false で 1 パスに減らせる。
- popup は
fade=in / enable='between(t,start,end)' / fade=out を組み合わせて時間窓制御している。
長時間処理の取り扱い
generate_videos.sh は ffmpeg を走らせるため数分かかる。目安(2 時間尺): エフェクト無し(stream copy / 静止画 1fps)= 約 1〜2 分 / エフェクト有り(v14 ループ・ベイク)= 約 1〜2 分(初回はベイク 10〜40 秒 + 連結 約 1 分、2 回目以降はベイク cache hit)。shrink.enabled の容量最適化や短尺フォールバックの全尺再エンコードを使うときは尺なりに数分〜十数分かかる。必ず Bash ツールを run_in_background=true で起動する。これによりユーザーは処理中も同じセッションで質問できる(Claude Code は完了時に自動でメッセージ通知するため、sleep ループや until での自前ポーリングは禁止)。
spawn 例:
bash "$(git rev-parse --show-toplevel)/.claude/skills/videoup/references/generate_videos.sh" \
> /tmp/videoup-$(date +%s).log 2>&1
VIDEOUP_EFFECT=particles VIDEOUP_EFFECT_INTENSITY=subtle \
bash "$(git rev-parse --show-toplevel)/.claude/skills/videoup/references/generate_videos.sh" \
> /tmp/videoup-$(date +%s).log 2>&1
これを Bash run_in_background=true で投げ、spawn 直後に次のメッセージを返す:
⏳ マスター動画生成を background 実行中(推定 N 分)。完了まで他の質問にもお答えできます。
ログ: /tmp/videoup-*.log
cmux 環境下($CMUX_WORKSPACE_ID あり)であれば補助で cmux set-status "videoup" "running" --icon "hourglass" --color "#f59e0b"、完了で cmux clear-status "videoup" + cmux notify --title "videoup 完了" を呼ぶ(非 cmux 環境では skip)。
完了通知が届いたらログ末尾から結果サマリー(生成された .mp4 のパス)をユーザーへ返す。失敗時は ffmpeg のエラー行を抜き出して報告する。
オーディオビジュアライザー / オーバーレイについて
generate_videos.sh は config/channel/youtube.json::overlays.enabled: true のときだけ、audio visualizer や subscribe popup を filter_complex で合成する。無効時または jq 不在時は従来の textless main.png/jpg(静止画背景)または loop.mp4(ループ動画背景)に音声を重ねる経路を維持する。
よくある誤解 (#646 feedback)
「Suno のデータ取り込み時にビジュアライザーを付けて」とユーザーが指示しても、Suno / Lyria / masterup の工程ではビジュアライザーは付かない。理由:
/suno / /lyria / /masterup は音源(mp3 / wav / m4a)を作る工程であり、映像オーバーレイは扱わない
- ビジュアライザーは本質的に動画生成(
generate_videos.sh)側の合成処理で、ffmpeg の filter_complex に showfreqs 等を組む
- 反映したい場合は
config/channel/youtube.json::overlays.enabled: true と必要な overlay 設定を用意してから /videoup を実行する
正しい運用
- ビジュアライザーが必要な動画は、
config/channel/youtube.json::overlays.enabled: true にしたうえで overlays.audio_visualizer.enabled: true を設定して /videoup を実行する
- popup も必要なら
overlays.subscribe_popup.enabled: true と画像パスを設定する。画像が見つからない場合は popup だけスキップし、visualizer は継続する
- overlays 無効チャンネルでは従来どおり textless
main.png/jpg または loop.mp4 のみで生成する
Claude への指示時の注意
オペレーターから「ビジュアライザー付きで」「波形表示で」等の指示があった場合は、Suno 側ではなく /videoup の overlays 設定で反映することを明示してから作業を進めること。その上で、
- overlays を有効にして生成するか
- 静止画 / ループ動画のみで進めるか
- 外部ツールで後付けするか
をユーザーに選んでもらう。黙って静止画で生成すると今回のような FB(期待と実装の乖離)が再発する。
障害時ガイダンス
動画生成は generate_videos.sh(ffmpeg)でローカル実行され、外部サービスには依存しない。
| 状況 | 兆候 | 対処 |
|---|
| ffmpeg 不在 | command not found: ffmpeg(generate_videos.sh の command -v チェックで停止) | brew install ffmpeg 等で install してから再実行 |
Next Step
動画生成後:
→ /video-description <collection-path> でYouTube概要欄を生成