anime-reel
入力:スクリプト + 各行につき1つの音声MP3(ユーザーが両方を添付)。出力:元の音声をそのまま含む9:16リールと16:9コピー、さらにWhatsApp用の20MB未満の720pコピー。
厳格なルール(毎回実行)
- すべてコードで描画:HTML Canvas、ヘッドレスChromeでフレームごとにレンダリング、ffmpegでエンコード。ストック映像や画像生成AIは使用禁止。ベースとして
engine/を使用し、拡張する(置き換えない)。これにより見た目が毎回同じになる。 - すべての単語を強制アライメント(torchaudio MMS_FA、
scripts/align.py経由)でタイミング設定。決してタイミングを推測しない。アライメントが失敗したラインは停止し、理由をユーザーに伝える。等間隔にフォールバックしない。 - フルレンダリング前に静止画のコンタクトシートを表示し、承認を待つ。
- 既存ファイルを上書きする前に確認を求める。
encode.shは上書きを拒否して終了コード2で終了する。その情報をユーザーに伝える。 - 最終MP4内では元の音声をそのまま維持する(音声ラインはタイムライン上に配置するのみで、再処理はしない)。ユーザーから要求がない限り、BGMは追加しない。
手順
- セットアップ。
bash scripts/check_setup.sh(ffmpeg、Node、puppeteer、torch/torchaudio、uroman)を実行。不足があれば修正してから次に進む。bash scripts/sfx.sh <project>/sfxを実行し、ffmpegでヒット/ウィッシュ/インパクト/ポップ効果音を合成。 - スクリプトをショットに分割。 音声ライン1つにつき1ショット。各ショットに以下を記述:
id、speaker、text(MP3の内容と完全一致)、audioパス、place(rooftop、office、street、bedroom、sky、または新しいdrawPlaceブランチを追加)、camera(static|push|pull|pan+amount)、cast、slots(left/center/right)、fx。shots.jsonとして保存(スキーマはscripts/build_timeline.py内)。ショットリストを表示し、曖昧な場合はユーザーに修正を促す。 - キャラクター。 各キャラクターを
charactersで定義(name、skin、hair、hairStyle spiky|bob|long|short、eye、outfit、accent、color=そのキャラクターのキャプション色)。既存のアニメからコピーせず、オリジナルであること。アニメ風の見た目:大きな目とハイライト、太くてきれいな輪郭線、フラットカラー+正確に1つのシェード。キャラクターシートをレンダリングし、JSONを唯一の情報源として維持することで、キャラクターがショット間で変わらないようにする:node scripts/render_frames.mjs sheet timeline.json landscape out/character_sheet.png - アライメントとリップシンク。
python3 scripts/build_timeline.py shots.json timeline.json workを実行すると、MMS_FAがラインごとに単語のタイミングを取得し、その音声ラインのラウドネスから各キャラクターの口の開きカーブを構築する(mouth.py)。まばたきとアイドルモーションはエンジンに組み込まれている。非英語ラインの場合、align.pyはuromanでローマ字化しつつ、画面には元のスペルを表示する。 - キーラインでのアニメ演出(
fxに追加、時間はショット開始からの秒数):speedlines(登場や決意の場面)、impact(白/黒フラッシュフレーム、sfx: "impact"とともに)、shake(ヒット時)、chibi(+who、sfx: "pop"、コミカルなリアクション時)。控えめに使うこと:だいたい2〜3ショットに1つの演出、効果を際立たせるため。 - キャプションと音響。 2〜3ワードのキャプションはエンジンで自動処理される。発声された単語はその話者の色で、残りは白で表示。効果音は(
fx[].sfxを介して)視覚的なヒットと同じキューに配置される。次のコマンドでミックス:python3 scripts/build_audio.py timeline.json work/audio.wav - コンタクトシート、その後承認。 エピソード全体から約12個の時間を選び、すべての演出を含める:
node scripts/render_frames.mjs stills timeline.json portrait work/stills 0.5,2.0,...bash scripts/contact_sheet.sh work/stills out/contact_sheet.pngout/contact_sheet.pngを表示して停止。ユーザーが承認するまでフル動画をレンダリングしない。 - 承認後レンダリング、各向きで実行(
portrait= 1080x1920、landscape= 1920x1080、30 fps):node scripts/render_frames.mjs video timeline.json portrait work/reel_silent.mp4bash scripts/encode.sh work/reel_silent.mp4 work/audio.wav out/<name>_9x16landscapeでも同様にout/<name>_16x9で繰り返す。encode.shはAAC 256k オーディオをマルチプレクスし、_720p.mp4コピー(目標約17 MB、常に20 MB未満)を書き出す。サイズをls -lhで確認し報告する。
レンダリング設定
- 9:16:1080x1920、30 fps、H.264 yuv420p、CRF 16、AAC 256k、faststart。16:9:1920x1080、同じ設定。
- WhatsAppコピー:720p(720x1280 または 1280x720)、ビットレートは動画の長さから計算し、20 MB未満にする。
- キャプションは9:16では約68%の高さ(上部250 px、下部420 pxのアプリUIを避ける)、16:9では約86%の高さに配置。
このスキルのファイル構造
engine/engine.js、engine/index.html:Canvasエンジン(キャラクター、場所、スピード線、インパクトフレーム、シェイク、ちびキャラ、キャプション、バッジ)。scripts/:check_setup.sh、sfx.sh、align.py、mouth.py、build_timeline.py、build_audio.py、render_frames.mjs、contact_sheet.sh、encode.sh。