オートパイロット - ユーザーが /short-form-video-editor と入力した場合の動作
ユーザーが動画(およびオプションでロゴ画像)をアップロードし、コマンドを入力します。質問せずに作業全体を実行してください。何かが本当にブロックされた場合(動画が見つからない、ffmpegがないなど)のみ停止します。コマンドの後の追加テキストはスタイル/ブランドのメモとして適用します。
- 入力の検索: セッションアップロード内の最新の動画(
ls -t /root/.claude/uploads/*/*.{mp4,mov,webm}またはメッセージに指定されたパス)。ロゴ = 添付画像があればそれ(なければ、透かし/ヒーロー/アウトロロゴをスキップし、クリーンなテキストなしのアウトロを使用)。言語 =asr_chunks.py ... autoで自動検出。 - ツールキットの特定: このスキルのフォルダ(このSKILL.mdを含むディレクトリ)に
template/があります。新しいプロジェクトフォルダで作業:セッション内にVideo-editingリポジトリのクローンがある場合は、その中にprojects/<slug>-<YYYYMMDD>/として作成。そうでなければスクラッチパッドに作成。cp -r template/. <project>/。 - 依存関係の確認/インストール(一度だけ):
ffmpeg、Node + Playwright Chromium(/opt/pw-browsers、playwright installは実行しない)、pip install numpy pillow sherpa-onnx、scripts/fetch_asr_model.sh。Huggingfaceへのネットワークは不可。GitHubリリース、npm、PyPIは利用可能。 - 以下のワークフローを最初から最後まで実行し、自身でデザイン判断を行う(ブランドカラーはロゴから取得。ロゴがない場合はコーラル/ティールのテクニカルパレット。シーンは
reference/scene-patterns.mdから、実際の発言に合うものを選択)。 - 成果物の提供:
SendUserFileでmp4を送信(レンダリング結果を表示)。その後、簡単なサマリー:スペック、追加したグラフィック、低信頼度の文字起こし箇所(耳で確認する必要あり)、映像解像度の注意点、「音声は確認していない」旨を記載。プロジェクト(work/ディレクトリを除く)と最終mp4をリポジトリに保存し、セッションで指定されたブランチ(指定がない場合はmain)にプッシュ。依頼がない限りPRは作成しない。 - 60秒の動画で約15〜25分(文字起こし約3分、レンダリング約4分、エンコード約2分)かかると見込む。開始時にユーザーに1行でその旨を伝え、その後は完了まで静かに作業する。
ダブモード - 翻訳 + 新しい音声 + リップシンク(Glowクリップで一度テスト済み:アラビア語→英語)
ユーザーが「口が言葉に合わせて動くように」別の言語での動画を希望する場合に使用。
- スクリプト: 編集モードと同様に文字起こしと確認を行い、その後自分で翻訳を
data/phrases.<lang>.jsonとして作成 =[[win_start, win_end, "text with *key words and DISPLAY|spoken overrides (多単語トークン内はNBSP)"], ...]。元のフレーズウィンドウはそのまま維持し、カメラ/グラフィックのビートが生き残るようにする。近接するウィンドウはマージしてもよい。英語の場合、1ウィンドウあたり約2.5〜3語/秒を予算とし、詰め込みすぎず、意味を保持し、新しい主張は追加しない。発音オーバーライドの例:*COSRX|Cosrex、Axis-Y|Axis\u00a0Y。 - モデル:
scripts/fetch_dub_models.sh(確認用にfetch_asr_model.shも)。 - 音声(デフォルト = 話者にクローン):
work/ref.wavを作成 = 話者の元の音声からポーズで区切られたクリーンなクリップを4〜5個(約15秒、16kHzモノラル、連結)。python3 -I scripts/tts_clone.py data/phrases.en.json work/ref.wav 8 <total_seconds>->work/voice_en.wav+ 実際の音声スパンを含むdata/transcript.source.json。YourTTS(coqui、fetch_dub_models.shでダウンロード)が音色をゼロショットでクローン。スクリプトは行ごとにNテイク生成し、Whisperの読み返しがスクリプトに最も一致するテイクを保持し、タイムストレッチ(0.72〜1.25倍、ピッチ保持)で元のウィンドウの約90%を埋める。Glowクリップでの実績:中央ピッチ144 Hz(話者154 Hz、ストックKokoro音声123 Hz)、長期スペクトル類似度0.96(対0.90)、全行が正しく読み返される。ブランド名はDISPLAY|spokenで発音を指定し(スコアリングから除外 - 自動)。フォールバックtts_phrases.py= ストックKokoro音声(明瞭だが話者の声ではない)。アクセント:モデルは音色/ピッチを転送するが、ネイティブアクセントは転送しない。「エジプトなまりの英語」を約束せず、達成された内容を説明する。 - 元の解像度フレームへのリップシンク:
ffmpeg -t <end> -i src -vf fps=30 work/raw/%05d.png;ffmpeg -i work/voice_en.wav -ac 1 -ar 16000 work/en16k.wav;MODELS=work/models python3 -I scripts/lipsync2.py work/raw work/en16k.wav work/ls --model wav2lip_gan_96.onnx --enhance 0.7(最初に--range a bでテスト。4CPUで1700フレームの場合、フル実行約25分:Haarボックス、全フレームの2dfan4ランドマーク、次にフレームごとにWav2Lip + GFPGAN)。lipsync2 = ランドマークアライメント済みFFHQ-512クロップ、スムーズ化ランドマーク、ランドマーク顔ボックス上のWav2Lip、GFPGAN復元を0.7でブレンド、口形状マスク(鼻には触れない)、貼り付け。その後scripts/01b_upscale_lipsynced.sh。古いlipsync.py(粗いHaarクロップ:ぼやけた唇、舌のようなアーティファクト - ユーザーから「非常に悪い」と評価)は使用しない。EDTalk-256も試したがより悪い(幽霊のような口)。モデル:facefusion-assetsのGitHubリリースから2dfan4、gfpgan_1.4、wav2lip_gan_96。 - 視覚的同期確認: 各タイルの下にオーディオエンベロープを重ねた口のコンタクトシート。無音ギャップでは口が閉じており、オーディオバーが上がっているときに開いて変化している必要がある。ピクセル相関メトリクスはノイズが多すぎるため、これに依存しない。
- グラフィックス:
python3 -I scripts/build_transcript.py work/en16k.wav(英語のソースjsonではmax_charsを約22に設定)、composition/transcript.jsを再生成、その後scene.jsのコピーとトリガーワードを新しい言語で書き換え(LTR:.row/.chunkの方向をltr、Interフォント、ストライク原点左、フロー矢印左→右)。多単語トークンは文字起こし内では別々の単語:単一単語を検索(ts('skin',0,43.5))、ts('your skin')は不可。 - 通常通りレンダリング(
LAST_SRC_FRAME=<n> scripts/02_render_all.sh、キュー、SFX)し、VOICE=work/voice_en.wav OUT=out/name-en.mp4 scripts/03_mix_and_encode.shでミックス。 - サマリーで正直に報告: Wav2Lipは約100pxの顔で柔らかくややぼやけた口(近くで見るとわかる)、頭や手の動きは元の話者のまま、音声は合成音声、話者は自分の肖像が吹き替えられたバージョンを承認すべき、AI吹き替えとラベル付けを検討すべき。低信頼度だったソースの翻訳フレーズがあれば名前を挙げる。
ショート動画エディター(キャプション + モーショングラフィックス + SFX)
2つのモード:編集(言語を維持し、キャプション/グラフィックス/SFXを追加)とダブ(別の言語に翻訳、新しい音声、新しい音声に合わせて唇を再アニメーション - ユーザーが英語/翻訳/吹き替え/リップシンクと言ったときに起動)。57秒のエジプトアラビア語薬局プロモーション(Glow Cosmetics)で実証済みのパイプライン。出力:1080x1920 @30、H.264/AAC、-14 LUFS。
動作例プロジェクト:https://github.com/MuhammadToffaha/Video-editing の projects/glow-kbeauty-reel/
「プロフェッショナル、テンプレートではない」を定義するルール
- 話者、声、意味をそのまま保持する。主張(数値、「100%」、価格)をでっち上げない。グラフィックに話されていないテキストが必要な場合、汎用的なものにする(カテゴリ名、見出しラベル)。
- すべてのビジュアルは話されたフレーズをサポートし、単語でトリガーされる(
ts('word'))。フレーズの開始ではない。カードは次のカードが入る前に終了。重なるゴーストはなし。 - 1つのビジュアル言語:ブランドカラー(ロゴからサンプリング)+ 白 + ダークインクガラスパネル、ラテンラベルはInter、見出し/キャプションはCairo(アラビア語)。ミントは成功状態のみ。
- レイアウトゾーン(1080x1920、話者の顔はおよそy 790-1110):カードはy 235-735(1.15倍ズーム後も顔の上には決して重ならない)、キャプションはy~1545、下部220pxと上部130pxは主要コンテンツを置かない(プラットフォームUI)。ソースごとに顔の位置を再確認。
- 保持デバイス(適度に):文の開始時にはパンチインスナップ(1.12-1.15倍)とその間のゆっくりしたドリフト、2〜4秒ごとにグラフィック、アクティブワードキャプションハイライト、打ち消し線/チェック/カウントアップマイクロアニメーション、ブランド名が言われたときのヒーローロゴモーメント、ブランドエンドカード。
- SFX:カードイン時にウーシュ、要素にポップ/チック、成功時にチャイム、ロゴにサド。音量は音声の約-10dB。ユーザーが提供しない限り音楽はなし。
ワークフロー
- 検査:
ffprobe、コンタクトシート(ffmpeg -vf "fps=1/6,scale=239:-1,tile=5x2")、末尾のエンドカード(WhatsApp/CapCutの黒フレーム)を見つけ、話者の位置を記録。ソースは通常低解像度(スマートフォン/WhatsApp):lanczosでアップスケールし、映像はソフトになるがグラフィックはシャープなままであることをユーザーに伝える。 - プロジェクト:
cp -r <skill>/template/. my-project/ && cd my-project;cp <logo> assets/;python3 -I scripts/extract_logo.py assets/logo_original.png assets/logo_white.png(ブランドの16進コードを出力)。composition/style.cssと#wm/#outroの--coral/--brandを更新。 - 準備:
END=<トリム秒> scripts/01_prepare.sh input.mp4(フレーム、16kHz wav、音声)。 - 文字起こし(サンドボックス内でHFアクセス不可。GitHubリリースは使用可能):
scripts/fetch_asr_model.sh。その後python3 -I scripts/asr_chunks.py work/asr16k.wav <lang|auto> 3.2 a、2.4と4.5で繰り返し。Whisperはチャンク末尾を切り捨てる。3つの仮説を自分でマージし、自身の言語知識で修正。- 不確かな単語/ブランド名:
python3 -I scripts/asr_probe.py work/asr16k.wav ar,en 14.0-16.8 14.5-16.6 ...(enパスはラテンブランド名のスペルを出力)。重複するウィンドウ間で一貫しているもののみ信頼。残りは最終メッセージとREADMEで低信頼度としてリストアップ。推測された名前に基づいてグラフィックを作成しない。
- タイミング:
python3 -I scripts/pauses.py work/asr16k.wav-> ポーズが信頼できるフレーズ境界。data/transcript.source.jsonを[start, end, "text"]フレーズとして作成(data/transcript.source.example.json参照。*word= アクセントピル。多単語ラテン名内ではNBSPを使用。RTLテキスト内のラテンブランド:アラビア語の接頭辞وをブランドに接着させない、و Brandと記述)。その後python3 -I scripts/build_transcript.py work/asr16k.wavとecho "window.TRANSCRIPT=$(cat data/transcript.json);" > composition/transcript.js。これにより、各フレーズ内の音節重みで単語時間を分配し、エネルギーの谷にスナップさせ、バランスの取れた2〜4単語のキャプションチャンクを作成。健全性チェック:無音内に単語開始がないこと。 - シーンのデザイン:
composition/scene.jsで(reference/scene-patterns.md参照)。card(t0,t1,{y,h,html})、pop、fade、draw、cue、tsを使用。サンプルシーンをパターンとして使用:フックカード、ブランドチップ(各名前が言われたときに埋まるスケルトンスロット)、カテゴリタイル、移動ドット+チェック付きA→Bマッチ図、打ち消し線チップ、フローノード、星評価、チェックリスト行、ロードマップ、棒グラフ、トラストリング、ヒーローロゴリビール、ブランドアウトロ。finish(<seconds>)を設定 = 音声終了 + アウトロ約1.7秒。 - レンダリング + QA: 最初にいくつかのテストフレームをレンダリング(
node scripts/render.mjs <f> <f+1> work/test)、Pillowでコンタクトシートを作成し、確認。その後scripts/02_render_all.sh(4ワーカー、合計約8 fps)、node scripts/render.mjs cues work/cues.json && python3 -I scripts/sfx.py work/cues.json work/sfx.wav、OUT=out/name.mp4 scripts/03_mix_and_encode.sh。ソースがエンドカードで終わる場合、LAST_SRC_FRAME=<n>を渡して最後のクリーンなフレームでフリーズ。 - 成果物の提供: mp4を送信(SendUserFile)、スペック、低信頼度の文字起こし箇所、映像解像度の限界、および音声は耳で確認していない(聞くことができない)こと - ラウドネスメーターと開始対エネルギーテストのみで確認したことを記載。
すでに解決済みの落とし穴(再学習しないこと)
- Pythonの
str.split()はNBSPで分割する -split(' ')を使用(build_transcript.pyでは既にそうなっている)。 - SVG
<rect>のアニメーションにCSSscaleYを使用すると、ヘッドレスChromiumで反転/オフセットする - 代わりにattr:{y,height}をトゥイーンする。ストローク描画:draw(path,t,d)。 - 非表示で開始する要素にはCSS
opacity:0(クラスhid)とimmediateRender:falseのトゥイーンが必要。すべてのトゥイーンはシーク可能でなければならない(ワーカーは開始フレームに直接ジャンプする)。 backdrop-filter付きのカードは、ビデオフレームが同じページ(#bgimg)にある場合のみブラー効果がかかる - そのためフレームはページ内で合成される。- 空のブラーカードは壊れて見える:トリガーワードでカードを開始するか、話されたときに光る薄暗いプレースホルダー行/スロットを表示する。
- アラビア語には実際の形状が必要:Chromium + Cairo woff2(unicode-rangeでアラビア語/ラテン語を分割)は機能する。Pillow/ffmpegのdrawtextは機能しない。
- sherpa-onnxのWhisperには単語タイムスタンプがなく、末尾を切り捨てる。そのため短いウィンドウ+ポーズアンカリングが必要。
- opencv 5.xには
CascadeClassifierがない(4.10.0.84に固定)。Haar顔ボックスは手/シャツに誤検出があり、約30%のフレームを見逃す -> 中央値ボックス外れ値除去+ROIセカンドパス+補間(lipsync.pyでは既に実装済み)。 - Kokoro/WhisperスタイルのTTSは
COSRXを「シーオーエスアールエックス」と読み上げる:DISPLAY|spokenオーバーライドを使用。 - GitHub MCP
create_repositoryは403になる可能性がある - ユーザーにリポジトリを作成してもらい、その後add_repo+ クローン(パスが存在する場合は新しいディレクトリにクローン)。