電話リール編集
ここにあるルールのほとんどは、そのステップで実際に失敗したリールから来ています。references/research.md にその理由と情報源があります。references/resolve-ui.md は、コンピュータ操作でDaVinci Resolveを動かすためのコントロールをマッピングしています。
いくつかのケース(HDRソース、30fpsのスローモーション、カメラに向かってのスピーチ、TikTokとShortsのセーフボックス、カバー)は、まだ公開されたリールでテストされていません。それらのコマンドはテストクリップでのみ実行されました。references/other-cases.md にそれらをまとめ、それぞれの確認方法を記しています。編集がこれらのケースに依存する場合は、ユーザーにその旨を伝えてください。
パイプライン:電話ソース → ffmpegでカット・手ぶれ補正 → カラー調整(DaVinci Resolve、またはフレーム全体の調整には scripts/grade.py) → Remotionでテキスト追加 → ffmpegでサウンド・マスタリング。
カット前
- クライアントのブランドルールがあれば読む:禁止ワード、連絡先、AIラベリング、投稿前に承認が必要なもの。
- すべてのソースクリップをチェック:
python -I scripts/probe_source.py clip.mp4。これにより、回転、フレームレート(変動の有無)、SDR/HDR、カラータグ、オーディオが報告され、カット前に必要な処理がリストアップされます。一般的な電話クリップはSDR bt709、約30または60fpsです。HDR、可変フレームレート、30fpsソースはそれぞれreferences/other-cases.mdに記載された追加のステップが必要です。背景での会話がある場合は元の音声をミュートにします。カメラに映っている人が視聴者に話しかけている場合は、同じファイルのスピーチセクションを参照してください。 - レビュアーとして別のAIモデルを使用する場合は、決定前にそのモデルとアイデアについて議論し、その内容を検証してください。
references/research.mdに、レビュアーモデルが犯した種類の間違いがリストされています。
ペース
- リールごとに一つのアイデア。テキストが長さを決めます。目標の秒数ではありません。テストリールでは、クライアントが10.5秒や13.5秒で読み終えられなかったため、18.6秒が必要でした。
- 各行が表示されてから、1秒あたり10アラビア文字を予算とします。これは意図的に遅く設定されています。視聴者は電話の画面も同時に見ているからです。
- 可能であればショットごとに2つのリビール(テキスト表示)。その間は少なくとも1.5秒。同時に表示される行は1つのリビールとしてカウントします。
- ネイティブリーダーによるペースの判定は、どのモデルの判定よりも優先されます。
- 最も強いビジュアルとフックテキストはフレーム0で画面に表示され、フェードインはありません。
- 突然の3倍速は避けてください。代わりに悪い瞬間を穏やかにランプアップしてください。
60fpsを0.5倍速で再生すると、実フレームが30fpsになるため、補間は不要です。30fpsのソースには余分なフレームがないため、スローモーションにする前に references/other-cases.md のスローモーションセクションを読んでください。60fpsの中間ファイルに手ぶれ補正をかけ、その後リタイムします:
ffmpeg -ss S -t D -i raw.mp4 -vf "vidstabdetect=shakiness=6:accuracy=15:result=x.trf" -f null -
ffmpeg -ss S -t D -i raw.mp4 -vf "vidstabtransform=input=x.trf:smoothing=14:zoom=2:optzoom=0:interpol=bicubic,crop=W:H:X:Y,scale=1080:1920:flags=lanczos,fps=60" -an -c:v libx264 -preset veryfast -crf 10 -pix_fmt yuv420p im.mp4
python -I scripts/retime.py im.mp4 c1.mp4 --start 0.4 --frames 99 --keys 0:.5
scripts/ へのパスはこのスキルのフォルダから実行します。ffmpegはvidstabフィルタを必要とします。すべてのクリップは時間ゼロから開始する必要があります。ゼロ以外の開始時間はResolveで先頭に黒フレームとして表示されます。-ss と時間フィルタを併用する場合は setpts=PTS-STARTPTS を追加し、start_time をffprobeで確認してください。
静止ショットの最後のフレームに手が映り込む場合は、前のフレームを保持して隠します:trim=end_frame=N,setpts=PTS-STARTPTS,tpad=stop_mode=clone:stop_duration=0.6。
カラー
ここでのカラーは補正を意味します:ニュートラルな白、自然な肌、正確な商品色、ショット間のマッチング。創造的なルック(ルックアップ)は最後に、控えめに適用します。適用後も商品の色は正確に測定できる必要があります。
ショットのニーズに応じてルートを選択します:
- フレーム全体の調整のみ(色かぶり、露光、コントラスト、彩度):
scripts/grade.pyを使用。高速で再現性があり、数値は再実行可能なコマンドに残ります。 - フレームの一部を個別に調整する必要がある場合(異なる光の下での肌、一つのオブジェクト):DaVinci Resolveとそのパワーウィンドウを使用。
どちらのルートも、「測定 → 調整 → 測定」のループと以下の同じターゲットを使用します。
grade.py を使用する場合
python -I scripts/grade.py still c1.mp4 1.5 before.png
python -I scripts/measure_grade.py before.png --patch counter:40,60,200,220 --skin 100,1450,1000,1920
python -I scripts/grade.py make c1.cube --frame before.png --neutral 40,60,200,220 --white 205 --contrast 1.06 --pivot 0.4 --lift -0.02
python -I scripts/grade.py still c1.mp4 1.5 check.png --lut c1.cube --compare
python -I scripts/grade.py apply c1.mp4 c1g.mp4 --lut c1.cube
--neutral はグレーまたは白であるべきパッチです:カウンター、壁、紙、白い蓋。make はそのR、G、Bを均等化し、--white は最終的なレベルを設定します。均等に照明が当たり、白飛びしていないパッチを選択してください。--compare フレームをフルサイズで確認し、グレーディングされた半分を測定してから適用します。ショットごとに1つのLUT。各ショットには独自の色かぶりがあるためです。
ゲインがハイライトを250以上に押し上げる場合は --knee 0.85 を追加します。--denoise light は目に見えてノイズの多い低照度クリップにのみ使用し、--sharpen は稀に使用します:スマートフォンは既にシャープネスをかけており、これ以上はエッジやテキストにハローを発生させます。
Resolveで作成したグレードはLUTとしてエクスポートできます:カラーページでクリップのサムネイルを右クリック → Generate LUT → 33 Point Cube。その後 grade.py apply --lut で任意のクリップに適用できます。LUTはフレーム全体の調整のみを含むため、ウィンドウは含まれません。
DaVinci Resolve (無料版)の場合
クリップをResolveがアクセスできるプレーンなフォルダにコピーします(一部のアプリデータフォルダは開けず、「パスが存在しません」と表示されます)。新しいタイムラインに配置し、パレードスコープを開きます。
各ステップは前のステップに依存するため、以下の順序で作業します:
- バランスノード。ゲインで白レベル、Tempで色かぶりを調整。Positive Tempで暖かくなります。2つのショットで同じ表面は一致している必要があります。
- コントラストノード。コントラストとピボット、ディープブラック用のリフト、彩度は5以下の小さな調整。
- サブジェクトノード(全体の調整が他の部分に悪影響を及ぼす場合のみ)。ソフトなパワーウィンドウを使用。テストリールでは、ウィンドウが手の肌を修正し、商品の色に影響を与えませんでした。
- レンダリング、測定、調整、繰り返し。2回のパスで十分でした。
python -I scripts/measure_grade.py frame.png --patch counter:40,60,200,220 --skin 100,1450,1000,1920
ターゲット値
- ニュートラルな表面:R、G、Bの差は約3~5以内。白は明るい見た目で約195~215。
- 肌の色相:約123度。自然に保ってください。ベクトルスコープの線は参照であり、ターゲットではありません。
- 肌の明るさ:ガイドによると、肌とシーンに応じて40%~70%。その範囲を間違いの発見に使い、厳密な数値として使いません。
- ハイライト:250以上のピクセルは全体の約2%未満。
- 彩度:
chromaラインを前後で比較。補正後のp95は補正前と近い値であるべき。大きなジャンプは、グレードがシーンにない色を追加していることを意味します。 - 商品の色:動画が商品を販売する場合、正確であること。
- 同じ表面の2つのショットは同じ測定値になること。
何が何を動かすか:
- Tintは赤くなった手のひらをほとんど動かしませんでした。チャンネルごとのGammaで修正:Gを上げ、RとBを少し下げる。
- Temp +300は青かぶりを超過しました。+130が正解でした。小さく始めてください。
Remotionによるアラビア語テキスト
assets/reelTemplate.tsx は動作するテンプレートです。各テキストブロックをデータとして保持し、テキストチェック用のプローブコンポジションを持っています。references/remotion-setup.md は、ゼロからプロジェクトを開始し、コンポジションを登録する方法をカバーしています。
ルール:
- 太字のアラビア語フォント(テンプレートではAlexandria 800)、白+アクセントカラー1色、ボックスなし、ソフトシャドウ。
- 1080x1920フレーム上でサイズ62~124 px。電話ではこの大きさが必要です。
- アラビア語の行ボックス1.5。1.22では文字のテールが次の行に接触します。
- すべての文字はx 110-950、y 220-1475の範囲内に収める。これにより、Instagramの右レールと下部バーが何も覆いません。
whiteSpace: nowrapで、予期せぬ折り返しを防ぎます。- フック(最初のテキスト)はフレーム0にオン。後続の行は約1秒間隔で、6フレームの立ち上がりとフェード。
- テキストの後ろにソフトな暗い帯を配置し、下の被写体が見えるようにします。
- 顧客の引用はそのまま使用し、顧客が同意しない限り名前や写真は追加しません。
- 視聴者が見ているものを説明します。ラベルが唯一の選択肢であると示唆しないでください。
テキストを変更した後、プローブフレームをレンダリングしてチェックします:
npx remotion still ReelProbe out/p0.png --frame=0
python -I scripts/check_text.py out/p0.png out/p1.png out/p2.png out/p3.png
2行のインクが14px以内に近づいたり、文字がセーフボックスからはみ出したりすると、エラーが発生します。1ブロックに最大7行まで保持できます。
次に、実際の画像に対してテキストをチェックします。各ショットの最後のフレーム(すべての行が表示されているとき)をレンダリングし、それらのフレームを同じ順序で渡します:
npx remotion still Reel out/r0.png --frame=119
python -I scripts/check_text.py out/p0.png out/p1.png --real out/r0.png out/r1.png
各行は、その文字の周囲の最も明るい部分に対するコントラスト値を取得し、3.0未満で失敗します。テストリールでは、アクセントカラーの行は3.2~4.6、白い行は5以上でした。低いスコアは、テキストの後ろに強い帯を追加するか、ブロックを移動することを意味します。
デフォルトのボックスはInstagramのものです。TikTokやShortsにも投稿するリールの場合は、--platform all を追加してください。これらの2つのボックスはサードパーティのガイドに基づいているため、各アプリでアップロードをプレビューしてください。
その後、各ショットの終わりのフルサイズフレームを確認してください。サムネイルシートでは衝突が隠れ、テキストの背後で動くものはフルサイズでのみ表示されます。テストリールでは、スプーンが線と交差しました。コーナーを起点とした小さなズームでそれを避け、ついでにはみ出た指もクロップしました。
レンダリングとサウンド
npx remotion render Reel out/reel.mp4 --codec=h264 --crf=15 --muted --color-space=bt709
python -I scripts/beat_offset.py music.ogg --cuts 3.3,6.5,10.3 --length 13.5 --from 0 --to 40
--color-space=bt709 は重要です。これがないと、Remotionは未知のプライマリを持つフルレンジのbt470bgを書き出します。
最適なオフセットから音楽をカットし、最後の1.2秒をフェードアウトし、-c:v copy で結合してからマスタリングします:
sh scripts/master.sh in.mov out.mp4 -14 0.4 0.75
最後の数字はリミッターの天井です。AACはその上にオーバーシュートを追加し、その量はトラックに依存するため、スクリプトは書き込まれたファイルを測定し、そのラウドネスとトゥルーピークを表示します。TOO HOT(トゥルーピークが -1 dBTP より高い)と表示された場合は、0.7で再実行します。
電話のスピーカーは300Hz以下のほとんどの音を失うため、その帯域をチェックします:
ffmpeg -hide_banner -nostats -i out.mp4 -vn -af "highpass=f=300:poles=2,highpass=f=300:poles=2,lowpass=f=12000,ebur128" -f null - 2>&1 | tail -12
-14 LUFSマスターで、その帯域で-20 LUFS以上を目指します。ベースの重いトラックは-23.9を測定し、電話ではこもって聞こえました。波形とスペクトルも描画してください。レビュアーモデルのタイムスタンプが常に一致するとは限らないためです。
AI生成の音楽や音声には、プラットフォームのAIラベルが必要です。リールより少し長めに音楽を生成してください。カットが短すぎると、きれいに延長できません。
完了前のチェック
- ffprobeが
yuv420p, tv, bt709, bt709, bt709、正しい長さとフレーム数を表示すること。 check_text.pyが--realフレームを含めてPASSと出力すること。master.shが-1 dBTP以下のトゥルーピークを出力したこと。- リールがプロフィールグリッドに表示される場合、カバーフレームが存在すること(
references/other-cases.md参照)。 - フルサイズのフレームを自分で確認すること。最初と最後のフレーム、各カットの直前のフレームを含みます。
- レビュアーモデルが最終的なmp4を視聴する場合、既に行われた決定をモデルに渡し、再検討させないこと。
- チェックされていないことを明記すること。エージェントは音声を聞いたり、電話でファイルを確認したりすることはできません。
- すでにどこかにアップロードされているファイルを置き換えた後は、再アップロードし、公開リンクから確認し、古いファイルを指しているスケジュールされたものをすべて更新すること。
公開にはクライアントの承認が必要です。