はじめに
「そのプロダクト、誰が使うのでしょうか?」
理解しています。すべて痛いほど理解しています。
しかし、誰かが最初の一歩を踏み出さなければ、何も始まりません。
Appleでさえ最初は「パソコンなんて誰が家で使うのか?」と言われました。Airbnbも「他人の家に泊まるなんて気持ちが悪い」と投資家全員に断られました。
そのような話が好きで、苦労を克服した話を聞くと、やる気も出ます。
PMFに至るまでの泥臭い道のり。資金が尽きかけた時の判断。チームが崩壊しかけた時にどう立て直したか。
そういった話を、ラジオ感覚で聴いて、心を燃やしたかったのです!
世の中にないのなら、作る。
それこそが、事業を作る人間のマインドセットではないでしょうか。
完成した動画の例 (クリックで再生)
特徴:
- 焚き火が見える背景映像(生成AI製)
- 焚き火のパチパチ音
- 落ち着いたナレーション
- さりげないBGM(Suno生成)
- 通勤中にイヤホンで聴くのに最適
なぜRemotionなのか
世間の「動画自動生成」へのアプローチ
昨今、動画自動生成の話題になると、必ず挙がるのが「AIエージェントに全て任せる」というアプローチです。
- 「Claude Codeに動画編集ソフトを操作させよう」
- 「GPT-4にFFmpegコマンドを考えさせよう」
- 「マルチエージェントで役割分担させよう」
確かに素晴らしいですし、デモとしては非常に見栄えが良く、X(旧Twitter)でも話題になります。
しかし、事業に携わる方ならお分かりいただけるかと思います。「デモで動く」ことと「本番で使える」ことは全くの別物です。
エージェントに動画編集を任せると、以下のような事態が起こり得ます。
- 試行錯誤のコストが高い — 1回のレンダリングに数分かかり、「少し違う」を繰り返すだけで1時間が経過します。
- 再現性がない — 同じプロンプトでも毎回微妙に出力が異なり、品質が安定しません。
- デバッグが困難 — 「なぜかタイミングがズレる」といった不具合の原因特定に半日を費やすこともあります。
- APIコストの増大 — 試行錯誤 × 複数エージェント = 月末の請求書を見て愕然とします。
これではスケールさせることは難しいでしょう。
毎日動画を作りたいのに、 毎回くじ引きを引くようなシステムでは実運用に耐えられません。
Remotionという選択
Remotionは「Reactで動画を作る」というフレームワークです。
claude codeのSkillが話題ですが、今回のポイントは「一度テンプレートを作れば、データを変えるだけで動画が量産できる」という点にあります。
// Reactコンポーネントとして動画を定義
export const MyStory = () => {
return <StoryTemplate slideData={slideData} audioBasePath={STORY_NAME} />;
};
AIエージェントに毎回「動画を作ってください」と頼むのではなく、データ生成だけをLLMに任せ、レンダリングは決定論的(Deterministic)に行います。
これはプロダクト開発と同様です。なるべく不確実性は排除し、自動化するのです。
全体アーキテクチャ
各コンポーネントの詳細
Step 1: Gemini Deep Researchでコンテンツ収集
自分が聴きたいテーマについて、Gemini Deep Researchを用いて調査します。
例えば:
- 「Ankerの創業からPMFまでの道のり」
- 「東京大学の歴史と日本の近代化」
- 「サントリーの創業者・鳥井信治郎の挑戦」
- 「YAMAHAがピアノメーカーからバイクを作るまで」
Deep Researchの出力を target_data.txt に貼り付けるだけです。
Step 2: スクリプト生成(Gemini 2.5 Pro)
target_data.txt からナレーション用のスクリプトを生成します。
BASE_PROMPT = """
あなたは長尺ストーリー動画の詳細なスクリプトライターです。
## ストーリー構造の要件
以下のセクションを必ず含めてください:
1. 起業前(創業者の背景)
2. 創業直後(初期の苦労)
3. PMF達成まで(試行錯誤)
4. PMF達成(転換点)
5. PMF後のいざこざ(成長痛)
6. 現在(成果と教訓)
## トーン・言葉選び
- 話し言葉で、友達に語りかけるテンション
- 「〜なんです」「〜ですよね」
- 専門用語は出しつつ、すぐ言い換える
"""
Step 3: ナレーション生成(Gemini TTS)
スクリプトから音声を生成します。チャプターごとに並列処理を行います。
def run_per_chapter(script_data: dict, output_dir: str, ...):
"""チャプターごとにナレーション生成"""
with ThreadPoolExecutor(max_workers=min(3, len(chapters))) as executor:
futures = {
executor.submit(_generate_chapter, idx, chapter): idx
for idx, chapter in enumerate(chapters, 1)
}
Gemini TTS選定の理由:
-
voice="Charon"— 落ち着いた声で長時間聴いても疲れません。 -
style="warm and lower tone, slowly"— ラジオのような雰囲気を演出できます。
Step 4: タイムライン生成(Whisper API)
音声ファイルからタイムスタンプを取得します。これはRemotionでのテロップ表示に不可欠です。
def transcribe_audio(audio_path: Path, ...):
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
response_format="verbose_json",
timestamp_granularities=["segment", "word"],
)
なぜGeminiではなくWhisperなのか:
Geminiも音声解析は可能ですが、現状ではタイムスタンプの精度が十分とは言えません。Whisperであれば、単語単位で正確な開始・終了時間を返してくれます。
Step 5: Remotionデータ生成 & レンダリング(核心部分)
ここがこのパイプラインの要です。remotion_generator.py が全体を統括します。
処理の流れ
def run(output_dir: str, skip_component_generation: bool = False):
"""Remotion用slideData.jsonを生成"""
# 1. generated_context.json(スクリプト)を読み込み
with open(context_file, "r", encoding="utf-8") as f:
context_data = json.load(f)
title = context_data.get("title", "")
company_name = context_data.get("company_name", "")
chapters = context_data.get("chapters", [])
# 2. タイトルタイムラインを処理
title_timeline_file = output_path / "timeline_title.json"
if title_timeline_file.exists():
with open(title_timeline_file, "r") as f:
title_timeline = json.load(f)
title_duration = title_timeline.get("duration", 0)
# タイトルのハイライト(強調ワード)をLLMで抽出
title_highlights = extract_highlights_with_llm(
title_text,
{"company_name": company_name, "chapter_name": "タイトル"}
)
# 3. チャプターを並行処理(ここが速度の肝)
with ThreadPoolExecutor(max_workers=4) as executor:
for chapter in chapters:
future = executor.submit(process_chapter, idx, chapter)
futures.append(future)
スライド生成のロジック
各チャプターのWhisperセグメントとスクリプトをマッピングし、スライドを生成します。
def generate_slides_from_segments(segments, chapter_content, context):
"""Whisperセグメントからスライドを生成(1セグメント=1スライド)"""
# LLM処理を並行実行(マッピング&ハイライト抽出)
with ThreadPoolExecutor(max_workers=2) as executor:
# Whisperの文字起こしとスクリプト原稿を対応づけ
future_mapping = executor.submit(
map_script_to_segments_with_llm,
chapter_content,
segments,
context
)
# 強調すべきワードを抽出
future_highlights = executor.submit(
extract_highlights_with_llm,
chapter_content,
context
)
mapped_segments = future_mapping.result()
chapter_highlights = future_highlights.result()
# 1セグメント = 1スライド として生成
slides = []
for mapped_seg in mapped_segments:
script_text = mapped_seg.get("script_text", "").strip()
slides.append({
"start": mapped_seg.get("start", 0),
"end": mapped_seg.get("end", 0),
"duration": mapped_seg.get("end", 0) - mapped_seg.get("start", 0),
"text": script_text,
"highlights": [h for h in chapter_highlights if h in script_text]
})
return slides
ハイライト抽出(LLM)
テロップで強調すべきワードをLLMが判断します。
def extract_highlights_with_llm(text: str, context: dict) -> list[str]:
"""テキストから強調すべきワード/フレーズを抽出"""
prompt = f"""
以下のテキストから、動画で強調すべき重要なワードを抽出してください。
会社名: {context.get("company_name", "")}
チャプター: {context.get("chapter_name", "")}
テキスト:
{text}
以下のカテゴリから重要なものを抽出:
1. 固有名詞(人名、会社名、製品名、地名)
2. 重要概念(PMF、VOC、戦略的ピボットなど)
3. 感情的フレーズ(「絶体絶命」「逆転」「危機」など)
4. 数値・統計(「100万ドル」「1000万人」「2011年」など)
"""
result = call_llm_json(prompt, schema, model="gemini-2.5-flash")
return result.get("highlights", [])
コンポーネント自動生成
新しいストーリーごとにRemotionコンポーネントを自動生成します。
def create_story_component(story_name: str, component_name: str, src_dir: Path):
"""Storyコンポーネントファイルを生成"""
component_content = f"""
import slideDataJson from '../../public/{story_name}/slideData.json';
import {{ StoryTemplate }} from '../common/StoryTemplate';
import {{ calculateTotalDuration }} from '../common/StoryTemplate/utils';
const STORY_NAME = '{story_name}';
const slideData = slideDataJson as SlideData;
const TOTAL_DURATION = calculateTotalDuration(slideData);
export const {component_name}_DURATION_FRAMES = Math.floor(TOTAL_DURATION * 30);
export const {component_name} = () => {{
return <StoryTemplate slideData={{slideData}} audioBasePath={{STORY_NAME}} />;
}};
"""
with open(component_file, "w", encoding="utf-8") as f:
f.write(component_content)
生成されるslideData.jsonのサンプル
{
"title": {
"text": "[Ankerの歴史] 43歳で失職。借金だけが残った。しかし、そこから世界最大のモバイルバッテリー企業が生まれた",
"companyName": "ANKER INNOVATIONS",
"duration": 12.5,
"highlights": ["43歳", "失職", "借金", "世界最大"],
"segments": [
{
"id": 0,
"start": 0,
"end": 5.2,
"text": "Ankerの歴史。43歳で失職。",
"highlights": ["43歳", "失職"]
},
{
"id": 1,
"start": 5.2,
"end": 12.5,
"text": "借金だけが残った。しかし、そこから世界最大のモバイルバッテリー企業が生まれた。",
"highlights": ["借金", "世界最大"]
}
],
"audioPath": "narration_title.wav",
"audioDuration": 12.5
},
"chapters": [
{
"chapterNumber": 1,
"chapterName": "チャプター1: 起業前",
"introDuration": 3.0,
"audioPath": "narration_chapter1.wav",
"audioDuration": 180.5,
"slides": [
{
"start": 15.5,
"end": 22.3,
"duration": 6.8,
"text": "Steven Yangは1969年、中国湖南省で生まれました。",
"whisper_text": "スティーブンヤンは1969年中国湖南省で生まれました",
"highlights": ["Steven Yang", "1969年", "中国湖南省"]
},
{
"start": 22.3,
"end": 31.1,
"duration": 8.8,
"text": "地元の大学でコンピューターサイエンスを学んだ後、アメリカに渡り、テキサス大学で修士号を取得します。",
"whisper_text": "地元の大学でコンピューターサイエンスを学んだ後アメリカに渡りテキサス大学で修士号を取得します",
"highlights": ["コンピューターサイエンス", "アメリカ", "テキサス大学", "修士号"]
},
{
"start": 31.1,
"end": 45.6,
"duration": 14.5,
"text": "その後、Googleに入社。検索エンジンの広告システム開発に携わり、7年間エンジニアとして働きました。",
"whisper_text": "その後Googleに入社検索エンジンの広告システム開発に携わり7年間エンジニアとして働きました",
"highlights": ["Google", "検索エンジン", "広告システム", "7年間"]
}
]
},
{
"chapterNumber": 2,
"chapterName": "チャプター2: 創業直後",
"introDuration": 3.0,
"audioPath": "narration_chapter2.wav",
"audioDuration": 195.2,
"slides": [
{
"start": 198.5,
"end": 210.3,
"duration": 11.8,
"text": "2011年、Yangは43歳でGoogleを退職します。理由は「自分の会社を作りたかった」から。",
"highlights": ["2011年", "43歳", "Google", "退職"]
}
]
}
]
}
slideData.jsonのポイント:
-
segments/slides:Whisperのタイムスタンプと1対1で対応しています。 -
highlights:各スライドで強調表示するワードです。 -
whisper_text:Whisperの生の文字起こし(デバッグ用)です。 -
text:LLMが補完した正確なスクリプトです。
Step 6: CapCutで後処理
生成AIで作成した焚き火背景映像とSunoで生成したBGMを使用し、CapCutのテンプレートにある解説動画部分を差し替えるだけで完了します。

