Communitygithub.com

rodrvc/personal-brand

使用 ElevenLabs Dubbing API (dubbing_v2) 將音訊和影片配音成其他語言,保留原始說話者的聲音。適用於將影片、Podcast 或錄音翻譯成其他語言、本地化媒體內容、審查或修正配音轉錄稿與翻譯,以及在編輯後重新產生配音。

personal-brand 是什麼?

這項技能讓開發者和 AI 代理能夠利用 ElevenLabs Dubbing API(dubbing_v2 端點)將音訊或影片內容配音成多種語言,同時保留原始說話者的聲音特色。它支援從檔案或 URL 創建專案、檢視和編輯原始轉錄稿、新增一個或多個目標語言、精煉每個片段的翻譯,並在編輯後重新產生配音輸出。此技能專為 ElevenLabs 的 Dubbing Projects API 設計(使用 `elevenlabs.dubbing.project.*` 或 `/v1/dubbing/project` 端點),而非舊版的 dubbing API。它適用於需要將媒體內容(如行銷影片、Podcast、教育課程或錄音)本地化為其他語言的場景,特別是在需要控制翻譯品質或進行後續編輯時。此技能支援 Python、JavaScript 和 cURL,適用於各種開發環境和自動化工作流程。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/rodrvc/personal-brand/tree/HEAD/.claude/skills/dubbing

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

ElevenLabs Dubbing

將音訊或影片配音成其他語言,同時保留原始說話者的聲音。從檔案或 URL 創建專案、檢視和編輯原始轉錄稿、新增一個或多個目標語言、精煉每個片段的翻譯,並重新產生輸出。

重要事項: 使用 Dubbing Projects API — SDK 中的 elevenlabs.dubbing.project.*,或 /v1/dubbing/project REST 端點。請勿使用舊版 v1 dubbing 介面 (client.dubbing.create()、client.dubbing.get()、client.dubbing.audio.get() 或裸 /v1/dubbing 路由) — 那是較舊的 dubbing API,現在在 API 參考文件中歸類為 Legacy。

設定: 請參閱安裝指南。REST 基礎 URL 為 https://api.elevenlabs.io,需在 xi-api-key 標頭中提供您的 API 金鑰;SDK 會自動讀取 ELEVENLABS_API_KEY 環境變數。

概念

概念意義
專案 (Project)一個媒體來源(檔案或 URL)及其原始轉錄稿。準備(轉錄)一次後,即處於 ready 狀態,等待您新增語言。
原始轉錄稿 (Source transcript)從來源轉錄的可編輯片段(文字、說話者、時間戳)。這是每個語言翻譯所依據的單一事實來源。
語言 (目標) (Language / target)一個配音輸出語言。每個目標語言都有自己專屬的轉錄稿(來源片段 + 每個片段的翻譯)和配音音訊輸出。
修訂版次 (Revisions)獨立的單調遞增計數器。專案的 revision 在原始轉錄稿編輯時遞增;語言的 revision 在翻譯編輯或影響該語言的來源編輯時遞增。語言的 output_revision 是其目前音訊產生時所依據的修訂版次 — 當它落後於 revision 時,輸出已過時。

建議的操作順序: 在新增任何語言之前,先完成原始轉錄稿的最終版本。翻譯是根據來源產生的,因此先修正來源,每個語言都能從正確的文字開始 — 在語言完成後編輯來源會將其標記為 stale,並需要(付費的)重新產生。

企業方案: 轉錄稿編輯和重新產生僅適用於企業工作區。創建專案、新增語言和下載配音則適用於所有方案。

工作流程

  1. 創建 專案(從檔案或 URL)→ queued
  2. 輪詢 專案直到 ready
  3. 檢視並完成原始轉錄稿(編輯/新增/刪除片段)
  4. 新增 每個目標語言一個 → queued → processing → completed
  5. 下載 每個語言的 outputs.lossless_audio(當狀態為 completed 時)
  6. 精煉 每個片段的翻譯(如有需要)→ 該語言變為 stale
  7. 重新產生 該語言 → 再次變為 completed 並提供全新輸出

快速入門 (Python)

import os
import time
import requests
from elevenlabs.client import ElevenLabs

elevenlabs = ElevenLabs(api_key=os.getenv("ELEVENLABS_API_KEY"))

# 1. 從本地檔案創建專案(或傳入 source_url=... 來替代檔案)
with open("promo.mp4", "rb") as f:
    project = elevenlabs.dubbing.project.create(
        file=f,
        source_language="en",
        reference="Q3 marketing video",
    )

