ウォール街式解説動画(wallstreet-explainer)
大きなお金の話を伝える:本物の人、本物のニュース、本物の映像を証拠に。グラフィカルなステージで数字と関係性を演じる。各カットは前のカットの要素を引き継ぎながら進み、視聴者は「今何を見ているのか、なぜそれを見ているのか」を常に理解できる。 動くのはカメラと世界であり、要素自体が動くのではない。前後層のあるステージをカメラがプッシュ、トラック、パンして、まさに語られている対象を探しに行く。オブジェクトはその場で状態を変える。すべての動きは、その瞬間の言葉の意味に対応している。
このスキルについて
-
これは:一連の設計思考(各カットに何を置くか、なぜそれなのか、なぜ次のカットへつなげられるのか)、一連のモーション原理(3本の類似リファレンス動画をフレーム単位で計測して導き出した、なぜPowerPointやAI生成と違うのか、手法のリストと定量目標)、一連のスタイル言語(ステージ、巨大文字、キーイング、ディスク、数字、チャート、原文ハイライトの具体的な実装、そしてオープニングフックメニュー)、およびツール一式を提供します。
-
テンプレートではありません。コピー可能な画面構成や固定されたカット順序はありません。各動画のビジュアルは、その都度、独自のスクリプトと素材から考案する必要があります。
examples/ai-burn-money/は、ある1本の動画がどのように考案され、どこで苦労したかを記録したものであり、そのカットをそのまま流用しないでください。 -
スロープッシュ、数字のスクロール、実写へのテキスト重ねは、リファレンス動画でも使用されています。安っぽいのはこれらの手法そのものではなく、その実装方法です。判断基準は3つの質問です:それを削ったら視聴者の理解がどれだけ減るか?動いているのはカメラであり、オブジェクトが状態を変えているのか、それとも要素自体がエントリーアニメーションを演じているのか?このレイヤーは、現実的で具体的なものか?
作業を始める前に、まず references/thinking.md と references/motion.md を読み、必要に応じて他の資料も参照してください。
フロー:各ステーションでユーザーに確認を取る
美的判断はユーザーが行います。いきなり完成版を出力せず、各ステーションで具体的な成果物を提示し、ユーザーの承認を得てから次に進みます。
| ステーション | 行うこと | ユーザーに見せるもの |
|---|---|---|
| 0 トピック選定 | トピックは「今ホットである」ことと「視聴後何か持ち帰れる」ことの両方を満たす必要がある | 2〜3のトピック案、それぞれに一言フックを添える |
| 1 スクリプト | 口語調、一人称、一文一文が次につながる。原音声を挿入する箇所には事前に伏線の文を書く(references/audio.md) | 全文。承認が得られるまで正式なナレーションは行わない |
| 2 ディレクターズテーブル | 下記「ディレクターズテーブル」セクションを参照 | 要点:冒頭でどう引き込むか、各箇所のつなぎ方、伏線の文が必要かどうか |
| 3 素材 | 公式高画質動画 → ニュース原文 → 当事者の原音声 → 当事者キーイング用のカット無し実写(切り替えポイントがなく、セリフに合った動きがあるもの)。まずコンタクトシートを確認し、イン点を決め、フレーム単位で切り替えポイントをチェックする(references/sourcing.md) | 主要素材(オプション) |
| 4 ナレーションとタイムライン | scripts/temp_voice.py:まず仮音声でタイムラインを生成、すべてのビジュアルをテキストに紐付ける | — |
| 5 オープニング | まず異なるメカニズムのフックを3つ選び、それぞれ5〜8秒のラフカットを作成してユーザーに選択させる(references/opening.md)。選ばれたフックを使って、0秒から最初のカット切り替え箇所までのサンプル(15〜20秒、音声付き)を作成する | 3つのフックのラフカット → 選ばれた後のオープニングサンプル |
| 6 全編720p | ディレクターズテーブルに従って全編を構成。2〜3カット書くごとに静止画フレームで確認し、重要な動きは連続フレームで確認する(strip.py)。納品前に motion_check.py を実行する | 720p全編、抽出フレーム画像、特に確認してほしい箇所を2〜3ヶ所指摘 |
| 7 完成版 | 満足がいくまで修正。正式ナレーションに差し替え。1080pで一度だけレンダリング | 1080p |
各納品時に必ず行うこと:
ffprobeを使用してファイルが開けることを確認する。- 自分で全カットを静止画フレームとコンタクトシートで確認し、重要な動きは連続フレームで確認する。
- 固定のレビューフォルダに入れ、番号と日本語名で命名し、旧バージョンには
旧_プレフィックスを付ける。 - このバージョンで何を変更したか、どのような測定を行ったか、ユーザー自身が確認すべきことを明確に伝える。
ディレクターズテーブル
全編の唯一の計画です。ユーザーはこれでビジュアルを確認し、制作時はこれに従い、レビュー時はこれと照合します。各カットに以下の列を記述します:
| カット | 時間 | セリフ | 画面に何が表示され、何が行われているか → 停止時に何が残るか | 視聴者は何を新たに理解したか | 担当 | 理解の瞬間 + 停止 | 承継 |
- 視聴者は何を新たに理解したか:前のカットとは異なる、具体的な一文。書けなければ、このカットは削除するか再考すべき。
- 担当:このカットが何によって理解を促進するか。人物 / 実証(実際の素材、原文)/ 構造(ディスク、チャート)/ テキスト(大字、結論)/ 混合。
- 承継:前のカットが残したどの要素をこのカットが引き継ぐか、引き継ぎ方は
続 / 切 / 持越 / 接近 / 展開 / 転換にその要素を加えて記述。最初のカットは—。 - 「画面」列には、カメラがどう動くかも明確に記述する:各移動の着地点(誰にプッシュするか、誰をパンで追うか、いつ引きで全体を見せるか)、どのカットで実写キーイングを使用するか。
- セリフは一字も変更しない。1カットが複数の文をカバーすることもある。常に単語に紐付ける(「"七千"と言った瞬間」のように)。
記述後、「読み合わせチェック」を行う:セリフと「何を新たに理解したか」の列を隠し、「画面」列だけを読んで、話が通じるか確認する。さらに、連続したハードカットがないか、十分に停止していないカットがないかをチェックする。例は examples/ai-burn-money/director.md を参照。
どの資料を読むか
| 取り組んでいること | 読む資料 |
|---|---|
| 1カットに何を置くか、なぜそれか、なぜ次のカットへつなげられるか | references/thinking.md |
| 動きの実現:なぜPowerPoint/AI生成と違うのか、手法リスト、定量目標、カメラとキーイングのコード感覚 | references/motion.md |
| 画面の見た目:ステージ、巨大文字、キーイング、ディスク、数字、チャート、タイトル、字幕、実写フレーム | references/style.md |
| カット間のつなぎ方、カメラワークとアクションの感覚 | references/grammar.md |
| オープニング | references/opening.md |
| 素材検索、ダウンロード、イン点選定、人物キーイング、ニュース原文、原音声 | references/sourcing.md |
| スクリプト、ナレーション、原音声編集ポイント、サウンドエフェクト、ミキシング | references/audio.md |
| 納品前の自己チェック | references/review.md |
| 実践で得た教訓 | references/lessons.md |
ツール(scripts/)
| スクリプト | 機能 |
|---|---|
footage.py | search 動画検索 / get ダウンロード(一部分のみ、音声のみも可)/ sheet タイムコード付きコンタクトシート / scenes カット切り替えポイント / extract 30fpsフレームシーケンス抽出 / wave 原音声編集ポイントのラウドネス確認 |
snap_news.mjs | ニュースとレポートの原文スクリーンショット:広告除去、フローティング要素除去、フォント読み込み待ち、キーワードの矩形測定 |
matte.py | 実写のフレーム単位キーイング(GPU上のISNetで約0.25秒/フレーム)、隠れた切り替えポイントを検出、人物の輪郭領域のみ保存 |
matte_clean.py | キーイング後処理:細かい線や断片の除去、くっついている背もたれを一括削除、各フレームの頭肩中心を書き出し(人物配置時の追従用) |
stage25d.js | ページ内で使用する小さなツール:レイヤーカメラ、方向性モーションブラー、被写界深度、キーイング人物追従、巨大文字、眉題、実写を背景に退避、10億単位の丸め。ツール関数であり、カットそのものではない |
temp_voice.py | script.json → 仮ナレーション(edge-tts)と timeline.json(各単語の時刻、原音声挿入箇所、タイトル位置)。正式ナレーションがある場合は自動的に差し替え、--asr で再アライメント |
render.mjs | フレーム単位レンダリング:--stills 静止画確認、--video --range 部分レンダリング、--h 1080 完成版出力 |
strip.py | 連続フレームの合成図:1つのアクションを8フレームで表示、静止画では見えないミスをチェック。リファレンス動画のアクション分解にも使用 |
motion_check.py | カメラ動作自己チェック:画面が全く動かない時間、停止回数、カメラが動いている時間、前後層、プッシュ/トラック比、リファレンス動画との範囲比較 |
mix.py | ナレーション、原音声、サウンドエフェクト、BGM(BGMはナレーションを優先するように調整)→ -14 LUFS。--check で各セクションのラウドネス測定 |
依存関係:ffmpeg、yt-dlp、Python(edge-tts、numpy、opencv-python、Pillow;推奨 faster-whisper;キーイングには onnxruntime-gpu と rembg のダウンロードモデルが必要)、Node と Playwright。インストール方法は README を参照。
ナレーション:まず仮音声を使用
- 最初に
temp_voice.pyで edge-tts の仮ナレーションを生成し、タイムラインを出力、ビジュアルはそれに合わせて作成する。 - スクリプトとビジュアルが確定したら、正式なナレーション(任意のTTS、声のクローン、または実際の音声録音)に差し替える:各セリフを
voice/<id>.final.wavとして保存し、temp_voice.py script.json --asrを実行する。 - ナレーションは常に:先頭と末尾の無音をカットし、元の速度を維持し、文間のポーズは
gapパラメータのみで決定する。後から atempo で速度を上げないこと。無音をカットした後にさらに速度を上げると、非常にせわしない印象になる。
動画の構成(骨格であり、コピーするためのものではない)
- 動画ディレクトリ:
index.html、film.css、film.js、timeline.json、assets/(実写フレームはassets/clips/<名前>/、キーイング済みはassets/cut/<名前>/)。カメラツールを使用する場合はscripts/stage25d.jsをコピーし、film.js より先に読み込む。 film.jsはwindow.readyとwindow.seek(t)を公開する。seekは t が属するカット(shot(t0, t1, fn))を見つけ、fn(t)を呼び出してそのフレームの HTML を返し、画像のデコードとフォントの読み込みを待つ。同じ t に対して常に同じフレームを描画し、CSS アニメーションや再生クロックに依存しない。- 時刻は常に
cue(句id, '単語')として記述し、タイムラインから取得する。秒数をハードコードしない。ナレーションを変更すると、全編が自動的に調整される。 - 実写はフレームシーケンスに抽出し、t に基づいてフレームを取得する。
<video>タグは使用しない。フレーム数を登録する必要があり、欠落があると存在しないフレームを取得し、黒画面や空のフレームが表示される。 - 1カット = 1つのカメラ位置関数 + 複数のレイヤー:カメラ位置は
camPath(t, 開始点, 移動テーブル)で定義し、各レイヤーはL(カメラ位置, 前フレームのカメラ位置, z, html)でラップする。遠いレイヤーほど z 値が小さく、モーションブラーは自動計算される。 - カット間の承継が必要な場合、前のカットの関数の最終フレームの画像を、次のカットの開始フレームとして使用する(プッシュスルー、縮小移動、展開、横押し出し)。これにより、前のカットの最終状態と次のカットの初期状態が自然に一致する。
- 720p で効果を確認し、1080p は最終確定後に一度だけレンダリングする。