Remotionの使い回しが最適である理由
決定論的な出力
同じ slideData.json であれば、必ず同じ動画が出力されます。
これがAIエージェントとの最大の違いです。
- デバッグが容易
- 品質が安定する
- 「なぜか今日は違う」がない
これは事業運営と同じです。再現性のないプロセスはスケールしません。
コスト効率
- LLMコスト:1動画あたり約$0.5
- Whisperコスト:1動画あたり約$0.1
- レンダリング:ローカル実行のため無料
エージェントに試行錯誤をさせると、同等の品質を得るのに10倍以上のコストがかかるでしょう。
まとめ
「自分を勇気づける動画を毎日半自動生成する」という、一見すると自己啓発セミナーの宣伝のような試みをご紹介しました。
しかし実際にやってみると、これが非常に良いのです。
朝の通勤電車で、自分が興味あることについてのラジオを聴く。焚き火のパチパチ音が、満員電車の喧騒を少しだけ和らげてくれます。
Remotionは「エージェントに全て任せる」という最近のトレンドとは逆行するアプローチですが、安定性とコスト効率を考慮すると、現時点ではベストな選択だと考えています。
毎日、魂を燃やして努力を続けている方々への一助となれば幸いです。
💼 開発・技術相談
このようなAIパイプラインの構築や、プロダクト開発についてご相談されたい方へ。
フリーランスとして以下のサポートを提供しております。
- 🛠️ AI活用システム開発 — LLMを活用した自動化パイプラインの構築
- 📱 LINE Bot/LIFFアプリ開発 — CookForYouで培ったノウハウを活用
- 🚀 技術コンサルティング — アーキテクチャ設計、AI導入支援
- 📊 プロトタイプ開発 — アイデアを素早く形にします
お問い合わせ
- X: https://twitter.com/Yoooongtae
- Facebook: https://www.facebook.com/yongtaih1
- Email: yong723.enjoy.everything@gmail.com
お気軽にご相談ください!💪
(複数媒体にご連絡いただけると確実です)
