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 秒)
⚠️ 開頭靜音:235 毫秒(可能開始較晚)
🐢 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」)以獲得自然發音
- 縮寫:寫出完整詞彙(如「二十四小時」而非「24小時」)
- 逐場景處理:不同場景可以使用不同角色(戲劇化的開場、冷靜的行動呼籲)
- 微調:使用
--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. 重複直到時間完美