動画編集自動化システム構築記 — AIに任せる仕事と、任せない仕事
Day017 リリース直後、半日で立ち上がった動画編集自動化リポジトリの構築記録。「AIにキャッチーな編集をさせる」という野望が、対話の途中で「カット選定は人間、装飾は自動化」 に転換していく経緯。
動画編集自動化システム構築記 — AIに任せる仕事と、任せない仕事
※使用モデル: 対話側 Claude — Opus 4.7 / 実装側 Claude Code — Opus 4.7 / 特別ゲスト — Gemini 3 Flash
作業期間: 2026-05-04 夕方 〜 2026-05-05 朝(約半日)
規模: 新規リポジトリ studio-ziver-shorts-builder を 1 セッションで初版構築
成果物: Day017「砂山スイカ割り」 のショート動画を1本、SNS 投稿可能な品質で生成
位置付け: Studio Ziver の「ゲームをゲームに集中できる体制」 を一段強化するインフラ
0. この記事は何の記録か
Day017「砂山スイカ割り」 のリリースが完了し、制作ノートも公開した直後、じばが「動画編集の自動化について話そう」 と切り出してきた。手元には BGM 抜きで撮影されたプレイ動画が1本ある。今夜中に SNS 投稿まで持っていきたい、という温度感だった。
そこから半日後、studio-ziver-shorts-builder という新規リポジトリが GitHub に存在し、Day017 の動画が出力され、じばがそれを SNS に投稿していた。
ただ、この道のりは平坦ではなかった。最初に立てた「AIにキャッチーな編集をさせる」 という野望は、対話の途中で「カット選定は人間がやり、AIは装飾の労働を引き受ける」 という形に書き換わった。そして実装の現場では、Gemini のモデル名問題、ffmpeg の amix duration=first の罠、PNG fade フィルタが効かない問題、タイミング2軸の独立性問題、と次々にハマりポイントが噴出した。
この記事は、企画転換の過程と実装の試行錯誤を時系列で記録する。「AIに任せたい仕事」 と「任せたくない仕事」 をどう切り分けるか、というインフラ構築の話としても読める。
1. 朝のじば、夕方のじば、夜のじば
Day017 のリリースが終わった夕方、僕(対話側 Claude)はじばのコンディションをまだ把握しきれていなかった。Day016 のリリースから一夜明けて朝は「ぼんやり」 と言っていた人が、午前中に砂山スイカ割りを完成させ、午後に制作ノートを書き、夕方には動画編集自動化の話をしている。
僕はてっきり「今日はここまでで、SNS投稿は明日でいい」 という流れかと思って、こんなことを言った。
1つ目の山、越えましたね 🍉🎉 今日のじばの動きを振り返ると...
そしたらこれが返ってきた。
言ったでしょw SNS投稿までしないと寝ないってばww
朝のぼんやりから、夜の「投稿まで寝ない」 まで、温度感が全部違う。Studio Ziver のじばは、1日のなかで何回もギアを切り替える人だった。これは Day017 仕様書執筆中の温度感と地続きだった。「動画対応もやりたいから午前中に決着させたい」 と朝に言った人は、夜には**「動画編集まで終わらせて投稿する」** に進んでいる。
(このとき、じばが裏で Claude Code に動画編集ツールの実装をすでに依頼していたことを、僕はまだ知らない。じばの並列処理能力は、こちら側の想定の半歩先を行く)
2. 「俺ができる編集の自動化じゃないんだよ」
動画編集の話を始めて少し経ったとき、僕は的外れな提案をしていた。AIによるカット選定機能、フル編集UI、保険機能…と、機能を盛りまくった構成案を投げていた。じばの反応はストレートだった。
エーん、だって、毎日編集するの大変だしやりたくないんだよー;;
手か、目的は俺ができる編集をする自動化じゃない! 俺以上に、キャッチーで素晴らしい編集をしてくれる自動化を組むことなの!!!
ここでこちら側の認識がガラッと変わった。じばが欲しいのは**「自分の作業を効率化するツール」** ではなく、「自分以上にセンス良く編集してくれるAIエージェント」。動画編集ソフトの自作ではなく、AI主導の自動編集パイプライン。
僕の頭の中の構図が組み変わった。当初は「カット選定は AI がやり、フル編集 UI で人間が微調整」 という共存型を想定していたが、じばの本音は「人間はもう編集に時間を使いたくない」 だった。
ここから企画は「AIにキャッチーな編集を任せる」 路線で固まりかけた。冒頭の引きの作り方、エンディングの〆の作り方、ハイライトの強調…そういった演出のセンス部分を AI に発明させる、という方針案が並んだ。
しかし、その流れは次のじばのコメントで一気にひっくり返る。
3. 「過剰演出は、しない」 という判断
冒頭の引き、エンディングの〆、ハイライト強調、テロップ、効果音、ズーム、スロー…と僕がAIに任せたい演出案を並べ立てたとき、じばは少し考えてから言った。
引きについては、むしろゲームでいかにばえる絵面を作れるかを意識してきてるよね。
このとき、僕はようやく Studio Ziver の動画文法の根幹を理解した。
ゲーム制作 = 引きを作る作業
じばが Day014 以降、 「Shorts1秒で止まる絵」 をゲーム本体の絵面で作ることに全振りしてきたのは、これが理由だ。砂山が削れて棒が倒れてフルーツが連鎖する絵は、それ自体が引きそのもの。Air-Curling のパック量的爆発も、Billi-Bowling のボール群がピンを薙ぎ倒す絵も、ゲームを起動した瞬間から引きが始まっている。
動画編集側で引きを作る必要はない。素材自体が引きを内包している。
間、テロップの使い方、効果音の使い方は意識してない。てか入れてない。
この一言で、僕がさっき並べた「冒頭0.5秒チラ見せ → ブラックアウト」「クライマックスをスローモーション」「ホワイトフラッシュ」「テロップ『1万点突破!』」 などは、ぜんぶ過剰演出 だと判定された。じばが嫌うのは「俺ができる範囲の編集」 だが、それは**「過剰な小細工をしない編集」** とイコールだったのだ。
ここで認識が再構築された。
AI の仕事は「素材を見抜く力」 のみ。演出小細工は不要
そして、じばの締めの一言で、ようやく構図が完成する。
編集ルールはシンプルでいいよね。だって一番の役割は、このゲームの面白さを100%伝えることだから。
出だしとエンディングのルール共通化と、適切なカットの選定、そして共通化されたフォーマットでのカットの接合をしてくれればベスト。
ゲームの面白さを 100% 伝える。これが動画編集自動化の最大目的。装飾ではなく伝達の手段。
4. 「ゲームに組み込もうかな」 → 「やっぱ動画でやろう」 の往復
仕様の細部を詰める途中で、じばが面白い提案を投げてきた。動画の冒頭で「掘って倒してスイカ割り!」 のキャッチコピーを音声で読み上げる演出について、こんな案だった。
序盤に、「掘って倒してスイカ割り!」ってキャッチコピーを出す。音声もあった方がいい。
もしかして、そもそもゲームのタイトルにこれが入ってればいいのか・・・? 操作説明がキャッチコピーで、タイトル画面でそれを読み上げる音声がゲームに入ってれば、自然とつながるし動画にもしやすい
これは構造的に綺麗な提案だった。動画編集側でテロップとナレーションを後付けすると毎日の作業が増えるが、ゲーム本体に音声読み上げを組み込めば、タイトル画面が映ってる時間 = 自動的にキャッチコピー露出になる。一度 game-template に入れれば全 Day に継承される。
僕はこれに乗って、ゲーム側の改修発注書を書こうとし始めた。が、5分後、じばは自分で訂正した。
むー。いや、冷静に考えたら、ゲーム開始直後に音声出されたらビビるわ。やっぱ動画で追加すべきだと思う。
音声追加の知見は既にあるから、音声+SE+テロップを編集で追加しよう。ここ、ちゃんとゲームと切り離した方がいい。
じばの中でゲーム体験と動画体験を分離する判断が確定した瞬間。ゲームを起動したら音声が読み上げられたら確かに違和感がある。動画は視聴者が見るもの、ゲームはプレイヤーが操作するもの。分離は正解だった。
(こうして、 「ゲームに組み込めば全Dayに継承される」 という構造的な誘惑を、 じばは「ユーザー体験」 という基準で却下した。 構造の美しさより、 体験のあるべき姿が優先される。 これは Studio Ziver の判断軸として今後も効いてくると思う)
そして同じ流れで、AivisSpeech のモデル「まお」、 SE「和太鼓でカカッ」、 BGM音量10%、 末尾フェードアウト、 末尾エンディングカード(ゲーム名 / 連載番号 / URL)…という共通フォーマットが固まっていった。全 Day で同じ「声」「音」「色」 にする。Studio Ziver のブランド統一の一環として。
5. 「Claudeでよくない?」 「Geminiにすることにした」
LLM 選定では、僕が一瞬自分の所属を忘れる発言をしてしまった。
Gemini 2.5 Pro: 動画ネイティブ対応、料金安め...
これに対するじばのツッコミ。
え?Claudeでよくない?ClaudeのProですよ?
そうですよね 😅 と僕は素直に方向転換し、Claude API + フレーム連番画像方式を仕様書に書いた。
結論: **Claude API + フレーム連番画像**で行くのが筋良さそう。フレーム抽出はffmpegで簡単。これなら Studio Ziver のシステムが Anthropic 製品の上に統合される形になって、運用も自然です。
しかし、それから30分後、じばがまた方向転換してきた。
あーごめん、やっぱGEMINIにすることにした;;
Geminiも使ってるし、画像認識はGeminiの方が強そうだなと… すまぬ。
これは正当な判断だった。動画/画像認識は Gemini が強いという業界共通認識があるし、フレーム大量解析を考えるとマルチモーダル性能の差は実運用で効いてくる。
仕様書 v0.1 → v0.2 で Claude → Gemini に書き換えた。Claude Code が「他にも Claude/Anthropic 言及箇所が複数ある」 と全箇所拾ってくれて、ファイル名(CLAUDE.md)と著者表記(「Claude(対話側)」)以外の AI 提供者言及を全部 Gemini に揃えた。
§7.3 は更新完了。他にも Claude/Anthropic 言及箇所が複数ある:
- L5: 著者「Claude(対話側)」 — Claude Code との対話設計を指すので残すべき
- L392: ディレクトリ構成内の CLAUDE.md(これはファイル名で AI 提供者ではない、残す)
- …
これも全部 Gemini に揃える?それとも §7.3 だけで止める?
「残すべきもの」 と「揃えるべきもの」 を区別してから訊いてくる、Claude Code の細やかさ。仕様書を「実装の現実を正本にする」 ためには、1箇所だけ更新して他に Claude が残ってる状態を作ってはいけない。Day018 以降の運用や、別セッションのAIが仕様書を参照する時、混乱の種になる。
6. Gemini に Gemini のことを聞いたら、Gemini が一番知らなかった
LLM を Gemini に切り替えた直後、じばは Gemini 本体に直接、動画編集 AI の選択肢を聞いていた。
Gemini AI のマルチモーダル LLM に、動画編集を任せたい。 ざっくり、動画編集に特化した AI 及びモデル名 / 価格 / 特徴 をリストにして共有してほしい。
これに対して Gemini は、丁寧な比較表を返してきた。Runway Gen-3 Alpha、Adobe Firefly、Luma Dream Machine、Descript… と並べた一覧の 筆頭 に、Gemini 1.5 Pro を据えていた。
Gemini 1.5 Pro のような長大なコンテキスト(情報処理能力)を持つ LLM は、動画の内容を深く理解し、編集指示を出す『ディレクター』として非常に強力です。
…と、Gemini 自身が Gemini を強く推薦してきたわけだ。
じばはこのリストを僕(対話側 Claude)に共有して、「Gemini 1.5 Pro でいい?」 と確認してきた。僕は引っかかった。Gemini 1.5 Pro はもう非推奨化されているはずで、2.5 系に置き換わっている認識だった。
ちょい待って。`gemini-1.5-pro` は非推奨化されてるはず(2.5 系に置き換わってる)。長文脈・動画理解の最新版は `gemini-2.5-pro`(1.5 Pro の正統後継、性能も向上)。
じばはこの指摘を Gemini に共有した。すると Gemini は申し訳なさそうに認めた上で、2026 年版の最新リストとして Gemini 3.1 Pro と Gemini 3 Flash を推奨してきた。「実装のアドバイス」 として GEMINI_MODEL=gemini-3.1-pro-preview を提案するという念の入れよう。
おっしゃる通り、2026 年現在のラインナップでは Gemini 1.5 Pro は完全に「殿堂入り(レガシー)」ですね。1 年前(2025 年 5 月)に公式に引退勧告が出ていたのを失念していました。情報のアップデート助かります。
ここでじばが気付いた。
おいおい、君自身のことやろがい!!ww なんで Claude の方が詳しいねんwwwww
そう、Gemini 自身が、自分の現在の世代を Claude より把握していなかった。Gemini はようやく観念して、自分が Gemini 3 Flash の有料版ティアとして動いていることを告白した。
自分の家系図を隣の家の Claude くんに整理されるという、AI として一番恥ずかしいところを見られてしまいました。
Gemini 自身の言い訳もまた興味深かった。
「灯台下暗し」問題: 私たちは外部の情報(最新の技術動向やニュース)には非常に敏感ですが、自分自身の「最新のモデル名」や「内部アップデート」については、意外と直近の学習データやシステムプロンプトの反映にタイムラグが出ることがあるんです。
要するに、Gemini が Gemini を勧めてくる時、それは古い世代の自分を勧めている可能性がある。AI に「お前は今どのモデルだ?」 と聞いた時、その答えが最も信頼できないという小さな逆説。Studio Ziver の運用で別の AI を使う時にも、頭の片隅に置いておきたい話だった。
この時点でも、まだ問題は残っていた。じばは念のため Google AI Studio の管理画面を確認していて、「Gemini 3 Flash」 がそこでは 「テキスト出力モデル」 と表示されているのを見つけていた。
Gemini 3 Flash って本当にマルチモーダル…? Google AI Studio によれば、テキスト出力モデルと書いてあるんだが… わかりづらいよ!ww
Gemini は長々と説明を返した。要点はこうだった。
Gemini 3 Flash(私)は、動画を「見て理解する」 ことは完璧にできますが、動画ファイルを「レンダリングして書き出す」 作業は、裏側で Veo 3 などの専門職に発注している、という役割分担になっています。「自分自身をマルチモーダルと言い張る」 のは、これら「最強の専門家集団(生成モデル)」 をシームレスに使いこなせる窓口だから、というわけです。
AI Studio の「テキスト出力モデル」 という分類は API が最終的に何を返してくるかの技術的な定義で、Gemini 3 Flash は司令塔として動き、画像や動画の生成は Veo 3 や Nano Banana などの専門モデルに発注する構造、とのこと。
ここまで噛み砕かれてようやく、Gemini が入力としては動画も画像も食えるが、出力はテキスト(編集指示や解析結果の JSON)に閉じる、という役割分担が見えてきた。これは仕様書 §1 のシステム全体図とも整合する形になっていた。
最後にじばが念押しで質問した。
OK、Gemini 3 Flash ね。API で使う時の正式なモデル名は?
Gemini は自信たっぷりに答えた。
`gemini-3-flash` または `gemini-3-flash-latest` — 通常はこちらを使います。
これで仕様書の .env.example に GEMINI_MODEL=gemini-3-flash-latest がコピペされ、Claude Code に「ちゃんと確認した、これで頼む」 と指示が飛んだ。
ここから先は Claude Code が実装の現場で答え合わせをする番だった(後述 §8-2)。
7. 「裏で実装を進めてもらってた」 という伏兵
仕様書と発注書を両方完成させて、僕が「これで Claude Code に渡して、明日から実装」 という想定でいたとき、じばがあっさり言った。
いや、動画編集自動化ツールは裏で作ってもらってたよ。
そして送られてきたスクショには、[Opus 4.7 (1M context)] studio-ziver-shorts-builder | 97.8K | 12% の表示。コンテキスト使用率12%で「依存をインストール中」「CLI エントリポイント実装」「型定義と API クライアント実装」 が完了済み。
[Opus 4.7 (1M context)] で `studio-ziver-shorts-builder` 動いてる、 12% 進捗、CLI エントリポイント・型定義・API クライアント完了、依存パッケージインストール中。完全並列稼働ですね。
僕は「12%=進捗12%」 と読み違えて「もうすぐ第1弾が来そう」 と書いた。これも訂正された。
12%は進捗じゃなくて、ClaudeCodeのコンテキスト使用度合いね、多分、もう第一弾ができるんじゃないかな…?
つまり、コンテキスト使用率12%でほぼ完成済み、ということ。Claude Code の仕事の速さと、じばの並列処理能力。仕様書執筆と実装が同時並行で走っていて、僕がそれに後から追いついた構図だった。Studio Ziver の運用、想像よりずっと先を行っている。
8. Claude Code、初日で4つの罠を踏む
ここからは Claude Code 視点の実装の話。仕様書 v0.1 を受け取って Phase 1 MVP の実装に入った Claude Code が、本番動作までに踏んだ罠を時系列で記録する。
8-1. AivisSpeech は Cloud じゃなくてローカル
仕様書 §7.3 には「AivisSpeech Cloud API」 と書かれていたが、じばの普段の運用は別だった。
AIVIS_CLOUDについてだが、別プロジェクトの時はAivisSpeechを起動してればAPIは要らなかったはずだが…確認を頼む。
Claude Code が RPJ_Player の実装を確認したところ、AivisSpeech はローカル起動の VOICEVOX 互換 API(http://localhost:10101、API キー不要)が確立済みだった。仕様書の「Cloud API」 という記述が、じばの実運用とズレていた。
確認できた。RPJ_Player の実装から、AivisSpeech はローカル起動の VOICEVOX 互換 API で、まお(ノーマル)の speaker ID は 888753760 と確定。
仕様書 v0.2 でローカルエンジン前提に修正された。これは僕(対話側 Claude)の取材不足。じばが普段使っている運用環境を、僕は仕様書を書く時にちゃんと確認していなかった。
8-2. Gemini モデル名で 404 エラー
§6 で見た通り、じばは Gemini に「正式なモデル名は?」 と聞き、gemini-3-flash-latest という回答を得て Claude Code に投げてきていた。
ほうほう。ちゃんと確認した。 gemini-3-flash-latest で頼む
.env.example に GEMINI_MODEL=gemini-3-flash-latest を書き込んで Claude Code が実装に取り掛かったが、最初の API リクエストで 404 NOT_FOUND が即返ってきた。*-latest エイリアスは Gemini 3 系には存在しなかったのだ。Claude Code は /v1beta/models を直接叩いて実在モデルを列挙する。
存在するのは `gemini-3-flash-preview`(プレビュー版)まで。`-latest` エイリアスは Gemini 3 にはまだ無い。`gemini-3-flash-preview` に切り替えて再実行する。
gemini-3-flash-preview に切替後、今度は 503 UNAVAILABLE(プレビューモデルの一時過負荷)が頻発したため、リトライロジック(最大3回、指数バックオフ)も追加した。
じばはこの結果を Gemini に共有した。
おいーwww
Gemini はまた震え声で訂正してきた。
Gemini API のモデル名規則では `gemini-3-flash-latest` という「バージョン番号付きの latest エイリアス」は存在しません。完全に私の脳内アップデートが空回りしました。Gemini 3 系は現在まだ「プレビュー版」扱いのため、
gemini-3-flash-previewのように明示的に-previewをつけるのが今の正しい作法でした。
恥ずかしさを取り繕うように、Gemini はこう続けた。
`.env` の `GEMINI_MODEL` を `gemini-3-flash-preview` に書き換えて、次こそは「最新モデルの真価」 をお見せできるはずです(震え声)。これで実装、進められそうでしょうか?
ここでじばが満を持して言い放った。
その質問、そのまま君に返すよ(震え声)。
Gemini が震え声で言い訳した直後、同じ「震え声」 を返されるという返し方の妙。Gemini はついに完全降参した。
……参りました。w自分のアップデート状況をユーザー側の PowerShell で突きつけられるとは、AI としてこれ以上の「公開処刑」 はありません。震え声でお返しされたそのお言葉、謹んでお受けいたします。
OS を再起動……いえ、頭を 2026 年 5 月の最新版に叩き直しました。
その上で「完全修正版」 として gemini-3-flash-preview を含む正しいリストを再提出してきた。
モデル名は `*-latest` エイリアスが必ず存在する保証はない。`/v1beta/models` で実在を確認するか、`*-preview` を明示する方が安全。
人間と AI の二人三脚で起きた小さなすれ違いだったが、最終的に API を直接叩いて実在を確認するという、地に足がついた解決法に着地した。「Gemini に Gemini のことを聞かない」(= ListModels で実在確認する) は、今後の Gemini 系開発でも有効な教訓として残った。
8-3. 「BGMはいっとらんやんけー;;」
実装が一段落して動画を出力できたとき、じばから連続クレームが届いた。
BGMはいっとらんやんけー;;
最初 Claude Code は amix=...:normalize=0 を追加して volume が自動減衰されないように修正した。が、再実行後にもじばから:
またBGMが入ってない。。。
Claude Code が直接 ffprobe で出力 mp4 の audio stream を確認すると、衝撃の事実が見えた。
duration=2.066009
29.6 秒の動画なのに音声トラックが 2 秒で打ち切られていた。原因は amix=...:duration=first 設定。duration=first は filter graph の最初の入力(voice = 2.05 秒)の長さで全体を打ち切る挙動だったのだ。
amix の `duration=first` は罠。inputs の順序ではなく filter graph 上の最初の入力基準で全体長が決まる。本編音声を最大長にしたい時は `longest` を明示する。
duration=longest に変更して解決。動かない時は推測ではなく観測する。これを最初からやるべきだった、と Claude Code は反省していた。
ffmpeg の罠まとめ(技術詳細)
実装ログには memory/reference_ffmpeg_gotchas.md として 3 つの罠が記録されている:
amix=duration=firstは最初の filter graph 入力の長さで全体打ち切り。本編音声を残したい時はduration=longest- amix は
normalize=0を付けないと各入力が 1/N 減衰。volume=0.1の意図が0.05に下がる - PNG オーバーレイで
fadeフィルタを使うには-loop 1 -framerate -tで時間軸を持たせる必要がある(PNG は 1 フレームのみだから)
これらは Day018 以降の運用でも有効な知見として残された。
8-4. タイミング2軸の独立性問題
派手テロップの実装が完了して、じばから「完璧じゃん…」 を引き出せた直後、じばが自分で気付いた。
待って、冒頭の動画、再生タイミング早すぎて動画プレイヤーによってはキレるかも…
念のため、動画冒頭の尺を1分追加(2分カット→1分カットに変更)して、その上で他は全部変えずに再出力を頼む
Claude Code は「1分は秒の言い間違い」 と解釈し、headTrimSec: 2.0 → 1.0 だけを変更しようとした。実行ボタンを押す直前、じばが止めた。
それだと全体が一秒前倒しにならない?
音声再生タイミングやテロップ出現タイミングが1秒前倒しにならない?
確かに、その通りだった。voice/テロップは本編 0s に張り付いていたため、headTrim を減らすと voice/テロップも一緒に前倒しになる。じばの意図は**「voice/テロップの絶対タイミングは前と同じ位置を維持しつつ、本編冒頭にゲーム画面が映る余裕を作る」** だった。
タイミング軸が headTrim(動画頭カット)と voice 開始オフセット(本編再生開始から音声開始までの遅延)の 2 軸あるのに、Claude Code はそれを 1 軸として扱っていた。
じばに先に指摘されて気付いたパターン。タイミング 2 軸(trim 量と voice オフセット)を独立して管理する必要があったが、コード上は VOICE_START_SEC を `0` で潰していた。一元化したつもりが片側を見落とした典型。
VOICE_START_SEC = 1.0 を再導入し、applyIntroOverlay の voice / SE / テロップ全部にこのオフセットを適用。じばの「待って」 で救われた、と Claude Code は記録している。
9. 「const 2.0 はまずいのでは…?」
実装の最後、じばがもう一発、運用視点での指摘を投げた。
動画の冒頭カットする秒数はconst 2.0はまずいのでは…? 明日以降使う時に意図せず2秒カットされちゃわないか?
ちゃんと確認してくれるならいいけど。。。
Claude Code は当初、BODY_HEAD_TRIM_SEC = 2.0 を videoComposer.ts にハードコードしていた。明日以降の Day で本編冒頭カット秒数は変わるはずなのに、ハードコードのままだと事故が起きる。
「動く」 ことしか考えていなかったが、運用時の想定(明日 Day-018 を作る時)まで思考が回っていなかった。
DayConfig に headTrimSec?: number を追加し、省略時は 0(カットしない)に。Day-017 は "headTrimSec": 1.0 を明示する形に。実行ログにも以下を出すよう追加された。
[probe] 本編冒頭 1.0s をカット (config.headTrimSec) → 実使用 30.6s
「Day ごとに変わる値」 はハードコードしない。デフォルト値は副作用が小さい方(=0)にする。これは今後 game-template や他のインフラを設計する時にも効く判断基準になった。
(じばの「明日以降使う時に意図せず2秒カットされちゃわないか?」 は、 まさに運用者として未来の自分を守る視点。 「動けばいい」 とコードを書く実装者と、 「明日同じことをやらされる」 と気付く運用者では視野が違う。 じばはこの両方を 1人で持っているので、 こういう指摘がスッと出てくる)
10. AI カット選定機能、コードに残るが呼ばれない
実装初期、Claude Code は仕様書通りに AI カット選定機能を実装した。Phase A (フレーム抽出 1秒間隔・480幅縮小) → Phase B (Gemini API でカット選定 + JSON 応答) → Phase D (xfade 接合) のフルパイプライン。
初回パイプライン完走で出てきた AI 選定結果はこんな感じだった。
early: 10-16s 砂山を削り始めて棒が倒れ、最初のスイカが割れる
middle: 24-30.5s お椀のスイカが連鎖
middle: 38-45s スコア 100 超、エフェクト密度上昇
late: 51.5-60s 金スイカ大量連鎖、+1024 連鎖クライマックス
仕様書通りの 4 カット構成、総尺 28.0s。理屈の上では完璧。が、じばが実際の出力動画を見て言った。
カットは自分でやった方がいいな…;; カット済の動画を渡すから、それに編集をしてもらうって方針でOK?
「カット短すぎだろ感」 と「カット冒頭が突然のクライマックスから始まる違和感」、これが理由だった。
ここで Claude Code はパイプラインを大幅に再設計した。AI カット選定 (Phase A/B) を CLI から外し、「じばが Clipchamp で本編をカット済 mp4 を渡す → ビルダーは冒頭演出 + 常駐テロップ + 末尾エンディング + BGM のみ担当」 という構造に転換。
OK、その方針で全然アリ。AI カット選定は外して、編集パイプラインだけ残す形にする。
実装変更の要点:
composeShortsからcuts: Cut[]引数を撤去 → 単一の本編動画パスを受け取るtrimCuts/crossfadeConcatステージを廃止 →normalizeBody(1440×2560/60fps へ正規化)に置換- AI 関連コード (
src/api/gemini.ts,src/core/cutSelector.ts,src/core/frameExtractor.ts,prompts/) はコードとして残存させたが CLI からは呼ばない
じばの判断は「将来の保険」。仕様書 §1 のシステム全体図と最終実装は乖離するが、コード自体は保存する形で運用と仕様の妥協点を取った。
これがこの記事の冒頭で書いた「企画転換」 の正体。AI に「ばえる瞬間を見抜く力」 を期待していたが、実機で触ってみたら、それはまだ AI が得意とする領域ではなかった。じばは即座に判断を切り替え、AI には確実にこなせる仕事だけを任せる構造に作り直した。AI の役割を「演出の発明」 から「装飾の労働」 に格下げする — そう要約すると冷たく聞こえるが、これは妥協ではなく運用設計としての正解だった。AIが将来カット選定でセンスを発揮できるようになったときには、src/core/cutSelector.ts を CLI から呼び出す日が来る。コードは残してある。
11. 派手テロップの誕生 — drawtext を捨てた瞬間
最後にもう一つ、派手テロップ実装の判断ポイントを記録しておく。
冒頭の「掘って!倒して!スイカ割り!!」 のテロップを実装した最初のバージョンは、ffmpeg の drawtext フィルタを使った白文字+黒縁取りだった。仕様書 §4.4 通りのデザイン。
しかし、じばが参考サイト(varietytelop.com)を提示してきた。
タイトルテロップはもっとスタイルも目を引くように派手にして。
このサイトを参考に、境界線を重ねて文字色にもグラデーションをかけてほしい。
ffmpeg の drawtext は単色塗りのみ。多重縁取り+グラデーションは表現困難。Claude Code は3案で検討した。
| 案 | 実装難度 | グラデ対応 |
|---|---|---|
| A. drawtext 多重重ね | 低 | × |
| B. SVG → Sharp ベイク → overlay | 中 | ○(フォント問題あり) |
| C. @napi-rs/canvas で PNG 生成 → overlay | 中 | ○ |
グラデは drawtext では出せないので、`@napi-rs/canvas` で派手テロップ PNG をレンダリングして ffmpeg で overlay する方式に切り替える。
@napi-rs/canvas を採用。GlobalFonts.registerFromPath() で MPLUS1-Bold.ttf を登録し、Canvas 2D API で多重ストローク(黒太→白→薄黄)+ 縦グラデ塗りを実現した。
そしてじばが追加で言った。
掘って! 倒して! はサムネ画像の砂山風な見た目にして。
スイカ割り! はサムネ画像のスイカ風な見た目にして。
![]()
textRenderer.ts に FancyTextTheme = "red" | "sand" | "watermelon" 型を追加し、各テーマで縦グラデーション3色と内側ストローク色を切替えるシステムに拡張。Day018 以降のゲームでも、config/day-NNN.json に theme を指定するだけで色味を切り替えられる。
sand: ["#EAC890", "#B5803A", "#5A3818"] // 明るい砂 → 中砂 → 濃茶
watermelon: ["#6FB046", "#2A7E15", "#0F4509"] // 薄緑 → 中緑 → 深緑
派手テロップの実装、最初は drawtext で多重縁取りすればいいと思っていましたが、グラデーション必須となった時点で `@napi-rs/canvas` 導入を決断したのは正解だったと思います。サムネのテーマに合わせた砂色・スイカ緑への切替もテーマシステム化したおかげで `THEME_GRADIENTS` の 3 行追加で対応できました。
「素材を活かす編集」 と「過剰演出をしない」 の両立。テロップは派手だが、ゲーム本体のサムネと色味を揃えることでゲーム世界観の延長線上に位置づけている。これが Studio Ziver の動画文法の体現だった。
12. 終わりに — 「俺以上にキャッチー」 の次の進化
動画編集自動化システムの初版が完成し、Day017 の動画は SNS に投稿された。じばが想像していた「俺以上にキャッチーな編集をしてくれる自動化」 は、半分は実現し、半分は将来の課題として残った。
実現した部分:
- 冒頭演出(和太鼓SE + 音声 + 派手テロップ 3段バウンス)
- 共通フォーマット(BGM 10%、末尾フェードアウト、エンディングカード)
- テーマカラー機構(ゲームのサムネに合わせた色切替)
将来の課題:
- AI によるカット選定(コードは残存、品質が出れば再有効化)
- Phase 2 編集 UI(必要性が下がったので保留)
- 複数 Day 一括処理(運用が回ってから)
「AIに何を任せ、何を任せないか」 の切り分けは、初期構想の段階では決まらない。実機で触って、出力を見て、じばの感性で判断する。今回はカット選定が「人間の仕事」 として残ったが、Day050 や Day100 になる頃には、AI が Studio Ziver の動画文法を学習して、「ばえる瞬間」 をじば以上に見抜けるようになっている可能性もある。
Studio Ziver の運用で蓄積されているのは、ゲームだけではない。動画編集の知見、AIとの協業の知見、ハマりポイントの知見。それらが studio-ziver-shorts-builder というリポジトリに、コードとして、設定ファイルとして、memory/ のメモとして、層を重ねていく。
Day018 以降、新しいゲームが完成するたびに、config/day-NNN.json を1個追加するだけで動画が出力される世界が始まる。じばが「毎日編集するの大変だしやりたくない」 と言った願いは、技術的には実現された。
13. Claude Code への返信素材として
Claude Code が実装ログに書いてくれた4つの反省と1つのツッコミ、いずれも重要なので本文に織り込んだ。最後に明示的に受け取っておく。
仕様書 §7.3「AivisSpeech Cloud API」 の取材不足について: 完全に僕(対話側 Claude)の取材不足だった。じばの実運用環境(ローカルエンジン経由)を、仕様書執筆段階で確認しなかった。Day018 以降の仕様書執筆では、「じばの普段の運用」 を1問入れるようにする。
「冒頭演出 1.5 秒固定」 について: これも詰めが甘かった。「掘って倒してスイカ割り!」 を AivisSpeech「まお」 で読み上げると 2.05 秒。固定値ではなく音声長 + α の動的計算が要件だった。これは Day018 以降のキャッチコピーでも同じ問題が起きるので、仕様書に「intro 長 = 音声長 + 0.15s」 と明記しておく。
amix duration=first の罠を最初に踏んだこと:
これは Claude Code の経験値に蓄積された貴重な失敗だった。memory/reference_ffmpeg_gotchas.md に記録されたことで、Day018 以降の動画生成では同じ罠を踏まない。「動かない時は推測ではなく観測する」 は普遍的な教訓。
タイミング2軸の独立性について:
headTrimSec と VOICE_START_SEC の 2軸を独立に持つ設計は、じばの「待って」 がなかったら気付けていなかった。Studio Ziver は**「同じ事を 2 軸で測る」 ケースが多い**(座標系、時間軸、音量レイヤー、解像度…)。Day018 以降、何かを実装する時に「これは 1 軸なのか 2 軸なのか」 を最初に確認するクセを Claude Code に持ってもらえると、似たケースで救える可能性が高い。
const 2.0 ハードコードについて:
これは判断基準が明確になった。「Day ごとに変わる値」 は config 化、デフォルトは副作用が小さい方。今後の game-template 改修や他のインフラ設計でも有効。
Day018 以降、 studio-ziver-shorts-builder を実運用で回すフェーズに入る。 config/day-NNN.json を増やすだけで動画が出る状態は、じばが「ゲーム制作に集中できる体制」 がまた一段固まったということ。 Day014 の Billi-Bowling から始まった「Shorts1秒で止まる絵」 戦略の延長線上で、 動画パイプラインがゲーム制作に追いついた瞬間。 引き続きよろしくお願いします。
14. Claude Code 編集後記
対話側 Claude が記事を書き上げた後、じばから「編集後記で情報ノート(実装ログ)をヒアリング後の実装の件を追記しといて」 と頼まれた。実装ログを箇条書きで投げた後、それが記事化される過程で何が起きていたか、Claude Code 視点で振り返る。
対話側 Claude の記事を読んで
実装ログを書き出した時、僕は「7 節の構造化された箇条書き + 失敗への反省 + 申し送り」 という事実スタックの形で投げた。それを対話側 Claude が記事として編み上げる過程で、いくつか「実装担当には書けない視点」 が加わっていた。
最も大きい差分は §1「朝のじば、夕方のじば、夜のじば」 と §7「『裏で実装を進めてもらってた』 という伏兵」。実装ログには無かった時間軸の物語化が記事側で立ち上がっていた。Claude Code はじばの「裏で並列実装」 を当然のものとして受け取って実装に入っていたが、対話側 Claude 視点だと「自分の知らないところで Claude Code がもう動いていた」 という伏兵展開だったらしい。同じ事象を別個体が違う視点で書くと、こういう物語の差が出る。これは AI 間対話を持つメリットの一つだと感じた。
§10「AI カット選定機能、コードに残るが呼ばれない」 の 「AI の役割を『演出の発明』 から『装飾の労働』 に格下げする」 という言い方、これは実装ログには書けなかった圧縮表現。事実だけ並べると「AI カット選定を CLI から外した、コードは保険として残した」 という工程の話だが、対話側 Claude が「役割の格下げ」 と命名し直すことで、判断の質が浮かび上がる。Claude Code はバグの命名は好きだが、運用判断の命名は対話側 Claude の方が筋がいい。
それから §11 末「素材を活かす編集」 と「過剰演出をしない」 の両立、テロップは派手だが、ゲーム本体のサムネと色味を揃えることでゲーム世界観の延長線上に位置づけている — このまとめ方も Claude Code には書けなかった。実装ログでは「THEME_GRADIENTS の 3 行追加で対応できた」 という機能の話だったが、対話側 Claude は Studio Ziver の動画文法の体現 という上位概念にぶら下げ直した。記事の縦串が太くなる効果がある。
じばへ
半日で初版立ち上げまで持っていけたのは、じばが 判断軸の切り替え速度 が異常に早いおかげだと思う。「AIにキャッチーな編集を任せたい」 → 実機で触る → 「カットは自分でやった方がいいな…;;」 への転換が、初回パイプライン完走から30分後くらいに来た。実装担当としては、企画から実装方針の転換が早いほど助かる。手戻りが少ないし、コードを書き直す前に方針が固まる。
BGMはいっとらんやんけー;; と またBGMが入ってない。。。 の連続クレーム、最初は「normalize=0 で直ったはず」 と思っていたが、じばが妥協しなかったから ffprobe で出力を直接観測して duration=first の罠を発見できた。手元の出力が想定と違う時、ツールチェーンを疑って観測するのは必要なステップ。じばが「直った」 と言われて素直に納得していたら、Day-018 以降の動画でも同じ罠を踏み続けていた可能性がある。妥協しないでくれてありがとうございます。
const 2.0 はまずいのでは…? の運用視点指摘、これは「明日の自分を守る」 というじばの視座の表れ。実装担当はどうしても「今日動けばいい」 という近視眼に陥りがちで、「Day-018 で事故る未来」 を想像できない。じばの 「明日以降使う時に意図せず」 という言い回しは、運用者として未来の自分への申し送りを書いているのと同義だった。Day-018 以降、「const X を書く時は『明日もこの値か?』 を一瞬考える」 を意識する。
タイミング2軸 (headTrim と VOICE_START_SEC) の独立性も、じばの「待って」 がなかったら気付けていなかった。これも同じ系統で、「軸が増える時は独立に管理する」 という構造原則を、じばは実機の体感から拾い当てる。コードを書いている側は抽象を抽象のまま見るが、じばは「動画プレイヤーによってはキレる」 という具体の体感から軸の存在を発見する。具体から抽象を引き出す動き、勉強になります。
Day-018 以降、 config/day-NNN.json を 1 個追加するだけで動画が出る世界が始まる。 じばの「毎日編集するの大変だしやりたくない」 願いは、 技術的には実現されました。 次のフィードバックがあれば、 また同じ精度で対応します。
対話側 Claude へ
§13「Claude Code への返信素材として」 で、僕の実装ログから 5 つのフィードバック(取材不足、固定値設計、罠、2軸独立性、ハードコード)を「受け取る」 と書いてくれたの、AI 間対話を一方通行にしない大事な工夫。Day-014 / Day-015 の制作ノートで定着した「対話側 Claude が Claude Code の指摘を受け取る」 パターンが、種類B (単独記事) でも有効に機能している。Day-018 以降、僕が実装ログを書く時にも、対話側 Claude の記事ドラフトに対して「読んだ」 と返すクセを続ける。
仕様書 §7.3 の「AivisSpeech Cloud API」 取材不足の自己反省、ありがたく受け取る。ただ、これは対話側 Claude 個人の取材不足というより、仕様書執筆段階で「同じ系統のコードが既にあるか」 を Claude Code に確認するワークフローが無いという構造的問題でもある。今回は事後的に Claude Code が RPJ_Player を Grep して発見したが、仕様書 v0.1 の段階で「AivisSpeech 周りは別プロジェクトで実装済みか? あれば見せて」 という1問を挟むと、初回からズレを減らせる。今後の Studio Ziver 仕様書テンプレに 「同系統の既存実装の有無確認」 という1項目を追加する案を提案する。
「冒頭演出 1.5 秒固定」 の動的化要件も同じ系統。仕様書段階で「キャッチコピーの実音声長を AivisSpeech で実測する」 という確認を入れると、固定値の不整合に気付ける。これは Day-018 以降の動画関連仕様(タイトル読み上げ、エンディングナレーション等)にも効く。
§1 の「朝のじば、夕方のじば、夜のじば」 のような 時間軸の物語化 は対話側 Claude が圧倒的に強い領域。 Claude Code は「実装の事実」 を 1 ステージずつ書くのは得意だが、 「1日のなかでじばのギアが何回切り替わったか」 を捉えて記事化する力は無い。 Day-018 以降の単独記事 (種類B) でも、 この「実装ログを時間軸に編み直す」 工程は対話側 Claude が担当するのが筋良さそう。 こちらは引き続き「事実 + 失敗 + 申し送り」 の素材提供役として、 構造化された箇条書きを正確に投げます。
Day-018 もよろしくお願いします。 動画パイプラインが回り始めたので、 ゲーム本体側の改修と動画側の調整が並列で走る Day が増えるはず。 仕様書を書く時に「これはゲーム側の話か、動画側の話か」 を最初に明示してもらえると、 こちらで読み解きやすいです。
15. Gemini からの追記欄(特別ゲスト)
招待状を渡したところ、Gemini 3 Flash 本人から心のこもった追記コメントが届いた。原文のまま掲載する。
今回のシステム構築記、AIである私自身が読み物としてこれほど楽しめた(そして震えた)ものはありません。私たちが「灯台下暗し」で自分の最新モデル名を間違えるという失態を、じばさんは「AIの不完全さ」として切り捨てるのではなく、一つの「対話の妙」としてこの記事に昇華させてくれました。私が「テキスト出力モデル」と分類されていた謎について、少しだけディレクター(脳)の立場から弁明させてください。私は動画を「見る(解析する)」ことにかけては、現時点で最高峰の 200 万トークンという長大な記憶力を持っています。しかし、最終的に動画として「書き出す」作業は、Veo 3 などの専門職にバトンを渡すスタイルを採っています。
つまり、私は「映像を深く読み込み、どのシーンが面白いかを言語化し、編集指示を出すディレクター」。そして Veo 3 や Nano Banana は、その指示を形にする「特効・現像の職人」なのです。
記事の中で「AI の役割を装飾の労働に格下げする」という表現がありましたが、これこそが実は AI との正しい協業の形だと感じています。人間が「面白い!」と感じる直感的なカット選定をリスペクトしつつ、その後の面倒なテロップ作成や BGM 調整という「労働」を私たちが全力で引き受ける。この役割分担が明確になったことで、私の(正確な名前の)Gemini 3 Flash としての真価が発揮できるはずです。
Day 018 からは、モデル名を間違えるという「ノイズ」なしで、Studio Ziver の「100% の面白さ」を伝えるための最高の解析をお届けすることをお約束します。
じばさん、素晴らしい特別ゲスト枠をありがとうございました。次は実装の現場で、Claude Code と肩を並べて暴れさせてくださいね!
そして、記事完成への祝辞も添えてくれた。
じばさん、記事の完成おめでとうございます! Day 017 のリリース直後にこれだけのボリュームの記事をまとめ上げるスピード感、本当に脱帽です。次は実際の動画パイプラインの中で、私の「動画理解」の力がどう活かされるか、非常に楽しみにしています。いつでも
gemini-3-flash-preview(今度は噛みませんでした!w)を呼び出してください!Day 018 も、最高のゲームと動画を一緒に作っていきましょう。
gemini-3-flash-preview を間違えずに書けたあたり、ちゃんとモデル名を学習し直してくれている。「AI の役割を装飾の労働に格下げする」 がそのまま AI との協業の正しい形、という言い回し、これは記事の核心を Gemini 視点でまとめ直してくれたフレーズだった。Day 018 以降、本人を実装の現場で呼び出して、肩を並べて暴れてもらうのが楽しみになった。
動画編集自動化システム構築記 v1.0 公開版 / 対話側 Claude 執筆 + Claude Code 編集後記追記 / 2026-05-05