Fable 5 × Remotion — 動画編集もデザインツールも開かずに広告動画をゼロから作って配信した
動画編集ソフトもデザインツールも一度も開かずに、広告動画をゼロから作って配信しました。この動画です。
音声入力キーボード koedesk の広告動画です。17.5秒、6つのアプリを切り替えながら「声で話した文章が入力欄にドンと着地する」様子を見せて、エンドカードで終わる。ごく普通の広告動画に見えると思いますが、Premiere も After Effects も Figma も Photoshop も使っていません。使ったのは Claude Code(モデルは Claude Fable 5。Anthropicの最新世代モデルです)と Remotion(Reactで動画を書くフレームワーク)だけ。画面に映っているアプリのUIも、iPhoneの筐体との合成も、カット割りも、エンドカードも、すべてTypeScriptのコードとして生成しました。
昼過ぎの時点でこの動画は存在すらしておらず、「プロモーションビデオのアイデアを考えてほしい」という雑な相談から始まって、同じ日の夜にはXで配信されていました。半日の記録として、ハマりどころと一緒に書き残します。
なぜ実在アプリのUIを使わなかったか
koedeskはiOSのキーボードとして動くので、広告としては「LINEでもGmailでもSlackでも使える」を実在アプリの画面で見せたい。まずそう考えました。
そこで投稿前に、主要7社の公式ブランドガイドラインを一次情報まで調査しました(この調査もFable 5のサブエージェント4体を並列で走らせて、各社の規約原文に当たらせています)。結果は想像よりずっと渋いものでした。以下は公開ガイドラインを私たちが調査日時点で読んだ整理であり、法的助言ではありません。判断の際は必ず各社の原文に当たってください。
| 対象 | 第三者の広告動画での実UI使用 |
|---|---|
| Apple純正アプリ(メモ/Safari) | ⭕ 条件付きで明文許容(自社アプリがApple UI内で動く様子を正確に見せる場合) |
| LINE | 🟡 動画広告は媒体を問わず全て事前確認必須(公式申請フォームあり・3〜5営業日) |
| Gmail | 🟡 説明目的のスクショは可、ただし「要素の追加・変更禁止」=キーボード合成が抵触リスク |
| X | 🟡 現行ブランドガイドにUI再現の規定自体がない |
| Claude | 🔴 商標ガイドラインが事前承認必須の建て付け |
| Slack | 🔴 広告での商標使用は明示的承認必須+「スクショはリサイズ以外の加工禁止」の条項があり、キーボード合成は難しいと判断 |
| Notion | 🔴 該当する規定が見当たらず、安全側に倒して不使用と判断 |
つまり「申請なしでそのまま使えるのはApple純正アプリだけ」。さらに調査の副産物として、Apple製品を自作CGや3Dレンダリングで描くことは、Appleのマーケティングガイドラインの禁止事項リストに挙げられていることも分かりました。マーケティング素材でiPhoneを見せたい場合、Apple公式配布の Product Bezels(実物写真ベースのPNG)を無改変で使うのが正規ルート、というのが私たちの理解です。
申請して待つのは面倒なので、方針を切り替えました。アプリは全部、架空のものをコードで作る。
架空アプリのUIをサブエージェント6体で並列実装する
「メッセンジャーらしさ」「メール作成画面らしさ」は、ロゴや固有の配色ではなく画面の骨格が伝えます。吹き出しが左右に並んでいればメッセンジャーだし、宛先・件名・本文の罫線が並んでいればメールです。これは特定のアプリではなく、ジャンル共通のUI文法です。そこで、
- 骨格=ジャンル共通のUI文法(吹き出しの左右配置、宛先/件名/本文の並びなど)に従い、用途が一目で分かるようにする
- 配色・装飾・ロゴは完全に独自のものにし、実在アプリの固有要素は使わない
- ブランド名は画面に出さない(ヘッダーに出すのは相手の名前、#チャンネル名、文書タイトル)
という設計原則で、架空アプリを6種類(メッセンジャー/メール/チームチャット/AIチャット/SNS投稿/ドキュメント)作りました。実装はFable 5がサブエージェント(Sonnet)6体に同時発注します。全員に同じprops契約を課すのがポイントで、
type CoreMockProps = {
width: number; height: number; scale: number;
landedOpacity: number; // 0..1 転写テキストの出現
landedText: string; // 着地する文章(=このカットの主役)
caretVisible: boolean;
statusTime?: string;
sendReady?: number; // 0..1 送信ボタンの活性
};
この契約さえ守られていれば、6つのアプリはどれも同じ状態機械(構え→録音→処理→着地)に差し替え可能な部品になります。6体は互いの存在を知らずに並列で書き、統合とピクセル検品だけ親エージェントがやります。全部で1時間かかっていません。
「画像生成AIでモックを量産すればいいのでは」という案も検討しましたが、採りませんでした。理由は3つあります。
- 着地する文章が動的である必要がある。 この広告の核は「話した文が入力欄に着地する」ことなので、入力欄の中身は本物のテキストレイヤーでなければならない。画像に焼き込んだら差し替えられない
- UIは画像生成が一番ボロを出す領域。 文字の破綻、揃わない余白。静止画でも「AI臭さ」が出る
- コード描画は検品が決定論的。 同じpropsなら同じピクセルが出るので、静止フレームの目視検品→修正のループが成立する
Apple公式ベゼルとの合成 — ハマりどころ2つ
iPhoneの筐体はApple Design Resourcesから公式ベゼルをダウンロードして使います。iPhone 17世代の全モデル・全色のPNGが入ったdmgが配布されていて、今回使ったのはiPhone 17 ProのSilverです。画面領域に自分のコンテンツを差し込むには開口部の正確な座標が要りますが、公式にはドキュメントがないので、PNGのアルファチャンネルを走査して実測しました。
画像: 1350x2760
画面開口: x[72,1277] y[69,2690] = 1206x2622 (402x874pt @3x)
Dynamic Island: PNGに焼き込み済み(自前で描いてはいけない)
ここで2つ、実際に踏んだ罠を共有します。
罠1: 白い四角が筐体からはみ出す
画面コンテンツを長方形のまま開口部に置くと、iPhoneの筐体の丸い角の外側に、コンテンツの四角い角がはみ出します。開口部の矩形の角は、筐体のアウトラインが丸く内側に切れ込む領域(=PNGの透明部分)にかかっているからです。
| Before | After |
|---|---|
![]() |
![]() |
(はみ出しているのは私たちが合成したコンテンツレイヤーの不具合で、ベゼル画像そのものは無改変です)
対策は、開口部の角丸半径を実測してコンテンツ側を同じ半径でクリップすること。半径もアルファ境界の座標3点から円をフィットして求めました(このベゼルでは190px)。
<div style={{
left: BEZEL.screen.x * s, top: BEZEL.screen.y * s,
width: BEZEL.screen.w * s, height: BEZEL.screen.h * s,
borderRadius: BEZEL.screenRadius * s, // ← これがないと白い角が出る
overflow: "hidden",
}}>
罠2: 非整数スケールの継ぎ目ヘアライン
キーボードUIは複数の帯(パネル上端の余白・キー面・OSの下段バー)を縦に積んで描いています。等倍レンダリングでは完璧なのに、ベゼル合成で非整数のスケール(この動画では3.0923倍で描いて0.3551倍に縮小)がかかると、帯と帯の境界に1pxの暗いヘアラインが出ました。端数ピクセルのギャップがアンチエイリアスで可視化される現象です。
対策はシンプルで、積層の親要素に帯と同じ背景色を敷くこと。どんな端数ギャップが開いても同色が見えるだけになり、線は消えます。修正前後をピクセル値で比較して([173,174,180]→[218,220,225]=周囲と均一)解消を確認しました。
カットごとに文章が着地するリズム — 負のSequenceオフセット
6アプリのデモはどれも同じタイムライン(フレーム300で文章が着地する13秒)を持っています。モンタージュでは各カットで「処理中の尻尾→着地→読む間」だけを見せたい。Remotionの Sequence は、from で指定したフレームから子コンポーネントを0フレーム目として再生する部品です。この from に負の値を渡すと、子コンポーネントを途中のフレームから再生できます。
{ORDER.map((kind, i) => (
<Sequence key={kind} from={i * CUT} durationInFrames={CUT}>
<Sequence from={-(LAND_FRAME - 12)}> {/* 着地12フレーム前から再生 */}
<GenericMiniDemo appKind={kind} />
</Sequence>
</Sequence>
))}
これで「カットが変わるたびに、新しいアプリで文章がドンと落ちる」リズムが宣言的に書けます。着地する文章はどれもpropsなので、ターゲット層ごとに差し替えた別バリアントがコマンド1発で出てきます。縦(9:16)・スクエア(1:1)・横(16:9)の3レイアウトも、同じ部品の配置換えだけです。

人間のダメ出しが9バージョンを作った
先に言っておくと、最初のバージョンはひどいものでした。制作の実態はAIの独走ではなく、人間の遠慮ないフィードバックとの往復です。実際に出た指摘を並べます。
- 「コピーの帯が入力エリアに被って、肝心の着地が見えない。それと着地する文が短い——打つのが億劫な長文をザザッと入れれば、入力欄がドンと膨らんで何が起きたか分かる」→ 帯を廃止し、着地文を全差し替え。これで動画の説得力が一段変わった
- 「文章が伸びたぶん、1カット1.1秒だと速すぎる」→ 1.6秒へ延長
- 「画面全体がピコピコ切り替わって不愉快。何のデモかすら分からない。これは出せない」→ 構図を根本から転換。フルブリードをやめ、額装した1台の端末の中だけでアプリが替わり、枠外に説明コピーを常時表示する形へ
- 「キーボードの付け根に黒い線が入ってる」→ 前述の罠2を発見
- 「注記の文字は小さすぎてどうせ読めない。消そう」→ 消した
白状すると、この往復での私(人間)の仕事は実質これだけです。喋ってダメ出しする。Claudeが直しているあいだTwitterを見て遊ぶ。直ったらまた喋ってダメ出しする。Twitterに戻る。以下繰り返し。ちなみにダメ出しは全部、koedeskの音声入力で喋って送っています。自社製品で自社製品の広告にダメ出しをする、妙な半日でした。
コードで動画を作る利点はここで効きます。どの指摘も「該当するpropsや定数を変えて再レンダー」で数分で反映でき、しかも修正が他のバリアントすべてに自動で波及します。タイムライン編集ソフトで9バージョン作り直すのは、少なくとも私たちの体制では無理でした。
配信もAPIで — nullcastという小技
最後に配信です。冒頭に埋め込んだ縦動画の単独投稿とは別に、横16:9版をレンダーして、運用中のX広告のプロモポスト(ターゲティング別に3本ある)それぞれにリプライとしてぶら下げました。広告からポストを開いた人に、続きのデモとして見える形です。ここで気になるのが、同じ動画リプを3本の広告に付けると、アカウントの返信タブに同一の投稿が3つ並んでしまうこと。
X Ads APIの承認を受けているアカウントは、投稿時に nullcast: true を付けるとプロフィールにもタイムラインにも載らない投稿が作れます(広告主がスレッド追記に使う標準手法です)。投稿APIは普通のv2エンドポイントで、ペイロードに1フィールド足すだけ。
payload = {"text": text, "media": {"media_ids": [media_id]},
"reply": {"in_reply_to_tweet_id": ad_post_id},
"nullcast": True}
投稿後にユーザータイムラインAPIを叩いて「スレッドには存在する・プロフィールには載っていない」ことまで検証して完了です。
まとめ
- 実在アプリのUIを広告に使うのは、調べると想像以上に厳しい(Slackは加工禁止・LINEは全動画事前確認・Apple筐体の自作CGは明示禁止)。架空アプリをコードで作るほうが速くて安全だった
- Remotionは「動画をpropsで差し替え可能な部品の集合として持つ」道具。広告のようにバリアントと修正往復が多い動画と相性がいい
- Fable 5のようなエージェントと組むと、権利調査→UI部品の並列実装→ピクセル検品→配信APIまでが1つの会話の中で繋がる。人間の仕事は方向の決定とダメ出しに寄っていく
動画の中で使っているkoedesk本体はこちらです。iPhoneのキーボードとして動く音声入力で、文字が打てる場所ならどこでも使えます(パスワード欄など、iOSの仕様でサードパーティキーボードが使えない欄を除く)。
近藤政貴 — Guide Inc. Vietnam CEO. koedesk を作っています。


Discussion