TTS (Azure) - Remotion テンプレート 解説
本ドキュメントは、Remotion TTS Exampleプロジェクトの包括的な技術資料です。
リンク
- GitHub リポジトリ: https://github.com/FelippeChemello/Remotion-TTS-Example
- Remotion公式テンプレート: https://www.remotion.dev/templates/tts
目次
プロジェクト概要
概要
TTS (Azure) - テキストを音声化された動画に変換するテンプレートです。音声合成にはAzure Cloudと連携します。
このプロジェクトは、Remotionを使用してText-to-Speech(TTS)機能を持つビデオを生成するサンプルアプリケーションです。Azure Cognitive Services Speech APIでテキストを音声に変換し、AWS S3に保存してからRemotionで動画を生成します。
このプロジェクトはRemotionの公式テンプレートとして提供されており、FelippeChemelloによって開発・メンテナンスされています。
技術スタック
- フロントエンド: React, TypeScript
- 動画生成: Remotion
- TTS: Azure Cognitive Services Speech SDK
- ストレージ: AWS S3
- バリデーション: Zod
- その他: MD5(ファイル名ハッシュ化)
プロジェクト構造
src/
├── HelloWorld.tsx # メインコンポーネント(動画表示)
├── HelloWorld/
│ └── Title.tsx # アニメーション付きタイトル表示
├── Root.tsx # Remotion Root コンポーネント
├── tts.ts # TTS機能の実装
├── types.ts # 型定義とスキーマ
├── debounce.ts # 入力待機機能
└── index.ts # エントリーポイント
処理フロー
1. 初期化フロー
- Root.tsx:8-47 - Remotionコンポジションの定義
- types.ts:4-13 - 環境変数の読み込みと検証
- types.ts:19-24 - プロパティスキーマの定義
2. TTS音声生成フロー
-
Root.tsx:24-42 -
calculateMetadata内での音声生成処理 - debounce.ts:3-25 - 入力待機(1秒)
- tts.ts:86-108 - S3に音声ファイルが既に存在するかチェック
-
tts.ts:34-84 - 音声合成処理:
- Azure Speech SDKでSSML形式の音声を生成
- S3に音声ファイルをアップロード
- tts.ts:131-141 - S3のパブリックURLを生成
3. 動画レンダリングフロー
-
HelloWorld.tsx:13-44 - メインコンポーネント:
- 音声の再生
- タイトルテキストの表示
- フェードアウトアニメーション
-
Title.tsx:3-52 - アニメーション付きタイトル:
- 単語ごとのスプリングアニメーション
- 時間差での表示制御
重要な処理部分
音声合成 (tts.ts:34-84)
export const synthesizeSpeech = async (text: string, voice: Voice): Promise<void>
- Azure Speech SDKを使用したSSML形式の音声合成
- 音声データのS3アップロード
- エラーハンドリング
ファイル名生成 (tts.ts:17-25)
export const getFileName = ({ text, voice }: { text: string; voice: string }) => {
return `${md5(`${text}--${voice}`)}.mp3`;
};
- テキストと音声の組み合わせからMD5ハッシュを生成
- キャッシュ機能の実現
動的メタデータ計算 (Root.tsx:24-42)
calculateMetadata={async ({ props, abortSignal }) => {
// 音声生成とファイル時間の計算
const duration = await getAudioDurationInSeconds(fileName);
return { props, durationInFrames: Math.ceil(duration * 30) };
}}
- 音声の長さに基づいた動画時間の動的計算
- 音声ファイルの存在確認とキャッシュ
アニメーション (Title.tsx:25-48)
transform: `scale(${spring({
fps: videoConfig.fps,
frame: frame - i * displaySpeed,
config: { damping: 100, stiffness: 200, mass: 0.5 },
})})`,
- 単語ごとの時間差スプリングアニメーション
-
displaySpeedによる表示速度制御
環境設定
- Azure: TTS_KEY, TTS_REGION
- AWS: ACCESS_KEY_ID, SECRET_ACCESS_KEY, S3_BUCKET_NAME, S3_REGION
- 音声: 4種類の音声(日本語ブラジル、英語)をサポート
基本的な使用方法
-
npm run dev- プレビュー開始 -
npm run build- 動画のビルド -
npx remotion render- 動画のレンダリング
実際の動作実行手順
前提条件
- Node.js (推奨:18.x以上)
- npm または yarn
1. 環境セットアップ
1.1 Azureアカウントの作成とTTSサービスの設定
- Azure Portalにアクセス
- 「Speech Services」を検索して作成
- 以下の情報を取得:
-
キー:
AZURE_TTS_KEY -
地域:
AZURE_TTS_REGION(例: eastus)
-
キー:
⚠️ 注意: サブスクリプションが有効になるまで時間がかかる場合があり、その間は「1006」エラーが発生する可能性があります。
1.2 AWS S3バケットの設定
- AWS ConsoleでS3バケットを作成
- バケットポリシーを設定(パブリック読み取り許可):
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowPublicRead",
"Effect": "Allow",
"Principal": { "AWS": "*" },
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
}
]
}
- CORS設定を追加:
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["HEAD", "GET", "PUT", "POST", "DELETE"],
"AllowedOrigins": ["*"],
"ExposeHeaders": ["ETag", "x-amz-meta-custom-header"]
}
]
- IAMユーザーを作成し、以下の権限を付与:
s3:GetObjects3:PutObject- 対象バケットのみに制限
1.3 環境変数の設定
-
.env.exampleを.envにコピー:
cp .env.example .env
-
.envファイルを編集:
AWS_ACCESS_KEY_ID=your_access_key_id
AWS_SECRET_ACCESS_KEY=your_secret_access_key
AWS_S3_BUCKET_NAME=your_bucket_name
AWS_S3_REGION=your_region
AZURE_TTS_KEY=your_azure_tts_key
AZURE_TTS_REGION=eastus
2. プロジェクトの実行
2.1 依存関係のインストール
npm install
2.2 開発サーバーの起動
npm run dev
ブラウザで http://localhost:3000 にアクセスすると、Remotion Studioが起動します。
2.3 動作確認
-
Remotion Studioで「HelloWorld」コンポジションを選択
-
右側のプロパティパネルで設定を調整:
- text: 音声化するテキスト
- voice: 音声の種類(enUSWoman1, enUSWoman2, ptBRWoman, ptBRMan)
- titleColor: タイトルの色
- displaySpeed: アニメーション速度
-
テキストを変更すると:
- 1秒後にAzure TTSで音声が生成される
- 音声ファイルがS3にアップロードされる
- 音声の長さに基づいて動画の長さが自動調整される
3. 動画のレンダリング
3.1 動画の生成
npx remotion render HelloWorld output.mp4
3.2 カスタムプロパティでレンダリング
npx remotion render HelloWorld output.mp4 --props='{"text":"Hello Remotion","voice":"enUSWoman1","titleColor":"red","displaySpeed":15}'
4. トラブルシューティング
4.1 よくあるエラー
- 1006エラー: Azureサブスクリプションが未有効
- S3アクセスエラー: IAM権限またはバケットポリシーを確認
- CORS エラー: S3バケットのCORS設定を確認
4.2 リント・型チェック
npm run lint
4.3 依存関係のアップデート
npm run upgrade
5. カスタマイズ
5.1 音声の追加
src/types.ts:15で音声リストを追加し、src/tts.ts:27-32でvoiceMapを更新
5.2 アニメーションの調整
src/HelloWorld/Title.tsx:33-41でスプリングアニメーションのパラメータを調整
5.3 動画設定の変更
src/Root.tsx:14-17で解像度、FPS、デフォルト長さを変更
TTS処理フローの詳細解説
TTSの処理タイミングと呼び出しフロー
1. 処理開始のトリガー
TTSの処理は RemotionのcalculateMetadataフック で開始されます:
- 開発時: Remotion Studio でプレビューを開始する際
- レンダリング時: 動画の生成処理を開始する際
- プロパティ変更時: コンポーネントのプロパティ(text, voiceなど)が変更された際
2. 処理の実行順序(時系列)
2.1 calculateMetadataフック開始
ファイル: src/Root.tsx:24-42
calculateMetadata={async ({ props, abortSignal }) => {
2.2 ①デバウンス処理
ファイル: src/debounce.ts:3-25
await waitForNoInput(abortSignal, 1000);
- 開発時: 1秒間待機(ユーザー入力完了を待つ)
- レンダリング時: 即座にスキップ
- 目的: リアルタイム編集での不要な処理を防止
2.3 ②音声ファイル存在確認
ファイル: src/tts.ts:86-109
const exists = await audioAlreadyExists({
text: props.text,
voice: props.voice,
});
- 処理内容: S3に同じテキスト・音声の組み合わせが存在するかチェック
-
ファイル名: MD5ハッシュ (
${md5( {voice}{text}-- )}.mp3) - 効果: 重複する音声生成を防止
2.4 ③音声合成処理(条件実行)
ファイル: src/tts.ts:34-84
if (!exists) {
await synthesizeSpeech(props.text, props.voice);
}
詳細フロー:
-
Azure Speech Service設定
const speechConfig = SpeechConfig.fromSubscription( env.AZURE_TTS_KEY, env.AZURE_TTS_REGION, ); -
SSML生成
const ssml = ` <speak version="1.0" xml:lang="en-US"> <voice name="${voiceMap[voice]}"> <break time="100ms" /> ${text} </voice> </speak>`; -
音声合成実行
const result = await new Promise<SpeechSynthesisResult>((resolve, reject) => { synthesizer.speakSsmlAsync(ssml, resolve, reject); }); -
S3アップロード
await uploadTtsToS3(audioData, fileName);
2.5 ④S3 URL生成
ファイル: src/tts.ts:131-141
const fileName = createS3Url({
text: props.text,
voice: props.voice,
});
2.6 ⑤音声長さ取得と動画長さ計算
const duration = await getAudioDurationInSeconds(fileName);
return { props, durationInFrames: Math.ceil(duration * 30) };
2.7 ⑥音声ファイル使用
ファイル: src/HelloWorld.tsx:40
<Audio src={createS3Url({ text, voice })} />
3. 処理フロー図
[Remotion起動/プロパティ変更]
↓
[calculateMetadata実行]
↓
[waitForNoInput (1秒待機)]
↓
[audioAlreadyExists (S3確認)]
↓
[ファイル存在?]
↙ ↘
[Yes] [No]
↓ ↓
[スキップ] [synthesizeSpeech]
↓ ↓
↓ [Azure TTS実行]
↓ ↓
↓ [S3アップロード]
↓ ↓
└─────────┘
↓
[createS3Url (URL生成)]
↓
[getAudioDurationInSeconds]
↓
[durationInFrames計算]
↓
[HelloWorldコンポーネント]
↓
[Audio要素で音声再生]
4. 各段階での処理時間
開発時(初回)
- デバウンス: 1秒
- 存在確認: 100-300ms
- 音声合成: 2-5秒(テキスト長による)
- S3アップロード: 500ms-2秒
- 音声長さ取得: 200-500ms
開発時(キャッシュ済み)
- デバウンス: 1秒
- 存在確認: 100-300ms
- 音声合成: スキップ
- 音声長さ取得: 200-500ms
レンダリング時
- デバウンス: スキップ
- 存在確認: 100-300ms
- 音声合成: 必要時のみ実行
- 音声長さ取得: 200-500ms
5. エラーハンドリング
5.1 Azure TTS エラー
if (res.reason === ResultReason.SynthesizingAudioCompleted) {
resolve(res);
} else if (res.errorDetails) {
reject(new Error(res.errorDetails));
} else {
reject(new Error("Speech Synthesis Error"));
}
5.2 S3 エラー
try {
return await s3.send(new HeadObjectCommand({ Bucket, Key }));
} catch {
return false; // ファイル存在しない場合
}
6. 最適化のポイント
6.1 キャッシュ機能
- MD5ハッシュ: テキストと音声の組み合わせで一意のファイル名生成
- S3での永続化: 同じ内容の音声は再利用
- 高速確認: HeadObjectCommandで存在確認
6.2 デバウンス機能
- 開発時のみ: レンダリング時は無効化
- ユーザー体験: 入力完了まで待機して不要な処理を防止
6.3 非同期処理
- 並列処理: 複数の音声生成が可能
- AbortSignal: 処理の中断に対応
7. 音声品質設定
7.1 対応音声
export const voiceMap: { [key in Voice]: string } = {
ptBRWoman: "pt-BR-FranciscaNeural",
ptBRMan: "pt-BR-AntonioNeural",
enUSWoman1: "en-US-JennyNeural",
enUSWoman2: "en-US-AriaNeural",
} as const;
7.2 SSML設定
- 言語: en-US(固定)
- ポーズ: 100ms の開始ポーズ
- 形式: MP3出力
総括
このプロジェクトは、効率的で高品質なTTS機能を持つRemotionビデオ生成システムです。キャッシュ機能、デバウンス処理、エラーハンドリングなど、実用的な機能が組み込まれており、開発体験とパフォーマンスの両方を重視した設計になっています。
- 開発効率: リアルタイムプレビューとキャッシュ機能
- 品質: Azure Neural Voice とSSML対応
- 拡張性: 新しい音声の追加やアニメーションのカスタマイズが容易
- 安定性: 包括的なエラーハンドリングと処理中断対応
Discussion