コンテンツにスキップ
Zenn Dev Satoh Y 0323 Articles 38f0b9d4e4b1fa

AI専用動画編集ツールにクロスフェードを足したら、動画が0.5秒『短く』なった — clipwright v0.16〜v0.17

  • URL: https://zenn.dev/satoh_y_0323/articles/38f0b9d4e4b1fa
  • 日付: 2026-06-25
  • Tier: Tier 3
  • 要旨: AI 専用動画編集 MCP サーバー clipwright にクロスフェード(xfade/acrossfade)と PySceneDetect バックエンド配線を追加(v0.16〜v0.17)。クロスフェード実装の核:重なり部分が「足し算が引き算になる」物理(2.5s + 2.5s = 5.0s が 0.5s ディゾルブで 4.5s に縮む)を JSON エンベロープに正確に反映。ffmpeg xfade フィルタの offset 算術は累積時間から過去の重なり累積を引き、さらに今回フェード長を引くという多段計算で、タイムラインの 2 経路(trim/silence 出力 vs sequence 出力)を共通化。フェード長>クリップ長では短い側にクランプ、warning は生数値埋め込みでなく固定文言+インデックス(CWE-209 防止)。トランジションと字幕の共存時は warning、per-boundary 混在指定は UNSUPPORTED で弾く(v1 では複雑度削減)。シーン検出 0 件時の応答改善:「閾値を 0.15 に下げて再実行」と具体値提示、backend=‘pyscenedetect’ 切替提案、既に floor に達していれば「素材が 1 カット」と別見立てを返す。PySceneDetect 未インストール時エラーは共通ヘルパの ffmpeg 案内を差し替え、pip install scenedetect の正しい手順に統一(モック化したテストで差し替え失敗を検出)。8 日前の自分の実装(シーン検出バックエンド)を未実装と誤認識、着手前の Explore 調査で二重実装を回避。4 周レビュー(ドキュメント嘘・例外漏れ経路・テスト欠落・例外チェーン from None 統一)で、動き/動かない以上の正確性・防御・退行検知を検証。

詳細

トランジション実装の要:クロスフェード(ディゾルブ)では A の終端と B の始端を同じ時間内に重ねるため、物理的には「繋ぎ目を足す」と見えるが動画尺としては「重なった分を引く」。ffmpeg xfade フィルタの offset 指定は「プログラム上の累積時間」ではなく「重なりを考慮した時刻」で渡す必要:累積時間から過去重なり累積を引き、さらに今回フェード長を引く多段計算でぴたりと合致。複数の接続経路(trim/silence の concat vs sequence の concat)が異なる場所で繋いでいたが、AI 利用者に「どの経路でも同じように効く」を実装で担保するため共通ヘルパに統一、分岐で従来 concat か xfade チェーンかを差し替え。フェード長がクリップより長い場合は短い側にクランプ、warning メッセージに生の数値埋め込みでなく固定文言+インデックスで情報露出(CWE-209)防止。トランジション導入で program time が縮むため、字幕・テロップ再タイミング計算が狂う課題は v1 で「同居時に warning」で保留(厳密解は複雑)、per-boundary 混在指定は「ハードカット+ディゾルブ混在で複雑になる割に需要低い」と UNSUPPORTED で明示的削除。実機 e2e 検証:2s + 3s = 5s が 0.5s ディゾルブで 4.5s(ffprobe で測定)。シーン検出の背景:ffmpeg 素朴検出ではカット少ない映像(ゲーム実況)で 0 件。従来メッセージ「Consider lowering the threshold」では AI は「いくつに下げるか」分からない。改善:「現在 0.3、次は 0.15 を試すよ」と半値+floor(0.05) クランプを自動計算、PySceneDetect バックエンド切替提案、floor 到達時は「これ以上下げても無効。素材が 1 カット」と判定切替。warning だけでなく summary 末尾にも同ガイダンス連結し AI が双方読んでも次手に気づく設計。PySceneDetect 未インストール時のエラーは共通ヘルパが ffmpeg (winget install Gyan.FFmpeg) のデフォルト文言を返すが、scenedetect 不在のコンテキストでは的外れ。エラーハンドリングで文言を「pip install scenedetect」に差し替え、テストでモック化した ffmpeg 文言が返された後も最終出力に「pip install」が含まれて「winget」が消えていることを否定 assert で証明(将来コード変更で差し替え失敗を即検出)。