Motion Frames — フレームベースモーションデザインシステム
動画ソフトウェアを使わずにプロフェッショナルレベルのモーションデザインを実現する完全な手法: アニメーション全体は シーンがフレーム番号のみの純粋関数であるHTMLページ であり、ヘッドレスクロームによってフレームごとにキャプチャされ、ffmpeg で MP4 に合成されます。すべては決定論的です。同じ入力、同じピクセル — 並列レンダリング、任意のフレームからの再開、1/60秒精度の音声同期が可能です。
1. 不変のルール: フレームの純粋関数
- シーン全体は
renderFrame(n)に存在し、nはフレーム番号 (60fps) です。 - 禁止: 時計 (
Date.now,performance.now,requestAnimationFrameによる状態の蓄積)、および シードなしのランダム。ランダム性はインデックス/フレームの決定論的hash(i)を介してのみ許可されます。 - 動き = イベント開始からの経過時間の閉じた式:
- 解析的スプリング (減衰不足):
spring(t, freq, damp)— オーバーシュートあり。すべての基本物理(エントリ、ポップ、スタック)に使用。 - 名前付きイージング:
easeOutCubic,easeInOutCubic,easeOutBack。 - セグメント:
seg(n, a, b)= フレーム範囲の進行度 0→1;clamp,lerpで任意の値(位置、色、モーフ形状)を補間。
- 解析的スプリング (減衰不足):
- 標準フォーマット: 1080x1920, 60fps。長さは内容に応じて決定(簡易テスト: 8秒 = 480フレーム)。
2. パイプライン (このスキルの pipeline/ ディレクトリ)
| ファイル | 説明 |
|---|---|
pipeline/template.html | ヘルパー (T, seg, spring, イージング、hash) と renderFrame(n) スケルトンを含むベースページ |
pipeline/render.mjs | 依存関係のないCDPレンダラー: node render.mjs <page.html> <dir> <num_quadros> 1080 1920 [quadro_inicial] |
pipeline/preview.mjs | 選択したフレームのみをPNGでレンダリング: node preview.mjs <page.html> <dir> "0,60,160,300" <total> 1080 1920 |
pipeline/sfx_kit.py | フレーム番号に連動した合成効果音キット (numpy/scipy) |
- Chromium: レンダラーは
CHROME_BINを探し、次にスクリプトの隣にあるchrome-headless-shell、最後にワークスペースの既知のパスを探します。すべての Chromium が使えるわけではありません: ドメインポリシー/WebGL ビルド (例: Hatch管理のChromium) はスタンドアロン実行を拒否します — 単体の chrome-headless-shell を使用してください。 - 速度:
FMT=jpeg(品質90) は PNG より約2倍高速で、結果は区別できません。プレビューにのみ PNG を使用。 - シャーディング: 長い動画は2つの並列プロセス (間隔の半分、
quadro_inicial引数を使用) でレンダリングし、各プロセスは独自のPORT(CDP) を持ちます。約8GBのマシンでは 最大2並列 — 3つでRAMが不足します。 - アセンブリ:
ffmpeg -framerate 60 -i dir/f%04d.jpg -i audio.wav -c:v libx264 -pix_fmt yuv420p -crf 18 -c:a aac -b:a 192k -movflags +faststart out.mp4。 - ローカルフォントと画像: HTML への相対パスで参照します (
file://経由で機能)。ブランドフォント:.woff2をダウンロードし、ローカルな CSS@font-faceを生成します — レンダリング時にネットワークに依存しないでください。シーンで使用する画像: ページ本文に非表示の<img>プリロードを含めます。そうしないと、最初の数フレームに画像が表示されません。
3. 制作フロー (この順序で)
- スクリプトとリファレンス: 各シーンのフレーズを定義します。リファレンスをフレームごとに研究し (ffmpeg でコンタクトシートを抽出)、文法 をメモします — 表面をコピーしないでください。
- 音声を最初に (ナレーションがある場合): カットを決定する前に無音を検出 (
ffmpeg -af silencedetect); faster-whisper (small,word_timestamps=True、16kHz WAV から読み取った numpy 配列として音声を渡す — 一部の PyAV バージョンでは faster-whisper の内部デコードが壊れます) で文字起こしし、キーワードの時間を フレームランドマーク (秒 × 60) に変換します。音声の長さを決してでっち上げないでください。 - ブランド偵察 (プロダクトビデオ): 実際のアイデンティティを取得します — サイトの HTML/CSS をダウンロードし、ロゴ (画像ファイル)、パレット (CSS で最も頻度の高い16進数)、フォントを抽出します。ビデオでは公式のロゴとフォントを使用します。
- シーンごとのデザイン: シーンごとに関数 (
s1(n),s2(n)…)、境界は音声ランドマークにあります。各シーンは主要イベントがすでに同期された状態で開始されます。 - プレビュー必須:
preview.mjsで15~30フレームのコンタクトシートを作成し、リズムと構図を確認します — さらに、必ず2~3のキーフレームを実寸で確認してください: コンタクトシートは誤解を招きます (テキストの重なり、幅オーバー、細かいディテールを隠します)。 - マイクロイベントごとのSFX (セクション8)、アニメーションと同じフレーム番号を使用。
- シャードレンダリング + アセンブリ + QA: 最終MP4 (個々のフレームではなく) からフレームを抽出し、納品前に確認します。
4. 動きの言語 (プロフェッショナルと凡庸を分けるもの)
- 映画的なオープニング: 最初の1秒はタイトル — スプリングとカメラワークで入る大きなタイポグラフィ、奥行きのある背景。静止画面は禁止。
- カメラは決して止まらない: すべてのショットでゆっくりとしたスケールのドリフト (1→1.03–1.09); 動き (レイヤー間のパララックスを伴うドリー/ズーム/パン) によってカットを隠します。
- 密度: 0.5~1.5秒ごとにマイクロイベント。2秒間何も起こらないセクションがあれば、それは間違いです。
- すべてに物理: オーバーシュートのあるスプリング、落下とバウンドのスカッシュ&ストレッチ、主要な動きの前の予備動作。線形の動きはデフォルトで禁止。
- トランジションはイベントであり、カットではない: オブジェクトのモーフ (ピルがバーに、バーがカードに)、ブラーを伴うズームスルー、またはズームパンチ (シーン境界で約18フレームのクロスフェードでスケール 1→1.09 を通過)。
- 控えめなパレット: 1つのファミリーの背景 + グローのある1つのアクセントカラー; 太いタイポグラフィ; 十分な余白。
5. 背景: 決してフラットではなく、常に生きている
真っ黒な背景 (または単色) は禁止 — 背景は独自の生命、流れ、背景/中間/前景のパララックスを持ちます。3つの実証済みレシピ:
- リビングスタジオ (暗めのプロモ): アクセントカラーのインクを使ったグラデーション、ゆっくり漂う2つのぼやけたカラーブロブ、上部からのスポットライト、浮遊するボケ粒子 (決定論的ハッシュ)、透視投影の点グリッド床 + 輝く水平線 + 中央要素の下の反射。
- リキッドオーロラ (連続シーン): 3~4本の細長い放射グラデーションバンド、
mix-blend-mode: screen、強いブラー、リサジュー図形で漂いゆっくり回転; コマンドがシーンの「色」を変えるときにクロスフェードする2つのパレット; 上部のパーティクルダスト。 - ブランドアイス (明るいキネティック): ブランドカラーの明るいグラデーション、流れるミントシルク (オーロラと同じ手法、明るめ)、微妙な点グリッドとダスト — クリーンだが呼吸している。
6. 本物の3D (重要 — ここが多くのビデオがリファレンスに劣る部分です)
- CSS
perspective+rotateX/rotateYをスマートフォン、カード、ダッシュボードに; 要素は傾きに反応する生きている影で 浮遊 します。 - 本当のパララックス: すべてのズーム/パンで背景、中間、前景が異なる速度で動きます。
- CSS によるキューブと3Dボックス: 各面は
translateZ = 幅/高さの半分で配置された div (これを間違えるとエッジに隙間ができます)。 - 上昇するアイソメトリック階段/ブロック、奥行きのあるスタック、ガラス (後ろの背景が単純な場合の
backdrop-filter)、および走査する鏡面反射。 - 経験則: シーンが「テキスト + フラットな四角形」と説明できるなら、3Dが不足しています。傾き、レイヤー、または奥行きを追加して、描かれたものではなく写真のように見えるようにします。
7. 4つの文法 (ショットごとの構造)
A. シネマ/モーフ (オープニングとスタイルテスト)
映画的なタイトル → 点線軌道上でスカッシュ&ストレッチするオブジェクト → カメラが潜り込み、オブジェクトが モーフ (円→ピル→画面) → 回転する3D要素と面へのズーム → 手描きの円があるキネティックタイポグラフィ → スプリングでグラフがあるガラスパネル → 開始点に戻るクロージング (必要に応じて完全ループ)。
B. プレミアムアプリプロモ (Opal/Qwixタイプのリファレンス)
- ライブなアンビエント背景 + スポットライト; グロウ/ブルームのある1つのアクセントカラー。
- オープニング: 3Dパースペクティブで浮遊するUI/スマートフォン、プルフォーカス を伴うドリーイン (ぼやけて始まり、ピントが合う)。
- カメラがディテール (グラフのバー) に潜り込み、それが次のショットになる。
- アイコン + カウントアップ数字 (easeOut) + ラベルの付いたガラスピル; 周回する光のアークのある境界線。
- 集約: ピルからサポートラインが描画され、大きな数字 + ▲ に収束。
- アプリアイコンのモーフ + パーティクルバースト。
- アプリシート + 光のスイープのある巨大なCTAピルボタン。
- ロゴリビール: シンボルが描画される (SVG dash) + ワードマーク + 小さなURL。
C. インタラクティブ連続シーン ("Built with Claude" リファレンス)
カットのない単一シーン、リキッドオーロラ上: シンボルが描画される → コマンドピルが入る → カーソルが移動し、ピルをクリック → ピルが モーフ してプロンプトバーになる → プロンプトが 単語ごとに入力される (点滅するキャレット、最後の単語が強調) → バーがモーフして結果になる (内部で構築されるカード: リング、バー、再生、進捗%) → 2番目のコマンド入力で背景全体の色が変わる → シンボルと署名でクロージング。ストーリーは「誰かが製品を使っている」。
D. 明るいキネティックタイプ (ポルトガル語のタイポグラフィ広告)
ブランドアイス背景; ブランドフォントの太いタイポグラフィが主役、音声のビートに合わせて単語ごと、キーワードはアクセントカラー、カラフルなゴーストシャドウ、手描きのいたずら書き (取り消し線、丸、スウッシュ — SVG dash)。実際のストーリーを伝えるUIを挟む: 物理でスタックする 通知、比較バー、ロゴの周りの 軌道 ノードシステム、会話するチャットバブル、グラフ付きステータスカード、巨大カウンター。シーン境界はズームパンチ; 中間のダークインバージョンビート ("E não para por aí!" — 「そしてまだ終わらない!」); 3つのヒットとアイコンでスローガン; カーソルがクリックしたロゴ + CTA + URL。
8. 音: マイクロイベントごとのSFX
sfx_kit.pyでトラックを構築: 各サウンドイベントは、視覚イベントと同じフレーム番号を使用します。- 語彙:
pop(クリック、カード、大きな単語)、tick(タイピング、バー、カウンター)、whoosh(トランジションとモーフ)、shimmer(確認、リビール)、pad(すべての下にある控えめなハーモニックパッド)。 - ビデオと同じ密度: マイクロビジュアルイベントがあれば、音があります。ナレーションがかかっている場合は、トラックを約0.5にミックスし、声を支配させます。
- ユーザーの声を生成したり置き換えたりしないでください: ナレーションは常にユーザーのもので、そのまま (無音カットは、分析された音声とカット後に再同期された同期のみで行います)。
9. 汎用的表現回避チェックリスト (納品前に確認)
- タイポグラフィは主役ですか、それとも単なるUIラベルですか? (主役であるべき)
- すべてのシーンに0.5~1.5秒ごとにマイクロイベントがありますか?
- 何かが物理でスタック、落下、または衝突していますか — それともすべてが孤立して浮遊していますか?
- インタラクション (カーソルクリック、プロンプト入力、製品使用中) はありますか?
- 手描きの落書きレイヤー (丸、下線、矢印、取り消し線) はありますか?
- 少なくとも1つのトランジションはズームだけでなくオブジェクトのモーフですか?
- 背景は独自の生命で流れ、レイヤー間にパララックスがありますか?
- UIには、抽象的なプレースホルダーではなく、ストーリーを伝える「実際の」コンテンツ (値、会話、名前) がありますか?
- 軌道システム、パス上のテキスト、またはその他の「シグネチャー」要素はありますか?
- 3Dはセクション6のテストに合格していますか?
- すべてのマイクロイベントにSFXがありますか?
10. 商業的真実 (数字を作らない)
- 商業的な約束になる数字 (率%、承認率、価格) は でっち上げません: ブランドが公開していない場合は、数字なしの視覚的な比較 (高いバー × 低いバー)、動きのリソースとしてのボリューム/成長カウンター、定性的な言葉 (「高い」、「かなり低い」) を使用します。
- 製品に関する不確かな事実は、レンダリング後ではなく、スクリプト作成前に 通知されます。
11. 過去に発生したエラー (繰り返さない)
- コンタクトシートは誤解を招く: サムネイルはテキストの重なりと幅オーバーを隠します。キーフレームは常に実寸で検証してください。
- SVGの重複属性: 同じ要素に2つの
stroke-dasharray— 最初のものが優先され、ドローオンが静かに死にます。要素ごとに1つの属性。 - シーンインデックスのハードコード: 固定シーンを返す関数 (
return 5) は、シーン数が変わると最後のシーンを壊します。境界配列から導出します。 - 3Dキューブが開いている: 間違った
translateZ(≠ 寸法の半分) の面は、エッジに隙間を残します。 - 並列3シャード = 小規模マシンでOOM。最大2。
- システムのChromiumは使えない場合がある (ドメインポリシー/WebGL): 単体の chrome-headless-shell を使用します。
- プリロードのない画像 は最初の数フレーム後にしか表示されません: 本文内の非表示
<img>で解決。 - 「ほぼ正しい」シーン: 大きなフォントのテキスト幅を測定 — 118px のスローガンフレーズは 1080px を超え、ひどく崩れる可能性があります。大きなプレビューで実際の幅を確認します。
12. サンプルプロジェクト (このシステムの実際のプロダクション)
~/workspace/motion-frames/teste_8s.mp4— 文法A: ボール/モーフ/キューブ/タイポグラフィのループ、8秒。~/workspace/iphone18/iphone18_pro.mp4— 単語ごとに同期されたナレーション (53秒)、CSSによる3D iPhone。~/workspace/kalo/kalo_app_v2.mp4— 文法B、リビングスタジオ背景 + AI食事スキャンシーン、15秒。~/workspace/kalo/feito_com_muse.mp4— 文法C: 連続シーン、カーソル、タイピングプロンプト、モーフ、クロスフェードオーロラ、14秒。~/workspace/turtle/turtlepags.mp4— 完全な文法D、ナレーション、実際のブランドアイデンティティ (サイトのロゴ/パレット/フォント)、53秒。