# 2. 等待來源媒體完成轉錄
while True:
    project = elevenlabs.dubbing.project.get(project.project_id)
    if project.status == "ready":
        break
    if project.status == "failed":
        raise RuntimeError("Project preparation failed")
    time.sleep(5)

# 3. 新增一個西班牙語目標
language = elevenlabs.dubbing.project.language.create(
    project.project_id,
    target_language="es",
)

# 4. 等待配音產生完成
while True:
    language = elevenlabs.dubbing.project.language.get(
        project.project_id, language.language_id
    )
    if language.status == "completed":
        break
    if language.status == "failed":
        raise RuntimeError("Dub generation failed")
    time.sleep(5)

# 5. 下載配音音訊(簽署 URL,有效期約 1 小時 — 重新獲取語言物件以取得新的 URL)
audio = requests.get(language.outputs.lossless_audio)
with open("promo_es.wav", "wb") as f:
    f.write(audio.content)

快速入門 (JavaScript)

import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import { writeFile } from "fs/promises";

const elevenlabs = new ElevenLabsClient();

// 1. 創建專案(示範使用 sourceUrl;也支援檔案上傳)
let project = await elevenlabs.dubbing.project.create({
  sourceUrl: "https://example.com/promo.mp4",
  sourceLanguage: "en",
  reference: "Q3 marketing video",
});

// 2. 等待來源媒體完成轉錄
while (true) {
  project = await elevenlabs.dubbing.project.get(project.projectId);
  if (project.status === "ready") break;
  if (project.status === "failed") throw new Error("Project preparation failed");
  await new Promise((resolve) => setTimeout(resolve, 5000));
}

// 3. 新增一個西班牙語目標
let language = await elevenlabs.dubbing.project.language.create(project.projectId, {
  targetLanguage: "es",
});

// 4. 等待配音產生完成
while (true) {
  language = await elevenlabs.dubbing.project.language.get(project.projectId, language.languageId);
  if (language.status === "completed") break;
  if (language.status === "failed") throw new Error("Dub generation failed");
  await new Promise((resolve) => setTimeout(resolve, 5000));
}

// 5. 從簽署 URL 下載配音音訊
const response = await fetch(language.outputs!.losslessAudio!);
await writeFile("promo_es.wav", Buffer.from(await response.arrayBuffer()));

快速入門 (cURL)

# 1. 創建專案(使用 -F "source_url=https://..." 替代檔案來從 URL 進行配音)
curl -X POST "https://api.elevenlabs.io/v1/dubbing/project" \
  -H "xi-api-key: $ELEVENLABS_API_KEY" \
  -F "[email protected]" \
  -F "source_language=en"
# → {"project_id": "proj_...", "status": "queued", ...}

# 2. 輪詢直到狀態為 "ready"
curl "https://api.elevenlabs.io/v1/dubbing/project/proj_..." \
  -H "xi-api-key: $ELEVENLABS_API_KEY"

# 3. 新增一個目標語言
curl -X POST "https://api.elevenlabs.io/v1/dubbing/project/proj_.../language" \
  -H "xi-api-key: $ELEVENLABS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"target_language": "es"}'

# 4. 輪詢該語言直到 "completed",然後下載 outputs.lossless_audio
curl "https://api.elevenlabs.io/v1/dubbing/project/proj_.../language/lang_..." \
  -H "xi-api-key: $ELEVENLABS_API_KEY"

創建選項

POST /v1/dubbing/project 接受 multipart/form-data,需提供 file 或 source_url(二選一,不可同時):

欄位必填備註
file檔案/source_url 二選一要配音的來源媒體(音訊或影片),最大 3 GiB
source_url檔案/source_url 二選一用於獲取來源媒體的公開 URL
source_language否ISO 639 代碼(例如 en)。省略以自動偵測 — 偵測到的語言會記錄在原始轉錄稿的 language 欄位中
reference否用於識別專案的自由格式標籤(最多 500 個字元)
model_id否dubbing_v2(預設)
target_language否可選擇在創建時排程第一個語言目標;稍後可透過 language.create 新增更多語言
keyterms否用於偏重轉錄/翻譯方向的詞彙(產品/品牌名稱)。最多 100 個詞彙,每個 200 個字元;在 multipart 中為每個詞彙重複一次該欄位

編輯原始轉錄稿

當專案處於 ready 狀態後,您可以讀取轉錄稿,然後在新增語言之前進行修正。每次編輯都會增加專案的 revision。每個片段都有一個穩定的 id,用於編輯或刪除它。(僅限企業工作區。)

# 讀取原始轉錄稿
transcript = elevenlabs.dubbing.project.transcript.get(project_id)

