ElevenLabs ナレーション生成
ElevenLabs API を使用して、Remotion 動画向けのプロフェッショナルな AI ナレーションを生成します。
前提条件
.env.localにELEVENLABS_API_KEYが設定されていること
クイックスタート
# テキストからナレーションを生成
node .claude/skills/elevenlabs-remotion-skill/generate.js --text "ここにテキスト" --output public/audio/voiceover.mp3
# ナレータースタイルで生成(より自然)
node .claude/skills/elevenlabs-remotion-skill/generate.js --text "あなたのテキスト" --character narrator --output voiceover.mp3
# シーンファイルを使った生成(リクエストスティッチング対応)
node .claude/skills/elevenlabs-remotion-skill/generate.js --scenes remotion/scenes.json --output-dir public/audio/project/
# 単一シーンの再生成
node .claude/skills/elevenlabs-remotion-skill/generate.js --scenes scenes.json --scene scene2 --new-text "更新されたテキスト"
# 利用可能な音声とキャラクタープリセットを一覧表示
node .claude/skills/elevenlabs-remotion-skill/generate.js --list-voices
node .claude/skills/elevenlabs-remotion-skill/generate.js --list-characters
キャラクタープリセット
画面上のテキストをそのまま読むのではなく、キャラクタープリセットを使用してより自然なナレーションを実現します。
| キャラクター | 説明 | 最適な用途 |
|---|---|---|
literal | テキストをそのまま読み上げます | 画面上のテキスト、引用 |
narrator | プロの語り手、スムーズで魅力的 | 解説動画、ドキュメンタリー |
salesperson | 熱意があり、説得力があり、元気 | マーケティング、広告 |
expert | 権威があり、自信に満ち、知識豊富 | 法的コンテンツ、チュートリアル |
conversational | カジュアルで、親しみやすく、自然 | ソーシャルメディア、カジュアルコンテンツ |
dramatic | 激しく、感情的で、インパクトがある | フック、問題提起 |
calm | 心地よく、安心感があり、優しい | 信頼構築、結論 |
# 全体にナレータースタイルを適用
node .claude/skills/elevenlabs-remotion-skill/generate.js --scenes scenes.json --character narrator --output-dir public/audio/
# または scenes.json 内でシーンごとに設定
{
"scenes": [
{ "id": "scene1", "text": "問題提起", "character": "dramatic" },
{ "id": "scene2", "text": "解決策", "character": "calm" }
]
}
シーンベース生成とリクエストスティッチング
ElevenLabs のリクエストスティッチングを使用して、複数のシーンを一貫した韻律で生成します。
scenes.json の形式
{
"name": "product-demo",
"voice": "George",
"character": "narrator",
"scenes": [
{
"id": "scene1",
"text": "一般的なテキスト読み上げはロボット的に聞こえます。あなたのブランドにはもっとふさわしいものがあります。",
"duration": 4.5,
"character": "dramatic"
},
{
"id": "scene2",
"text": "音声クローンを使えば、自分の声で無限のコンテンツを作成できます。",
"duration": 5.5
},
{
"id": "scene3",
"text": "短いサンプルを録音し、クローンを作成します。数分でプロフェッショナルなナレーションを生成できます。",
"duration": 6,
"delay": 0.3
}
]
}
全シーンを生成
node .claude/skills/elevenlabs-remotion-skill/generate.js \
--scenes remotion/product-demo-scenes.json \
--output-dir public/audio/product-demo/
これにより以下が作成されます:
product-demo-scene1.mp3~sceneN.mp3product-demo-combined.mp3(全シーンを連結)product-demo-info.json(長さなどのメタデータ)
単一シーンの再生成
シーンの開始が早すぎる、タイミングが合わない、またはテキストを変更したい場合:
# scene2 を新しいテキストで再生成
node .claude/skills/elevenlabs-remotion-skill/generate.js \
--scenes remotion/scenes.json \
--scene scene2 \
--new-text "更新されたシーン2のテキスト" \
--output-dir public/audio/project/
# scene3 を別のキャラクターで再生成
node .claude/skills/elevenlabs-remotion-skill/generate.js \
--scenes remotion/scenes.json \
--scene scene3 \
--character salesperson \
--output-dir public/audio/project/
# 単純な再生成(同じテキスト、同じキャラクター)
node .claude/skills/elevenlabs-remotion-skill/generate.js \
--scenes remotion/scenes.json \
--scene scene1 \
--output-dir public/audio/project/
# MP4 動画にサムネイルを埋め込む
node .claude/skills/elevenlabs-remotion-skill/generate.js \
--embed-thumbnail public/videos/my-video.mp4 \
--thumbnail public/videos/my-thumbnail.png \
--output public/videos/my-video-with-thumb.mp4
このツールは自動的に:
- 前のシーンのリクエストスティッチングを使用し、一貫した韻律を維持
- 新しいメタデータで info.json ファイルを更新
--new-textが指定された場合は scenes.json を更新
サムネイル埋め込み
MP4 動画にサムネイル画像を埋め込むことで、Twitter、YouTube、動画プレイヤーなどで最初のフレームではなくカスタムサムネイルが表示されるようにします。
動画にサムネイルを埋め込む
# 基本的な使用方法 - 出力は video-thumb.mp4
node .claude/skills/elevenlabs-remotion-skill/generate.js \
--embed-thumbnail public/videos/promo.mp4 \
--thumbnail public/videos/thumbnail.png
# カスタム出力パス
node .claude/skills/elevenlabs-remotion-skill/generate.js \
--embed-thumbnail public/videos/promo.mp4 \
--thumbnail public/videos/thumbnail.png \
--output public/videos/promo-final.mp4
Remotion とのワークフロー
# 1. 動画をレンダリング
npx remotion render MyVideo public/videos/my-video.mp4
# 2. サムネイルをレンダリング(Still コンポジションを使用)
npx remotion still MyVideoThumbnail public/videos/my-thumbnail.png
# 3. サムネイルを埋め込む
node .claude/skills/elevenlabs-remotion-skill/generate.js \
--embed-thumbnail public/videos/my-video.mp4 \
--thumbnail public/videos/my-thumbnail.png \
--output public/videos/my-video-final.mp4
対応フォーマット
- 動画: MP4 (H.264/H.265)
- サムネイル: PNG, JPG, JPEG
埋め込みには ffmpeg の -disposition:v:1 attached_pic フラグを使用して、サムネイルを添付画像として設定します。ほとんどの動画プレイヤーやプラットフォームで認識されます。
タイミングバリデーション
このスキルは生成後、ffprobe を使用して自動的にタイミングを検証します。
チェック内容
| チェック項目 | しきい値 | 説明 |
|---|---|---|
| 長さの不一致 | >15% | 実際の長さが予想と異なる場合に警告 |
| 先頭の無音 | >200ms | 音声の開始が遅い(ナレーションの遅延) |
| 末尾の無音 | >500ms | 末尾に不要な無音がある |
| 話速 | 2~4.5 語/秒 | 最適は約3語/秒 |
既存の音声を検証
# プロジェクト内の全シーンを検証
node .claude/skills/elevenlabs-remotion-skill/generate.js --validate public/audio/product-demo/
出力例:
🔍 product-demo (6 シーン) を検証中
❌ scene1: 3.00秒 (予想: 4.5秒)
❌ 音声が予想より1.50秒短い
👍 8語 @ 3.1語/秒
⚠️ scene2: 6.35秒 (予想: 5.5秒)
⚠️ 先頭の無音: 235ms (開始が遅い可能性)
🐢 10語 @ 1.8語/秒
✅ scene4: 4.36秒 (予想: 4秒)
👍 9語 @ 2.3語/秒
📊 合計時間: 30.80秒 (予想: 30.00秒)
更新された info.json
検証後、info.json には実際の計測値が含まれます:
{
"scenes": [
{
"id": "scene1",
"duration": 4.5,
"actualDuration": 3.0,
"leadingSilence": 0.05,
"wordsPerSecond": 3.1
}
]
}
Remotion コンポジションでは actualDuration を使用して正確な同期を実現してください。
オプション
| オプション | 説明 | デフォルト値 |
|---|---|---|
--text, -t | 音声に変換するテキスト | 必須 (--file または --scenes がない場合) |
--file, -f | ファイルからテキストを読み込む | - |
--output, -o | 出力ファイルパス | output.mp3 |
--output-dir | シーンの出力ディレクトリ | public/audio |
--voice, -v | 音声名またはID | George |
--model, -m | モデルID | eleven_multilingual_v2 |
--character, -c | キャラクタープリセット | literal |
--scenes | シーン定義のJSONファイル | - |
--scene | 再生成する単一シーンID | - |
--new-text | シーン再生成用の新しいテキスト | - |
--validate | 既存の音声ディレクトリを検証 | - |
--skip-validation | 自動検証をスキップ | false |
--embed-thumbnail | サムネイルを埋め込む動画ファイル | - |
--thumbnail | サムネイル画像ファイル (PNG/JPG) | - |
--stability | 音声の安定性 (0-1) | キャラクターによる |
--similarity | 音声の類似性 (0-1) | キャラクターによる |
--style | スタイルの強調 (0-1) | キャラクターによる |
--no-combined | 連結ファイルを作成しない | false |
推奨音声
| 音声 | スタイル | 最適な用途 |
|---|---|---|
George | 温かみのある魅力的な英国風 | ナレーション、解説 |
Antoni | プロフェッショナルで温かい | 法的コンテンツ、チュートリアル |
Arnold | 権威があり、深みのある | コーポレート、シリアスな話題 |
Josh | フレンドリーで会話調 | マーケティング、カジュアルコンテンツ |
Remotion との統合
シーンのナレーションを生成した後、コンポジションで使用します:
import { Audio, Sequence, staticFile } from "remotion";
// 個別のシーン音声ファイルを使用して正確に同期
const SCENE_DURATIONS = {
scene1: 4.5, // info.json から
scene2: 5.5,
scene3: 8.0,
};
export const VideoWithVoiceover: React.FC = () => {
const { fps } = useVideoConfig();
const scene1Frames = Math.round(SCENE_DURATIONS.scene1 * fps);
const scene2Frames = Math.round(SCENE_DURATIONS.scene2 * fps);
return (
<>
<Sequence from={0} durationInFrames={scene1Frames}>
<Audio src={staticFile("audio/project/project-scene1.mp3")} />
<Scene1Visual />
</Sequence>
<Sequence from={scene1Frames} durationInFrames={scene2Frames}>
<Audio src={staticFile("audio/project/project-scene2.mp3")} />
<Scene2Visual />
</Sequence>
</>
);
};
最良の結果を得るためのヒント
- キャラクタープリセットを使用する: 画面上のテキストをそのまま読むのではなく、
narratorやexpertを使用して自然な流れにしましょう - 句読点が重要: 間隔にはピリオド、短い休止にはカンマを使用します
- 数字: 自然な読み上げのために数字は書き出します(「500」ではなく「五百」)
- 略語: 完全な単語で書きます(「24h」ではなく「24時間」)
- シーンごとに: 異なるシーンに異なるキャラクターを使用できます(劇的なイントロ、落ち着いたCTA)
- 微調整:
--sceneを使用して、全体をやり直さずに個別のシーンだけを再生成します - リクエストスティッチング: 全シーンで一貫した音声を維持します
ワークフロー例
# 1. スクリプトを含む scenes.json を作成
# 2. ナレータースタイルで全シーンを生成
node .claude/skills/elevenlabs-remotion-skill/generate.js \
--scenes remotion/my-video-scenes.json \
--character narrator \
--output-dir public/audio/my-video/
# 3. Remotion でプレビューし、scene2 の開始が早すぎることに気づく
# 4. scene2 だけを更新テキストで再生成
node .claude/skills/elevenlabs-remotion-skill/generate.js \
--scenes remotion/my-video-scenes.json \
--scene scene2 \
--new-text "映像のタイミングに合わせるため、少し長めのテキスト" \
--output-dir public/audio/my-video/
# 5. info.json の新しい長さで動画コンポジションを更新
# 6. タイミングが完璧になるまで繰り返す