動画に字幕を付ける作業、地味に時間がかかりませんか?

テロップを1枚ずつ作って読み込んで位置合わせ…という繰り返し作業は、マニュアル動画でもPV動画でも変わりません。

この記事では、Claude Code × Remotion を使って、動画の字幕(キャプション)を透明背景のオーバーレイ動画として書き出す方法を解説します。Premiere Pro に重ねるだけで字幕が完成する仕組みを一度作れば、あとは content.ts を書き換えて再レンダリングするだけです。


    ワークフロー

    最終的なワークフローはシンプルです。

    元動画(録画・PV映像など)
        ↓
    # Remotion で生成
    - caption.mov(字幕オーバーレイ・透過)
        ↓
    # Premiere Pro で合成
      ├─ V2: caption.mov(字幕)
      └─ V1: preview.mp4(元動画)
        ↓
    完成動画
    

    Remotion が書き出すのは ProRes 4444(アルファチャンネル付き).mov ファイルです。Premiere Pro のタイムラインに乗せるだけで透過合成されます。

    字幕の内容やタイミングはすべて content.ts で管理するため、修正はテキストを書き換えて再レンダリングするだけ。フォントや見た目の変更も1ファイルで完結します。

    前提条件

    • Node.js 18 以上
    • Claude Code(Anthropic)

    Claude Code がなくても Remotion 単体で完結しますが、コンポーネントの修正や座標調整を自然言語で指示できるため、あわせて使うことを前提にしています。


    Step 1: プロジェクトの作成

    Remotion の公式テンプレートからプロジェクトを作成します。

    npx create-video@latest [project-name]
    cd [project-name]
    

    途中でテンプレートを選ぶ画面が出ます。最初は Hello World(デフォルト)で問題ありません。

    プロジェクトが作成されると、以下のような構成になっています。

    [project-name]/
    ├─ src/
    │     ├─ Composition.tsx   # サンプルコンポジション
    │     └─ Root.tsx          # コンポジション登録
    ├─ public/                  # 静的ファイル置き場(フォント・動画など)
    └─ package.json
    

    Step 2: 必要なパッケージのインストール

    Remotion Skills のインストール

    Claude Code が Remotion のベストプラクティスを理解するためのスキルファイルをインストールします。Claude Code への指示精度が上がるため、最初に入れておくことをおすすめします。

    npx skills install remotion-dev/skills
    

    フォントパッケージ(任意)

    日本語フォントを使う場合は、public/fonts/ にフォントファイルを置くか、npm パッケージで管理できます。

    # 例:しっぽり明朝(npm パッケージ版)
    npm install @sarap422/font-shippori-mincho-otf
    

    フォントの詳しい使い方は「Remotion でテロップを作る」で解説しています。

    Gemini×Remotion でテロップを作る【Telop.tsx の実装とフォント設定】 Remotionでテロップコンポーネント(Telop.tsx)を実装する方法を解説。日本語フォント・約物カーニング・フェードアニメーション・縦位置の切り替えなど、品質にこだわった実装を紹介。Geminiとのcontent.ts連携でタイムスタンプ生成も自動化で...  続きを読む

    Step 3: content.ts の作成

    字幕のタイムスタンプと本文を content.ts で一元管理します。
    「どのファイルを直せばいいか」が一目でわかるのが最大のメリットです。

    // src/content.ts
    /**
    * 動画情報
    * 総尺: X分XX秒
    * 内容: XXXXXX
    */
    
    // 動画の基本設定
    export const VIDEO_CONFIG = {
    fps: 30,
    width: 3840,
    height: 2160,
    durationSeconds: 60,
    };
    
    // タイムスタンプをフレーム数に変換
    export const toFrame = (timestamp: string, fps: number): number => {
    const [min, sec] = timestamp.split(":").map(Number);
    return Math.round((min * 60 + sec) * fps);
    };
    
    export interface Caption {
      id: number;
      start: string;      // "MM:SS" 形式
      end: string;        // "MM:SS" 形式
      caption: string;    // 字幕テキスト
    }
    
    export const CAPTIONS: Caption[] = [
      {
        id: 1,
        start: "00:05",
        end: "00:15",
        caption: "管理画面から「設定」を開きます",
      },
      {
        id: 2,
        start: "00:15",
        end: "00:28",
        caption: "「保存」ボタンをクリックして完了です",
      },
      // 続く...
    ];
    

    タイムスタンプの作り方

    手で書いてもよいですが、Gemini に動画を読み込ませて自動生成させる方法が効率的です。以下のプロンプトで content.ts 形式のまま出力させられます。

    この動画は「〼〼〼〼の方法」の操作手順です。
    draft-XXXX.md の下書き構成に沿って、字幕のタイムスタンプデータ content-XXXX.ts を作成してください。
    
    ## 出力形式
    TypeScript の配列として出力してください。Markdown は不要です。
    
    /**
    * 動画情報
    * 総尺: X分XX秒
    * 内容: XXXXXX
    */
    
    // 動画の基本設定
    export const VIDEO_CONFIG = {
    fps: 30,
    width: 3840,
    height: 2160,
    durationSeconds: 60,
    };
    
    /** "MM:SS" or "MM:SS.ff" → 秒数(ff はフレーム番号) */
    export const toSeconds = (ts: string, fps: number = 30): number => {
      const [time, frameStr] = ts.split(".");
      const [m, s] = time.split(":").map(Number);
      const frames = frameStr ? Number(frameStr) : 0;
      return m * 60 + s + frames / fps;
    };
    
    interface Caption {
      id: number;
      start: string;           // "MM:SS.ff"
      end: string;             // "MM:SS.ff"
      caption: string;         // キャプション(字幕/※不要なら空文字)
    }
    
    export const CAPTIONS: Caption[] = [
      { id: 1, start: "MM:SS", end: "MM:SS", caption: "字幕テキスト" },
      ...
    ];
    
    ## 制約
    - start/end は "MM:SS.ff" 形式(例: "00:05.00", "01:30.15")
    - text は日本語 30 文字以内
    - 配列のみ出力(説明文不要)
    

    出力されたものをそのまま content.ts に貼り付けるだけです。


    Step 4: Caption コンポーネントの作成

    画面下部に表示するシンプルな字幕コンポーネントです。Claude Code に作ってもらうのが早いですが、ベースとなるコードを以下に示します。

    // src/components/Caption.tsx
    
    import React from "react";
    import { useCurrentFrame, interpolate, Easing, staticFile } from "remotion";
    
    const fontFace = `
    @font-face {
      font-family: 'Noto Sans JP';
      src: url('${staticFile("fonts/Noto_Sans_JP/NotoSansJP-Regular.woff2")}') format('woff2');
      font-weight: 400;
      font-style: normal;
    }
    `;
    
    interface CaptionProps {
      text: string;
      startFrame: number;
      endFrame: number;
    }
    
    export const Caption: React.FC<CaptionProps> = ({
      text,
      startFrame,
      endFrame,
    }) => {
      const frame = useCurrentFrame();
      const fadeInDuration = 8;
      const fadeOutDuration = 8;
    
      const opacity = interpolate(
        frame,
        [startFrame, startFrame + fadeInDuration, endFrame - fadeOutDuration, endFrame],
        [0, 1, 1, 0],
        { extrapolateLeft: "clamp", extrapolateRight: "clamp" },
      );
    
      const translateY = interpolate(
        frame,
        [startFrame, startFrame + fadeInDuration],
        [20, 0],
        {
          extrapolateLeft: "clamp",
          extrapolateRight: "clamp",
          easing: Easing.out(Easing.cubic),
        },
      );
    
      if (frame < startFrame || frame > endFrame) return null;
    
      return (
        <>
          <style>{fontFace}</style>
          <div
            style={{
              position: "absolute",
              bottom: 80,
              left: "50%",
              transform: `translateX(-50%) translateY(${translateY}px)`,
              opacity,
              backgroundColor: "rgba(0, 0, 0, 0.75)",
              color: "#FFFFFF",
              padding: "24px 56px",
              fontFamily: "'Noto Sans JP', sans-serif",
              fontSize: 80,
              fontWeight: 400,
              lineHeight: 1.5,
              width: "100%",
              textAlign: "center",
              whiteSpace: "pre-wrap",
              letterSpacing: "0.02em",
            }}
          >
            {text}
          </div>
        </>
      );
    };
    

    フォント・色・サイズなどのカスタマイズは Claude Code に「フォントをしっぽり明朝にして」「背景を青にして」と指示するだけで変更できます。


    Step 5: CaptionOverlay コンポジションの作成

    content.ts のデータを読み込み、字幕を時系列に並べるコンポジションです。

    // src/compositions/CaptionOverlay.tsx
    
    import { AbsoluteFill, Sequence } from "remotion";
    import { Caption } from "../components/Caption";
    import { CAPTIONS, toFrame, VIDEO_CONFIG } from "../content";
    
    export const CaptionOverlay: React.FC = () => {
      const { fps } = VIDEO_CONFIG;
    
      return (
        <AbsoluteFill style={{ backgroundColor: "transparent" }}>
          {CAPTIONS.map((caption) => {
            const startFrame = toFrame(caption.start, fps);
            const endFrame = toFrame(caption.end, fps);
    
            return (
              <Sequence
                key={caption.id}
                from={startFrame}
                durationInFrames={endFrame - startFrame}
              >
                <Caption
                  text={caption.text}
                  startFrame={0}
                  endFrame={endFrame - startFrame}
                />
              </Sequence>
            );
          })}
        </AbsoluteFill>
      );
    };
    

    Step 6: Root.tsx へのコンポジション登録

    // src/Root.tsx
    
    import { Composition } from "remotion";
    import { CaptionOverlay } from "./compositions/CaptionOverlay";
    import { VIDEO_CONFIG } from "./content";
    
    export const RemotionRoot: React.FC = () => {
      return (
        <>
          <Composition
            id="CaptionOverlay"
            component={CaptionOverlay}
            durationInFrames={VIDEO_CONFIG.durationInFrames}
            fps={VIDEO_CONFIG.fps}
            width={VIDEO_CONFIG.width}
            height={VIDEO_CONFIG.height}
          />
        </>
      );
    };
    

    Step 7: Remotion Studio でプレビュー確認

    コンポーネントが完成したら、書き出す前に Studio でプレビューを確認します。

    cd "[project-name]"
    
    npx remotion studio
    

    ブラウザで http://localhost:3000 が開きます。左サイドバーから CaptionOverlay を選択すると、タイムライン上で字幕の表示・タイミングを確認できます。

    おすすめの使い方

    Cmd(Ctrl) + T で、ターミナルを2つ開いておくと作業がスムーズです。

    ターミナル①:npx remotion studio(起動したまま)
    ターミナル②:claude(Claude Code を起動)
    

    ファイルを保存するたびにブラウザが自動リロードされるため、Claude Code で修正 → Studio でリアルタイム確認、というサイクルを高速で回せます。

    実際の映像と重ねて確認したい場合

    字幕オーバーレイは背景が透過なので、Studio 上ではチェッカー柄になります。実際の映像と合わせて確認するには、Root.tsx に Preview コンポジションを追加します。

    // Root.tsx に追加
    import { OffthreadVideo, staticFile } from "remotion";
    
    const Preview: React.FC = () => (
      <AbsoluteFill>
        <OffthreadVideo src={staticFile("video/preview.mp4")} />
        <CaptionOverlay />
      </AbsoluteFill>
    );
    
    // Composition を追加登録
    <Composition
      id="Preview"
      component={Preview}
      durationInFrames={VIDEO_CONFIG.durationInFrames}
      fps={VIDEO_CONFIG.fps}
      width={VIDEO_CONFIG.width}
      height={VIDEO_CONFIG.height}
    />
    

    動画ファイルは public/video/preview.mp4 として置き、必ず staticFile() を使って参照してください。http://localhost:3000/... とハードコードするとレンダリング時にエラーになります。


    Step 8: 透過動画の書き出し

    透明背景を維持するには、以下の 4つのオプションをすべて指定する必要があります。

    cd "[project-name]"
    
    npx remotion render CaptionOverlay output/caption-overlay.mov \\
      --image-format=png --pixel-format=yuva444p10le --codec=prores --prores-profile=4444 --muted
    

    オプションの意味はそれぞれ次の通りです。

    オプション 理由
    --image-format=png アルファチャンネルを扱うために必須。省略すると次のエラー:Pixel format was set to 'yuva444p10le' but the image format is not PNG.
    --pixel-format=yuva444p10le アルファチャンネル(透過情報)を含むピクセルフォーマット
    --codec=prores ProRes コーデックを指定
    --prores-profile=4444 アルファチャンネルに対応したプロファイル
    --muted 字幕オーバーレイに音声は不要なため

    package.json にスクリプト登録しておくと便利です。

    {
      "scripts": {
        "render:caption": "remotion render CaptionOverlay output/caption.mov --image-format=png --pixel-format=yuva444p10le --codec=prores --prores-profile=4444 --muted"
      }
    }
    

    以降は npm run render:caption で書き出せます。


    Step 9: Premiere Pro での合成

    書き出した caption.mov を Premiere Pro に読み込み、元動画の上のトラックに配置します。

    # Premiere Pro タイムライン
      ├─ V2: caption.mov(字幕オーバーレイ)
      └─ V1: preview.mp4(元動画)
    

    ProRes 4444 は Premiere Pro がネイティブで透過を認識するため、特別な設定は不要です。配置するだけで字幕が合成されます。


    Claude Code への指示例

    仕組みが完成したあとの運用は、content.ts を更新して書き出すだけです。
    Claude Code を使う場合は以下のように一括依頼できます。

    content.ts の CAPTIONS を以下の内容で更新して、書き出してください。
    
    ## CAPTIONS
    
    1. 00:05-00:12: 「設定画面を開きます」
    2. 00:12-00:25: 「項目を選択してください」
    3. 00:25-00:40: 「保存ボタンをクリックして完了です」
    
    ## 書き出し
    
    npm run render:caption
    

    まとめ・関連記事

    この記事では、字幕オーバーレイを ProRes 4444 の透過動画として書き出す基本セットアップを解説しました。

    content.ts にタイムスタンプとテキストを書いて npm run render:caption を実行するだけで字幕動画が生成できます。マニュアル動画・PV動画・製品紹介動画など、字幕が必要な動画制作全般に使い回せる仕組みです。

    より凝った表現をしたい場合は、以下の記事でステップアップできます。

    Gemini×Remotion でテロップを作る【Telop.tsx の実装とフォント設定】 Remotionでテロップコンポーネント(Telop.tsx)を実装する方法を解説。日本語フォント・約物カーニング・フェードアニメーション・縦位置の切り替えなど、品質にこだわった実装を紹介。Geminiとのcontent.ts連携でタイムスタンプ生成も自動化で...  続きを読む Remotion で Callout アニメーションを作る【Studio × Zod でリアルタイム座標調整】 Remotionでコールアウト(地図ピン・波紋・コネクター線・ラベル)をdivアニメーションで実装する方法を解説。SVGが使えない問題の解決策、段階的アニメーションのチェイン、Remotion Studio+Zodスキーマによるリアルタイム座標調整まで踏み込ん...  続きを読む Remotion で LottieFiles のアニメーションを使う【矢印・アイコンをオーバーレイ動画に組み込む】 RemotionにLottieFilesのアニメーション(矢印・アイコン等)を組み込む方法を解説。@remotion/lottieのインストールからJSON配置・カラー変更・フェードアニメーション・透過書き出しまで、動画オーバーレイへの実践的な活用方法を紹介し...  続きを読む

    参考リンク