dubbing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseElevenLabs Dubbing
ElevenLabs Dubbing
Dub audio or video into other languages while preserving the original speakers' voices. Create a project from a file or URL, review and edit the source transcript, add one or more target languages, refine translations per segment, and regenerate outputs.
Important: Use the Dubbing Projects API —in the SDKs, or theelevenlabs.dubbing.project.*REST endpoints. Do not use the legacy v1 dubbing surface (/v1/dubbing/project,client.dubbing.create(),client.dubbing.get(), or bareclient.dubbing.audio.get()routes) — that is the older dubbing API, now under Legacy in the API reference./v1/dubbing
Setup: See Installation Guide. REST base URL iswith your API key in thehttps://api.elevenlabs.ioheader; the SDKs readxi-api-keyautomatically.ELEVENLABS_API_KEY
将音频或视频配制成其他语言,同时保留原说话人的音色。可从文件或URL创建项目,审核并编辑源文稿,添加一种或多种目标语言,逐段优化译文,重新生成输出内容。
重要提示: 使用配音项目API——SDK中的,或REST端点elevenlabs.dubbing.project.*。请勿使用旧版v1配音接口(/v1/dubbing/project、client.dubbing.create()、client.dubbing.get(),或裸client.dubbing.audio.get()路由)——这是旧版配音API,现归类到API参考文档的“Legacy(旧版)”部分。/v1/dubbing
设置: 参见安装指南。REST基础URL为,需在https://api.elevenlabs.io请求头中携带你的API密钥;SDK会自动读取xi-api-key环境变量。ELEVENLABS_API_KEY
Concepts
核心概念
| Concept | Meaning |
|---|---|
| Project | One source of media (file or URL) plus its source transcript. Prepared (transcribed) once, then rests in |
| Source transcript | Editable segments (text, speaker, timing) transcribed from the source. The single source of truth every language is translated from. |
| Language (target) | One dubbed output language. Each has its own transcript (source segments + a translation per segment) and its own dubbed audio output. |
| Revisions | Independent monotonic counters. The project's |
Recommended order of operations: finalize the source transcript before adding any languages. Translations are produced from the source, so correcting the source first means every language starts from the right text — editing the source after a language completes marks it and requires a (charged) regeneration.
staleEnterprise: Transcript editing and regeneration are available to enterprise workspaces only. Creating projects, adding languages, and downloading dubs work on all plans.
| 概念 | 含义 |
|---|---|
| Project(项目) | 一个媒体源(文件或URL)加上其源文稿。只需转录一次,之后处于 |
| Source transcript(源文稿) | 从源媒体转录得到的可编辑片段(文本、说话人、时长)。是所有目标语言翻译的唯一基准。 |
| Language (target)(目标语言) | 一种配音输出语言。每种语言都有自己的文稿(源片段+每个片段的译文)和对应的配音音频输出。 |
| Revisions(版本号) | 独立的递增计数器。编辑源文稿时,项目的 |
推荐操作顺序: 在添加任何目标语言之前,先定稿源文稿。译文基于源文稿生成,因此先修正源文稿能确保所有目标语言从正确的文本开始——在目标语言生成完成后编辑源文稿会将其标记为(过期),并需要重新生成(会产生费用)。
stale企业版: 文稿编辑和重新生成功能仅对企业工作区开放。创建项目、添加目标语言、下载配音内容在所有套餐中均可用。
Workflow
工作流程
- Create the project from a file or URL →
queued - Poll the project until
ready - Review and finalize the source transcript (edit/add/delete segments)
- Add one language per target → →
queued→processingcompleted - Download each language's when
outputs.lossless_audiocompleted - Refine translations per segment if needed → the language goes
stale - Regenerate the language → again with fresh output
completed
- 创建项目(从文件或URL)→ (排队中)
queued - 轮询项目状态,直到变为(就绪)
ready - 审核并定稿源文稿(编辑/添加/删除片段)
- 添加目标语言(每次一种)→ (排队中)→
queued(处理中)→processing(完成)completed - 当状态变为(完成)时,下载每种语言的
completed(无损音频)outputs.lossless_audio - 如有需要,逐段优化译文→ 目标语言状态变为(过期)
stale - 重新生成目标语言→ 再次变为(完成)并生成新的输出内容
completed
Quick Start (Python)
快速入门(Python)
python
import os
import time
import requests
from elevenlabs.client import ElevenLabs
elevenlabs = ElevenLabs(api_key=os.getenv("ELEVENLABS_API_KEY"))python
import os
import time
import requests
from elevenlabs.client import ElevenLabs
elevenlabs = ElevenLabs(api_key=os.getenv("ELEVENLABS_API_KEY"))1. Create a project from a local file (or pass source_url=... instead of file)
1. Create a project from a local file (or pass source_url=... instead of file)
with open("promo.mp4", "rb") as f:
project = elevenlabs.dubbing.project.create(
file=f,
source_language="en",
reference="Q3 marketing video",
)
with open("promo.mp4", "rb") as f:
project = elevenlabs.dubbing.project.create(
file=f,
source_language="en",
reference="Q3 marketing video",
)
2. Wait for the source media to be transcribed
2. Wait for the source media to be transcribed
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)
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. Add a Spanish language target
3. Add a Spanish language target
language = elevenlabs.dubbing.project.language.create(
project.project_id,
target_language="es",
)
language = elevenlabs.dubbing.project.language.create(
project.project_id,
target_language="es",
)
4. Wait for the dub to finish generating
4. Wait for the dub to finish generating
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)
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. Download the dubbed audio (signed URL, valid ~1 hour — re-fetch the language for a fresh one)
5. Download the dubbed audio (signed URL, valid ~1 hour — re-fetch the language for a fresh one)
audio = requests.get(language.outputs.lossless_audio)
with open("promo_es.wav", "wb") as f:
f.write(audio.content)
undefinedaudio = requests.get(language.outputs.lossless_audio)
with open("promo_es.wav", "wb") as f:
f.write(audio.content)
undefinedQuick Start (JavaScript)
快速入门(JavaScript)
typescript
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import { writeFile } from "fs/promises";
const elevenlabs = new ElevenLabsClient();
// 1. Create a project (sourceUrl shown; file upload is also supported)
let project = await elevenlabs.dubbing.project.create({
sourceUrl: "https://example.com/promo.mp4",
sourceLanguage: "en",
reference: "Q3 marketing video",
});
// 2. Wait for the source media to be transcribed
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. Add a Spanish language target
let language = await elevenlabs.dubbing.project.language.create(project.projectId, {
targetLanguage: "es",
});
// 4. Wait for the dub to finish generating
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. Download the dubbed audio from the signed URL
const response = await fetch(language.outputs!.losslessAudio!);
await writeFile("promo_es.wav", Buffer.from(await response.arrayBuffer()));typescript
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import { writeFile } from "fs/promises";
const elevenlabs = new ElevenLabsClient();
// 1. Create a project (sourceUrl shown; file upload is also supported)
let project = await elevenlabs.dubbing.project.create({
sourceUrl: "https://example.com/promo.mp4",
sourceLanguage: "en",
reference: "Q3 marketing video",
});
// 2. Wait for the source media to be transcribed
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. Add a Spanish language target
let language = await elevenlabs.dubbing.project.language.create(project.projectId, {
targetLanguage: "es",
});
// 4. Wait for the dub to finish generating
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. Download the dubbed audio from the signed URL
const response = await fetch(language.outputs!.losslessAudio!);
await writeFile("promo_es.wav", Buffer.from(await response.arrayBuffer()));Quick Start (cURL)
快速入门(cURL)
bash
undefinedbash
undefined1. Create a project (use -F "source_url=https://..." instead of file to dub from a URL)
1. Create a project (use -F "source_url=https://..." instead of file to dub from a URL)
curl -X POST "https://api.elevenlabs.io/v1/dubbing/project"
-H "xi-api-key: $ELEVENLABS_API_KEY"
-F "file=@promo.mp4"
-F "source_language=en"
-H "xi-api-key: $ELEVENLABS_API_KEY"
-F "file=@promo.mp4"
-F "source_language=en"
curl -X POST "https://api.elevenlabs.io/v1/dubbing/project"
-H "xi-api-key: $ELEVENLABS_API_KEY"
-F "file=@promo.mp4"
-F "source_language=en"
-H "xi-api-key: $ELEVENLABS_API_KEY"
-F "file=@promo.mp4"
-F "source_language=en"
→ {"project_id": "proj_...", "status": "queued", ...}
→ {"project_id": "proj_...", "status": "queued", ...}
2. Poll until status is "ready"
2. Poll until status is "ready"
curl "https://api.elevenlabs.io/v1/dubbing/project/proj_..."
-H "xi-api-key: $ELEVENLABS_API_KEY"
-H "xi-api-key: $ELEVENLABS_API_KEY"
curl "https://api.elevenlabs.io/v1/dubbing/project/proj_..."
-H "xi-api-key: $ELEVENLABS_API_KEY"
-H "xi-api-key: $ELEVENLABS_API_KEY"
3. Add a target language
3. Add a target language
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"}'
-H "xi-api-key: $ELEVENLABS_API_KEY"
-H "Content-Type: application/json"
-d '{"target_language": "es"}'
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"}'
-H "xi-api-key: $ELEVENLABS_API_KEY"
-H "Content-Type: application/json"
-d '{"target_language": "es"}'
4. Poll the language until "completed", then download outputs.lossless_audio
4. Poll the language until "completed", then download outputs.lossless_audio
curl "https://api.elevenlabs.io/v1/dubbing/project/proj_.../language/lang_..."
-H "xi-api-key: $ELEVENLABS_API_KEY"
-H "xi-api-key: $ELEVENLABS_API_KEY"
undefinedcurl "https://api.elevenlabs.io/v1/dubbing/project/proj_.../language/lang_..."
-H "xi-api-key: $ELEVENLABS_API_KEY"
-H "xi-api-key: $ELEVENLABS_API_KEY"
undefinedCreate Options
创建项目参数
POST /v1/dubbing/projectmultipart/form-datafilesource_url| Field | Required | Notes |
|---|---|---|
| one of file/source_url | Source media to dub (audio or video), up to 3 GiB |
| one of file/source_url | Public URL to fetch the source media from |
| no | ISO 639 code (e.g. |
| no | Free-form label to identify the project on your end (max 500 chars) |
| no | |
| no | Optionally queue the first language target at creation; add more with |
| no | Terms to bias transcription/translation toward (product/brand names). Up to 100 terms of 200 chars each; repeat the field once per term in multipart |
POST /v1/dubbing/projectmultipart/form-datafilesource_url| 字段 | 是否必填 | 说明 |
|---|---|---|
| 二选一(file/source_url) | 要配音的源媒体(音频或视频),最大3 GiB |
| 二选一(file/source_url) | 用于获取源媒体的公开URL |
| 否 | ISO 639代码(例如 |
| 否 | 自定义标签,用于在你的系统中标识项目(最多500字符) |
| 否 | 默认值为 |
| 否 | 可选择在创建项目时直接排队第一个目标语言;后续可通过 |
| 否 | 用于偏向转录/翻译的术语(产品/品牌名称)。最多100个术语,每个最多200字符;在multipart请求中需重复该字段一次以添加一个术语 |
Editing the Source Transcript
编辑源文稿
Once the project is , read the transcript, then correct it before adding languages. Every edit bumps the project's . Each segment has a stable used to edit or delete it. (Enterprise workspaces only.)
readyrevisionidpython
undefined项目进入(就绪)状态后,读取文稿并在添加目标语言前进行修正。每次编辑都会增加项目的版本号。每个片段都有一个稳定的,用于编辑或删除该片段。(仅企业工作区可用。)
readyrevisionidpython
undefinedRead the source transcript
Read the source transcript
transcript = elevenlabs.dubbing.project.transcript.get(project_id)
transcript = elevenlabs.dubbing.project.transcript.get(project_id)
Correct a segment's text — send only the fields to change (text, speaker_id, start_s, end_s)
Correct a segment's text — send only the fields to change (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.",
)
elevenlabs.dubbing.project.transcript.update_segment(
project_id,
segment_id=transcript.segments[0].id,
text="Welcome to our latest product demo.",
)
Add a segment (reuse an existing speaker_id so it's dubbed with that speaker's voice)
Add a segment (reuse an existing speaker_id so it's dubbed with that speaker's voice)
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,
)
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,
)
Delete a segment
Delete a segment
elevenlabs.dubbing.project.transcript.delete_segment(project_id, segment_id=added.segment.id)
Via REST: `GET /v1/dubbing/project/{project_id}/transcript`, then `PATCH .../transcript/segment/{segment_id}` with only the changed fields:
```bash
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."}'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}`接口并仅传入需要修改的字段:
```bash
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."}'Refining Translations and Regenerating
优化译文与重新生成
A language's transcript pairs each source segment with its ( = not yet translated; segment ids match the source). Edit a single translation, then regenerate. (Enterprise workspaces only.)
translationnullpython
undefined目标语言的文稿将每个源片段与其(译文)配对(表示尚未翻译;片段id与源文稿一致)。编辑单个译文后重新生成。(仅企业工作区可用。)
translationnullpython
undefinedRead the language's translations
Read the language's translations
target = elevenlabs.dubbing.project.language.transcript.get(project_id, language_id)
target = elevenlabs.dubbing.project.language.transcript.get(project_id, language_id)
Refine a single translation (pass translation=None to clear it and mark for re-translation)
Refine a single translation (pass translation=None to clear it and mark for re-translation)
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.update_segment(
project_id,
language_id,
segment_id=target.segments[0].id,
translation="Bienvenido a nuestra última demostración de producto.",
)
Regenerate the dub from the current transcript (charged like a generation)
Regenerate the dub from the current transcript (charged like a generation)
elevenlabs.dubbing.project.language.transcript.regenerate(project_id, language_id)
Via REST: `PATCH /v1/dubbing/project/{project_id}/language/{language_id}/transcript/segment/{segment_id}` with `{"translation": "..."}`, then `POST .../language/{language_id}/transcript/regenerate` (returns `202 Accepted`).
A translation edit affects only that language. After the edit, a `completed` language becomes `stale` — it keeps serving its previous output until you regenerate. Poll until `completed`; `output_revision` then equals `revision` and `outputs.lossless_audio` reflects the current transcript.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`会反映当前文稿内容。Dubbing into Multiple Languages
多语言配音
Add one language target per language — each generates independently. Track them all with instead of polling one by one:
language.listpython
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)为每种目标语言添加一个语言目标——每个目标独立生成。可使用接口跟踪所有目标语言的状态,而非逐个轮询:
language.listpython
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)States
状态说明
Project:
| Status | Meaning |
|---|---|
| Created; source fetch + preparation enqueued |
| Preparation (transcription) running |
| Source transcript available; add/generate languages. Projects stay |
| Preparation failed (e.g. source couldn't be fetched or decoded) |
Language:
| Status | Meaning |
|---|---|
| Waiting on the project becoming |
| The dub is being generated |
| Finished; |
| Previously completed, but the transcript changed; keeps the last output until regenerated |
| Generation failed |
You can add a language before the project is — it stays and starts automatically once the project becomes . Adding a language accepts optional (defaults to the project's) and (e.g. , range 0–10, default 7 — controls how strongly dubbed speakers clone the source voices).
readyqueuedreadymodel_idvoice_settings{"cloning_strength": 7}项目状态:
| 状态 | 含义 |
|---|---|
| 已创建;源媒体获取与准备任务已排队 |
| 准备中(转录进行中) |
| 源文稿已就绪;可添加/生成目标语言。项目会保持 |
| 准备失败(例如无法获取或解码源媒体) |
语言状态:
| 状态 | 含义 |
|---|---|
| 等待项目变为 |
| 配音生成中 |
| 已完成; |
| 此前已完成,但文稿已变更;会保留上一次的输出内容,直到重新生成 |
| 生成失败 |
你可以在项目进入状态前添加目标语言——它会保持状态,待项目变为后自动开始处理。添加目标语言时可选择传入(默认使用项目的model_id)和(例如,范围0–10,默认7——控制配音说话人模仿源音色的程度)。
readyqueuedreadymodel_idvoice_settings{"cloning_strength": 7}Error Handling
错误处理
- 401: Invalid API key
- 409 Conflict on regenerate: The project isn't or the language isn't settled (e.g. already generating) — wait and retry
ready - Expired download URL: is signed and valid ~1 hour; re-fetch the language for a fresh URL
outputs.lossless_audio - Transcript editing / regeneration unavailable: These endpoints are enterprise-only — on other plans, create the project with a finalized source and add languages directly
- 401:API密钥无效
- 409 Conflict(冲突)(重新生成时):项目未处于状态或目标语言未稳定(例如正在生成中)——等待后重试
ready - 下载URL过期:是签名URL,有效期约1小时;重新获取语言信息可获得新的URL
outputs.lossless_audio - 文稿编辑/重新生成不可用:这些接口仅对企业版开放——其他套餐用户需使用定稿的源内容创建项目并直接添加目标语言
References
参考资料
- Installation Guide
- API Reference — every endpoint with full request/response schemas and SDK method names
- 安装指南
- API参考文档——包含所有端点的完整请求/响应 schema 以及SDK方法名称