Communitygithub.com

rodrvc/personal-brand

使用 ElevenLabs Dubbing API (dubbing_v2) 将音频和视频配音到其他语言,保留原始说话者的声音。适用于翻译视频、播客或录音,本地化媒体内容,审查或修正配音转录和翻译,或在编辑后重新生成配音。

personal-brand 是什么?

这是一个针对 ElevenLabs 配音功能的 AI Agent 技能,它允许开发者通过 API 将音频或视频内容配音成多种语言,同时保留原始说话者的声音特征。该技能基于新的 ElevenLabs Dubbing Projects API(`elevenlabs.dubbing.project.*` 或 `/v1/dubbing/project` 端点),并明确警告不要使用旧的 v1 配音 API。它支持完整的工作流程:从文件或 URL 创建项目、等待转录完成、审查和编辑源转录文本、添加一个或多个目标语言、细化每个片段的翻译,然后在编辑后重新生成配音输出。该技能非常实用,因为它将复杂的多步骤媒体本地化任务自动化,使 AI Agent 能够按正确顺序执行操作(例如,在添加语言之前最终确定源文本以避免昂贵的重新生成),并处理项目/语言状态轮询、下载已签名的音频 URL 以及细力度编辑翻译等细节。它通过提供 Python、JavaScript 和 cURL 示例,以及清晰的概念表(项目、源转录、语言、修订)和状态转换表,支持 ElevenLabs SDK 和 REST API。高级功能,如转录编辑和重新生成,仅适用于企业工作区,但所有计划都支持项目创建、语言添加和配音下载。

兼容平台~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.*,或 REST 端点 /v1/dubbing/project。不要使用旧的 v1 配音界面(client.dubbing.create()、client.dubbing.get()、client.dubbing.audio.get() 或裸的 /v1/dubbing 路由)—— 那是旧的配音 API,现已在 API 参考中标记为“Legacy”。

设置: 请参阅安装指南。REST 基础 URL 是 https://api.elevenlabs.io,在 xi-api-key 头中传递你的 API 密钥;SDK 会自动读取 ELEVENLABS_API_KEY 环境变量。

概念

概念含义
项目一个媒体源(文件或 URL)及其源转录。准备好(转录后)一次,然后处于 ready 状态等待添加语言。
源转录从源媒体转录的可编辑片段(文本、说话者、时间戳)。每个语言翻译都基于此单一事实来源。
语言(目标)一个配音输出语言。每个目标语言都有自己的转录(源片段 + 每片段的翻译)和自己的配音音频输出。
修订版本独立的单调递增计数器。项目的 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(不能同时包含):

字段必需性说明
filefile/source_url 二选一要配音的源媒体(音频或视频),最大 3 GiB
source_urlfile/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 与源匹配)。编辑单个翻译,然后重新生成。(仅限企业工作区。)

# 读取语言的翻译
目标 = 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
  • 转录编辑/重新生成不可用:这些端点仅限企业——在其他计划上,请使用已最终确定的源创建项目并直接添加语言

参考

相关技能