Claude Code で組んだ動画編集の自動化パイプラインを、実装レベルで解説します。 動画編集の話に見えますが、本質は「自分が毎回やっている手作業を、どう仕組みに移すか」です。 その型はそのまま、皆さんの別の作業にも使えます。
入力は画面収録のmp4が1本だけです。カットもテロップも何もしていない、撮ったままのファイルを置きます。 出力は「編集済みの動画」ではなく、Premiere Proにそのまま読み込めるプロジェクト一式です。
収録した mp4(32分51秒) │ ├─ preprocess ──→ 音声を抜いて正規化・無音を検出・文字起こしを用意 │ audio_normalized.wav / silences.json / transcript.json │ ├─ cut-analyze ──→ フィラー(えー、あのー)と どもり を機械検出 │ filler_cuts.json / cut_review.md │ ├─ AI判断(Claude)→ 言い直し・失敗テイク・冗長を読んで判断 │ ai_cuts.json + テロップの誤認識を校正 │ ├─ cut-apply #1 ─→ カット計画を確定(ここでテロップのlintが走る) │ cut_plan.json … 1971.7秒 → 1582.2秒 / 132クリップ │ ├─ plan-scaffold ─→ オープニング・スライド・インサート・Bロールの計画 │ ├─ retention ────→ 「30秒以上なにも変化しない区間」を検出して演出を提案 │ ├─ character ────→ 右下のキャラを口パクさせてアルファ付き動画に │ ├─ cut-apply #2 ─→ 全トラックを配線 │ Telops / Topic / Character / Slides / Inserts / Broll / Mosaic │ ├─ program-gate ─→ 必要な素材が全部あるか機械が検査(無ければ止まる) │ └─ editor_package → 編集者へ渡す単一ZIP(XML+参照素材+リンク修復ツール)
このパイプラインは、最終的な動画ファイルを書き出しません。出すのは Premiere が読む
timeline.xml(Final Cut Pro 7 XML・xmeml v4形式)と、それが参照する素材です。
理由は3つあります。
| 理由 | 中身 |
|---|---|
| 直せる | 焼き込んだ動画は直せない。XMLなら編集者が1カットだけ動かせる。AIの判断が外れた箇所を人が上書きできる |
| 速い | 32分の動画を書き出すと数十分かかる。XMLなら数秒。試行錯誤の回転が段違いに上がる |
| 渡せる | 編集者は普段のPremiereで作業できる。専用ツールを覚えてもらう必要がない |
ここが応用の要です。「AIに最後までやらせる」と考えると、人が直せない成果物ができます。 AIには"人が直せる中間物"まで作らせて、最後の判断を人に残すと、精度が足りなくても実用になります。 このパイプラインが実務で回っているのは、AIが賢いからではなく、外したときに直せる形にしてあるからです。
フォント・色・サイズ・AIの生成指示まで、見た目に関わる値はすべて config/style.json にあります。
コンポーネントやスクリプトを直接書き換えることは禁止にしています。
pipeline.silenceNoiseDb = -30 # これより静かなら無音とみなす
pipeline.silenceMinDurationSec = 0.45 # 0.45秒以上続いたら無音区間
pipeline.jetcutPadSec = 0.1 # 切り口の前後に残す余白
pipeline.jointFadeMs = 12 # 繋ぎ目の音のフェード
pipeline.cut.minKeepSec = 0.45 # これより短い"残し"は作らない
pipeline.cut.maxAiCutRatio = 0.25 # AIが切ってよい上限は全体の25%まで
最後の maxAiCutRatio が効きます。AIが暴走して動画の半分を削る事故を、構造的に防ぐためのものです。
AIに判断させるなら、判断できる範囲そのものに上限を置く——これは動画に限らず使える考え方です。
「無音を切る」だけだと、実際には使えません。喋っていない映像、言い淀み、言い直しは無音にならないからです。 このパイプラインは4つの層で別々に判定します。
| 層 | 何を切るか | 判定の方法 | 今回の実測 |
|---|---|---|---|
| ① 無音 | 音が止まっている区間 | ffmpeg の silencedetect(−30dB・0.45秒以上) | 91.0秒 |
| ② 非発話 | 音はあるが喋っていない区間 | 文字起こしの語の時刻と突き合わせ、語が無い区間を検出 | 214.0秒 |
| ③ フィラー | 「えー」「あのー」やどもり | 語彙辞書+前後の間の長さで孤立度を判定 | 14.6秒 |
| ④ AI判断 | 言い直し・失敗テイク・冗長 | Claude が文字起こし全文を読んで判断 | 69.9秒 |
注目してほしいのは②が一番大きいことです。無音カットだけの自動編集ツールは多いですが、 実際の画面収録で一番多いのは「操作しながら黙っている時間」です。これは音があるので無音検出では取れません。 文字起こしの単語ごとのタイムスタンプを持っているから、ここを切れます。
機械が判定できない領域だけをAIに回します。AIに渡すのは cut_review.md
という中間ファイルで、全セグメントが時刻つきで並び、機械が拾った候補に印が付いています。
[# 34 180.44- 185.86] あとは僕自身サムネイルとかアイキャッチ画像を作る (→間24.58s)
[# 35 210.44- 214.74] 作る方法であったり仕組み、あとは僕自身がですね
「作る」で切れて24.58秒の間があり、次で言い直している——これは機械には判定できません。
AIは ai_cuts.json に理由つきで書きます。
{"startSec": 180.44, "endSec": 185.86, "kind": "retake",
"reason": "「作る」まで言って24.58秒の間。#35が言い直しているので言いかけ側を落とす"}
理由を必ず書かせるのが肝です。後から「なぜここが切れたのか」を人が検証できます。 今回の実測では、終盤で締めの挨拶を4回言い直しているのをAIが見つけ、最初の1回だけ残しました。
全発話にテロップを入れる方針(フルテロップ)です。問題はどこで改行するかで、 ここが雑だと一気に素人っぽくなります。
悪い例:
❌ 「実際にどのような形でサムネイルを作ってきたかみたいな感じの」
「苦労話を」 ← 短すぎる断片
「交えて実際に結構大事な」
これを防ぐため、BudouX(Googleが公開している日本語の文節分割ライブラリ)で文節を認識したうえで、 8種類のlintルールを機械でかけています。
| ルール | 検出する崩れ | 強さ |
|---|---|---|
short-fragment | 断片が短すぎる | hard(止まる) |
no-before-noun | 「〜の」で行が終わり、次が名詞 | soft(警告) |
head-particle | 行頭が助詞で始まる | soft |
adnominal-tail | 連体修飾で行が終わる | soft |
predicate-tail | 述語の途中で切れる | soft |
compound-split | 複合語が途中で割れる | soft |
hard違反が1件でもあると cut-apply が止まります。納品基準は0件です。
今回も実際に1件で止まり、直してから先に進みました。
AIは文字起こしの誤認識も直します。今回は40箇所を校正しました。
瀬野アオ → セナオ ← 名前の誤認識(公開面に出るので最重要)
2Dカテゴン風 → 2Dカートゥーン風
相決画像 → 素材画像
周囲化を目的 → 収益化を目的
キャンバー → Canva
クロードコード → Claude Code
short-fragment 違反を直したときも、「の」を削除せず次の行頭へ移動しました。
校正は「置き換え」だけ。削除と要約は禁止——これは何度か失敗してから機械の検査項目にしました。
画面収録をそのまま出すと、APIキー・メールアドレス・本名・ファイルパスが映り込みます。 1回でも出せば取り返しがつきません。ここは人の注意力に任せず、機械で塞いでいます。
動画 ──1fpsでフレーム抽出──→ PNG(1,972枚)
│
├─ OCR(macOS Vision・無料・画面の文字に強い)
│ ※ Tesseract へのフォールバックあり
│
├─ NGパターン照合(20パターン)
│ 正規表現8種:メール / OpenAIキー / Google APIキー / AWS /
│ GitHubトークン / Slackトークン / Bearer / 電話番号
│ + ローカル辞書(本名など・git管理外に分離)
│
├─ スパン統合(連続するヒットを1区間にまとめる)
│ 検出43件 → 27スパン
│
└─ mosaic_review.md(チェックボックス+サムネ画像つき)
既定は全件 [x]=安全側。確認して --approve で確定
設計で効いているのは次の3点です。
クラウドのOCRに画面を送ると、秘密を隠すために秘密を外部送信することになります。 macOS 内蔵の Vision なら、ローカルで完結し、無料で、画面の文字に強い。
レビューファイルは最初から全件チェック済みで生成されます。人は「外す」判断だけをする。 逆(既定OFFで必要なものを選ぶ)にすると、見落としがそのまま漏洩になります。
演出を塞がないよう自動適用には件数上限がありますが、本名・APIキー・手動指定は上限の対象外で必ず全件適用されます。 今回も「秘匿必須25件は上限の対象外として全件適用」と出ています。
ng_keywords.local.txt / ng_patterns.local.json という
ローカル専用の辞書に分離し、git管理外にしています。検査ルール自体をリポジトリに置くと、
そこから秘密が漏れるためです。
画面右上に出る「トピック|◯◯ / 内容|◯◯」のカードです。テレビ番組の画面構成を真似たもので、 視聴者が途中から見ても何の話か分かるようにする役割があります。
仕組みは拍子抜けするほど単純です。work/<name>/topic_title.txt に2行書くだけ。
サムネ自動生成
動画を入れるだけ
このファイルが存在すれば、cut-apply が Topic トラックとして自動配線します。
ラベルの「トピック|」と「内容|」はコンポーネント側が付けるので、中身だけ書きます。制約は各行14字以内・体言止め・句読点なし。
文言は文字起こしからAIが自動で決めます。直したければ、テキストファイルを書き換えて cut-apply を再実行するだけ(1〜2分)。
「ファイルの有無で機能をON/OFFする」——この設計はパイプライン全体で使っています。
character_mode.txtにonと書けばキャラが出る、topic_title.txtがあればトピックが出る。 設定画面もフラグ管理も要らず、人もAIも同じ方法で操作できます。
画面右下でキャラクターが喋りに合わせて口を動かします。普通なら音声解析(Rhubarb など)が要りますが、 既定では音声を解析せずに作っています。
すでに単語ごとのタイムスタンプ付き文字起こしを持っているので、これを使います。
結果は Rhubarb 互換の mouth_cues.json になります。外部API不要・追加依存ゼロ・処理は一瞬。
精度が要る回だけ --engine rhubarb で本物の音声解析に昇格できます。
レンダリングはアルファ付き ProRes 4444(character_layer.mov)で書き出し、
cut-apply が Character トラックとして重ねます。
-c copy)します。さらに完成済みチャンクはマニフェスト照合して再利用するので、
途中でクラッシュしても続きから再開できます。
視聴維持率が落ちるのは、多くの場合画面に変化がない時間です。 人間は自分の動画を見ていると気づきにくいので、機械に探させます。
やっていることはシンプルで、タイムライン上の「変化イベント」を全部集めて、間隔を測るだけです。
| 集めるイベント | 出どころ |
|---|---|
| カットの継ぎ目 | cut_plan.json の各クリップ境界 |
| 強調テロップ | telop_keywords.json |
| スライド挿入 | slides_plan.json |
| 定型インサート | inserts_plan.json |
これらを時刻順に並べ、30秒以上イベントが無い区間を「変化なし」として検出します。 そして区間ごとに、ズーム・効果音・スライド・Bロールのどれを入れるべきかを提案します。
提案は自動適用されます(既定で最重要2件まで。上限は「演出を塞がない」ための調整弁)。 残りはレビュー表に出るだけで、人が選べます。
ここも応用が効きます。「良くする」のは難しいですが、「悪い状態を機械的に定義する」のは簡単です。 "面白い動画"は定義できませんが、"30秒何も変化しない"は測れます。 自分の作業でも、良さを測ろうとせず、避けたい状態を1つ数値で定義すると、そこから自動化が始まります。
最後に、外部の編集者へ渡すZIPを作ります。ここが一番地味で、一番事故が起きるところです。
timeline.xml は素材を絶対パスで参照します(pathurl)。
自分のMacのパスが書かれているので、そのまま渡すと編集者の環境では全部リンク切れになります。
しかも「どの素材が必要か」は人間には追えません(今回は132クリップ+テロップ+キャラ+モザイク)。
pathurl を正として素材をコピーするpathurl を中立パス(file://localhost/PKG/素材/…)に書き換える単一ZIPにしているのも理由があります。Google Drive はフォルダをダウンロードすると約2GBごとに複数ZIPへ分割され、 素材が散ってリンクが壊れます。これは実際に起きた事故で、以後「受け渡しは必ず単一ZIP」に固定しました。
動画編集の話をしてきましたが、効いているのは動画固有の技術ではありません。 次の6つは、皆さんのどんな作業にも当てはまります。
| 型 | このパイプラインでの現れ方 | 皆さんの作業なら |
|---|---|---|
| 人が直せる中間物を作る | 動画ではなくXMLを出す | 清書ではなく下書きを出させる。最後の判断は自分が持つ |
| 機械とAIを分業する | 無音はffmpeg、文脈はAI | ルールで決まることはAIに投げない。安く・速く・ブレない |
| AIの裁量に上限を置く | AIが切れるのは全体の25%まで | 「AIが勝手に変えてよい範囲」を先に数値で決める |
| 判断には理由を残させる | 各カットに reason 必須 | 後から検証できない自動化は、事故が起きたとき直せない |
| 悪い状態を数値で定義する | 「30秒変化なし」を検出 | 良さは測れなくても、避けたい状態なら測れる |
| 守らせたいことは機械で止める | lint・program-gate・ng_check | 手順書に書いても守られない。止まる仕組みにする |
このパイプラインは最初からこの形だったわけではありません。 オープニングを3回無音で納品し、キャラのレンダリングで5回OOMを起こし、テロップの校正で音とズレを作りました。
今ある検査項目は、そのほとんどが実際に失敗してから足したものです。 逆に言えば、仕組みは失敗するたびに強くなるということです。
最初から完璧に設計しようとせず、失敗したらその場で「同じ失敗を機械が止める形」に変える。 これを繰り返すだけで、半年後には人が注意しなくても品質が保たれる状態になります。