前の記事では、画面下部に表示するシンプルな字幕(Caption)を作りました。
この記事では一歩進んで、テロップ(Telop)を実装します。
字幕との違いは主に2点です。
- 表示位置を柔軟に切り替えられる(画面中央 / 下部)
- 日本語フォントや約物カーニングなど、見た目の品質にこだわれる
マニュアル動画・PV動画・製品紹介動画など、用途に応じてスタイルを変えたい場合に役立ちます。
環境構築・プロジェクト作成・基本的な書き出し手順は「Claude Code × Remotion で動画字幕を自動化する」で解説しています。この記事では
Telop.tsxの実装に絞って解説します。
Claude Code × Remotion で動画字幕を自動化する【環境構築から書き出しまで】
プロジェクト構成
テロップ用に追加・変更するファイルは次の通りです。
[project-name]/
├─ src/
│ ├─ components/
│ │ └─ Telop.tsx # ← この記事で作成
│ ├─ compositions/
│ │ └─ overlays/
│ │ └─ TelopOverlayFull.tsx # ← この記事で作成
│ ├─ content.ts # ← Gemini の出力を貼る
│ └─ Root.tsx
└─ public/
└─ fonts/
└─ ShipporiMincho-OTF/
├─ ShipporiMincho-OTF-Regular.otf
└─ ShipporiMincho-OTF-Medium.otf
Step 1: content.ts の設計
Gemini でタイムスタンプを自動生成する
Gemini に動画を渡して content.ts 形式で出力させると大幅に効率化できます。以下のプロンプトをそのまま使えます。
この動画をもとに、Remotion用のタイムスタンプデータ/各シーンでのテロップ案を作成してください。
## 出力形式
TypeScript の配列のみ出力してください。Markdown は不要です。
以下のインターフェースに従ってください。
interface Step {
id: number;
start: string; // "MM:SS.ff"
end: string; // "MM:SS.ff"
scene: string; // シーン名
telop: string; // 日本語 30 文字以内。不要なシーンは ""
telopDraft?: {
draft1?: string; // テロップ案1
draft2?: string; // テロップ案2
draft3?: string; // テロップ案3
}
}
export const STEPS: Step[] = [...];
## 動画情報
- 総尺: [秒数]秒
- 内容: [動画の内容を簡潔に]
出力されたものをそのまま content.ts に貼り付けるだけです。Markdown テーブルよりパースエラーが少なく、interface 定義をプロンプトに含めることでフィールド漏れも防止できます。
Step 2: Telop.tsx の実装
フォントの読み込み
Remotion では staticFile() を使って public/ フォルダ内のフォントを参照します。@font-face を文字列として定義し、<style> タグで注入するのが基本パターンです。
import { staticFile } from "remotion";
const fontFace = `
@font-face {
font-family: 'Shippori Mincho OTF';
src: url('${staticFile("fonts/ShipporiMincho-OTF/ShipporiMincho-OTF-Regular.otf")}') format('opentype');
font-weight: 400;
}
@font-face {
font-family: 'Shippori Mincho OTF';
src: url('${staticFile("fonts/ShipporiMincho-OTF/ShipporiMincho-OTF-Medium.otf")}') format('opentype');
font-weight: 500;
}
`;
staticFile() を使う理由:/fonts/... とハードコードすると、レンダリング時にパスが解決されずフォントが適用されません。必ず staticFile() を経由してください。
コンポーネント全体
// src/components/Telop.tsx
import React from "react";
import { useCurrentFrame, interpolate, staticFile } from "remotion";
const fontFace = `
@font-face {
font-family: 'Shippori Mincho OTF';
src: url('${staticFile("fonts/ShipporiMincho-OTF/ShipporiMincho-OTF-Regular.otf")}') format('opentype');
font-weight: 400;
}
@font-face {
font-family: 'Shippori Mincho OTF';
src: url('${staticFile("fonts/ShipporiMincho-OTF/ShipporiMincho-OTF-Medium.otf")}') format('opentype');
font-weight: 500;
}
`;
interface TelopProps {
text: string;
startFrame: number;
endFrame: number;
/** 表示位置: "center"(デフォルト)または "lower"(画面下部) */
position?: "center" | "lower";
}
export const Telop: React.FC<TelopProps> = ({
text,
startFrame,
endFrame,
position = "center",
}) => {
const frame = useCurrentFrame();
const fadeInDuration = 15;
const fadeOutDuration = 15;
const opacity = interpolate(
frame,
[startFrame, startFrame + fadeInDuration, endFrame - fadeOutDuration, endFrame],
[0, 1, 1, 0],
{ extrapolateLeft: "clamp", extrapolateRight: "clamp" }
);
if (frame < startFrame || frame > endFrame) return null;
const positionStyle =
position === "center"
? {
top: 0, bottom: 0, left: 0, right: 0,
margin: "auto",
display: "flex",
justifyContent: "center",
alignItems: "center",
}
: {
top: 0, bottom: 0, left: 0, right: 0,
margin: "auto",
display: "flex",
justifyContent: "center",
alignItems: "end",
paddingBottom: 80,
};
return (
<>
<style>{fontFace}</style>
<div
style={{
position: "absolute",
...positionStyle,
opacity,
// フォント設定
fontFamily: "'Shippori Mincho OTF', serif",
fontSize: 176, // 4K 基準。1080p なら 96 前後
fontWeight: 500,
color: "#FFFFFF",
// 約物カーニング
fontKerning: "normal",
fontFeatureSettings: '"palt"',
// テキスト設定
letterSpacing: "0.03em",
lineHeight: 1.66,
textAlign: "center",
whiteSpace: "pre-wrap", // \n を改行として表示
}}
>
{text}
</div>
</>
);
};
実装のポイント
縦位置の切り替え(position prop)
"center" で画面中央、"lower" で画面下部に表示します。用途に応じて使い分けてください。
// 画面中央(PV・プロモーション映像向け)
<Telop text="未来を、標準に。" position="center" ... />
// 画面下部(マニュアル動画・操作説明向け)
<Telop text="「設定」をクリックします" position="lower" ... />
改行対応
content.ts で \n を使った改行は、CSS の whiteSpace: "pre-wrap" で自動的に改行として表示されます。
telop: "上質な暮らしを、\nここから始める。",
約物カーニング
OpenType の palt 機能を有効にすることで、句読点・カギ括弧などの余白が自然に詰まります。日本語テロップでは指定しておくことをおすすめします。
fontKerning: "normal",
fontFeatureSettings: '"palt"',
4K 制作時のフォントサイズ
解像度によって適切なフォントサイズが変わります。目安は以下の通りです。
| 解像度 | fontSize の目安 |
|---|---|
| 1080p(1920×1080) | 80〜96px |
| 4K(3840×2160) | 160〜200px |
Step 3: TelopOverlayFull コンポジションの作成
// src/compositions/overlays/TelopOverlayFull.tsx
import React from "react";
import { AbsoluteFill, Sequence } from "remotion";
import { Telop } from "../../components/Telop";
import { STEPS, toFrame, VIDEO_CONFIG } from "../../content";
export const TelopOverlayFull: React.FC = () => {
const { fps } = VIDEO_CONFIG;
return (
<AbsoluteFill style={{ backgroundColor: "transparent" }}>
{STEPS.filter((step) => step.telop !== "").map((step) => {
const startFrame = toFrame(step.start, fps);
const endFrame = toFrame(step.end, fps);
return (
<Sequence
key={step.id}
from={startFrame}
durationInFrames={endFrame - startFrame}
>
<Telop
text={step.telop}
startFrame={0}
endFrame={endFrame - startFrame}
position="center"
/>
</Sequence>
);
})}
</AbsoluteFill>
);
};
step.telop !== "" のフィルターにより、空文字のシーンは自動的にスキップされます。
Step 4: Root.tsx への登録と書き出し
// src/Root.tsx
import { Composition } from "remotion";
import { TelopOverlayFull } from "./compositions/overlays/TelopOverlayFull";
import { VIDEO_CONFIG } from "./content";
const { fps, width, height, durationSeconds } = VIDEO_CONFIG;
export const RemotionRoot: React.FC = () => (
<>
<Composition
id="TelopOverlayFull"
component={TelopOverlayFull}
durationInFrames={durationSeconds * fps}
fps={fps}
width={width}
height={height}
/>
</>
);
書き出しコマンドは字幕記事と同じ形式です。
npx remotion render TelopOverlayFull output/telop.mov \
--image-format=png \
--pixel-format=yuva444p10le \
--codec=prores \
--prores-profile=4444 \
--muted
package.json にスクリプト登録しておくと便利です。
{
"scripts": {
"render:telop": "npx remotion render TelopOverlayFull output/telop.mov --image-format=png --pixel-format=yuva444p10le --codec=prores --prores-profile=4444 --muted"
}
}
Premiere Pro での合成
書き出した telop.mov を元動画の上のトラックに配置するだけです。
# Premiere Pro タイムライン
├─ V2: telop.mov(テロップオーバーレイ)
└─ V1: [元動画]
タイムスタンプは content.ts 側で制御されているため、Premiere Pro での位置調整は基本的に不要です。修正が必要な場合も content.ts の start / end を変更して再レンダリングするだけです。
まとめ・関連記事
この記事では Telop.tsx の実装を中心に、日本語フォントの読み込み・約物カーニング・縦位置の切り替えを解説しました。
content.ts への Gemini 出力の流し込みと組み合わせることで、テロップ付けの作業を大幅に効率化できます。
Claude Code × Remotion で動画字幕を自動化する【環境構築から書き出しまで】
Remotion で Callout アニメーションを作る【Studio × Zod でリアルタイム座標調整】
Remotion で LottieFiles のアニメーションを使う【矢印・アイコンをオーバーレイ動画に組み込む】