# 修正片段的文字 — 僅傳送要更改的欄位(text, speaker_id, start_s, end_s)
elevenlabs.dubbing.project.transcript.update_segment(
    project_id,
    segment_id=transcript.segments[0].id,
    text="Welcome to our latest product demo.",
)

# 新增一個片段(重複使用現有的 speaker_id,以便使用該說話者的聲音進行配音)
added = elevenlabs.dubbing.project.transcript.create_segment(
    project_id,
    text="Thanks for watching.",
    speaker_id=transcript.segments[0].speaker_id,
    start_s=40.0,
    end_s=42.0,
)

# 刪除一個片段
elevenlabs.dubbing.project.transcript.delete_segment(project_id, segment_id=added.segment.id)

透過 REST:GET /v1/dubbing/project/{project_id}/transcript,然後 PATCH .../transcript/segment/{segment_id} 並僅傳送要更改的欄位:

curl -X PATCH "https://api.elevenlabs.io/v1/dubbing/project/{project_id}/transcript/segment/{segment_id}" \
  -H "xi-api-key: $ELEVENLABS_API_KEY" -H "Content-Type: application/json" \
  -d '{"text": "Welcome to our latest product demo."}')

精煉翻譯與重新產生

語言的轉錄稿將每個來源片段與其 translation 配對(null = 尚未翻譯;片段 ID 與來源相符)。編輯單一翻譯,然後重新產生。(僅限企業工作區。)

# 讀取語言的翻譯
target = elevenlabs.dubbing.project.language.transcript.get(project_id, language_id)

# 精煉單一翻譯(傳入 translation=None 以清除翻譯並標記為需要重新翻譯)
elevenlabs.dubbing.project.language.transcript.update_segment(
    project_id,
    language_id,
    segment_id=target.segments[0].id,
    translation="Bienvenido a nuestra última demostración de producto.",
)

# 從當前轉錄稿重新產生配音(收費方式與初次產生相同)
elevenlabs.dubbing.project.language.transcript.regenerate(project_id, language_id)

透過 REST:PATCH /v1/dubbing/project/{project_id}/language/{language_id}/transcript/segment/{segment_id} 搭配 {"translation": "..."},然後 POST .../language/{language_id}/transcript/regenerate(回傳 202 Accepted)。

翻譯編輯只會影響該語言。編輯後,一個 completed 的語言會變為 stale — 它會繼續提供先前的輸出,直到您重新產生。輪詢直到 completed;屆時 output_revision 會等於 revision,且 outputs.lossless_audio 會反映當前的轉錄稿。

配音成多種語言

每種語言新增一個目標 — 各自獨立產生。使用 language.list 追蹤所有語言,而不是逐一輪詢:

for lang in ["es", "fr", "de", "ja"]:
    elevenlabs.dubbing.project.language.create(project_id, target_language=lang)

while True:
    result = elevenlabs.dubbing.project.language.list(project_id)
    if not any(l.status in ("queued", "processing") for l in result.languages):
        break
    time.sleep(5)

狀態

專案:

狀態意義
queued已創建;已排入來源擷取與準備佇列
preparing正在執行準備(轉錄)
ready原始轉錄稿已就緒;可以新增/產生語言。專案保持 ready 狀態 — 每個語言的進度由語言本身管理
failed準備失敗(例如無法擷取或解碼來源)

語言:

狀態意義
queued正在等待專案變為 ready,或等待產生工作程序
processing正在產生配音
completed完成;outputs 中包含了簽署的下載 URL(有效期約 1 小時 — 重新擷取以取得新的 URL)
stale先前已完成,但轉錄稿已變更;保留最後一次輸出直到重新產生
failed產生失敗

您可以在專案處於 ready 狀態之前新增語言 — 它會保持 queued 狀態,並且在專案變為 ready 後自動開始。新增語言可以接受選用的 model_id(預設為專案的模型)和 voice_settings(例如 {"cloning_strength": 7},範圍 0–10,預設為 7 — 控制配音說話者對原始聲音的克隆強度)。

錯誤處理

  • 401:API 金鑰無效
  • 409 Conflict(重新產生時):專案未處於 ready 狀態,或語言尚未穩定(例如正在產生中)— 請稍後再試
  • 下載 URL 過期:outputs.lossless_audio 已簽署,有效期約 1 小時;重新擷取語言物件以取得新的 URL
  • 轉錄稿編輯 / 重新產生不可用:這些端點僅限企業方案 — 在其他方案上,請在創建專案時先確定來源已最終化,然後直接新增語言

參考資料

相關技能