dubbing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ElevenLabs 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 —
elevenlabs.dubbing.project.*
in the SDKs, or the
/v1/dubbing/project
REST endpoints. Do not use the legacy v1 dubbing surface (
client.dubbing.create()
,
client.dubbing.get()
,
client.dubbing.audio.get()
, or bare
/v1/dubbing
routes) — that is the older dubbing API, now under Legacy in the API reference.
Setup: See Installation Guide. REST base URL is
https://api.elevenlabs.io
with your API key in the
xi-api-key
header; the SDKs read
ELEVENLABS_API_KEY
automatically.
将音频或视频配制成其他语言,同时保留原说话人的音色。可从文件或URL创建项目,审核并编辑源文稿,添加一种或多种目标语言,逐段优化译文,重新生成输出内容。
重要提示: 使用配音项目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
环境变量。

Concepts

核心概念

ConceptMeaning
ProjectOne source of media (file or URL) plus its source transcript. Prepared (transcribed) once, then rests in
ready
while you add languages.
Source transcriptEditable 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.
RevisionsIndependent monotonic counters. The project's
revision
bumps on source-transcript edits; a language's
revision
bumps on translation edits or source edits that affect it. A language's
output_revision
is the revision its current audio was generated from — when it's behind
revision
, the output is out of date.
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
stale
and requires a (charged) regeneration.
Enterprise: Transcript editing and regeneration are available to enterprise workspaces only. Creating projects, adding languages, and downloading dubs work on all plans.
概念含义
Project(项目)一个媒体源(文件或URL)加上其源文稿。只需转录一次,之后处于
ready
状态,供你添加目标语言。
Source transcript(源文稿)从源媒体转录得到的可编辑片段(文本、说话人、时长)。是所有目标语言翻译的唯一基准。
Language (target)(目标语言)一种配音输出语言。每种语言都有自己的文稿(源片段+每个片段的译文)和对应的配音音频输出。
Revisions(版本号)独立的递增计数器。编辑源文稿时,项目的
revision
会增加;编辑译文或源文稿变更影响到目标语言时,该语言的
revision
会增加。语言的
output_revision
是当前音频生成时对应的版本号——当它落后于
revision
时,输出内容已过期。
推荐操作顺序: 在添加任何目标语言之前,先定稿源文稿。译文基于源文稿生成,因此先修正源文稿能确保所有目标语言从正确的文本开始——在目标语言生成完成后编辑源文稿会将其标记为
stale
(过期),并需要重新生成(会产生费用)。
企业版: 文稿编辑和重新生成功能仅对企业工作区开放。创建项目、添加目标语言、下载配音内容在所有套餐中均可用。

Workflow

工作流程

  1. Create the project from a file or URL →
    queued
  2. Poll the project until
    ready
  3. Review and finalize the source transcript (edit/add/delete segments)
  4. Add one language per target →
    queued
    processing
    completed
  5. Download each language's
    outputs.lossless_audio
    when
    completed
  6. Refine translations per segment if needed → the language goes
    stale
  7. Regenerate the language →
    completed
    again with fresh output
  1. 创建项目(从文件或URL)→
    queued
    (排队中)
  2. 轮询项目状态,直到变为
    ready
    (就绪)
  3. 审核并定稿源文稿(编辑/添加/删除片段)
  4. 添加目标语言(每次一种)→
    queued
    (排队中)→
    processing
    (处理中)→
    completed
    (完成)
  5. 当状态变为
    completed
    (完成)时,下载每种语言的
    outputs.lossless_audio
    (无损音频)
  6. 如有需要,逐段优化译文→ 目标语言状态变为
    stale
    (过期)
  7. 重新生成目标语言→ 再次变为
    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)
undefined
audio = requests.get(language.outputs.lossless_audio) with open("promo_es.wav", "wb") as f: f.write(audio.content)
undefined

Quick 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
undefined
bash
undefined

1. 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"
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"

→ {"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"
curl "https://api.elevenlabs.io/v1/dubbing/project/proj_..."
-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"}'
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. 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"
undefined
curl "https://api.elevenlabs.io/v1/dubbing/project/proj_.../language/lang_..."
-H "xi-api-key: $ELEVENLABS_API_KEY"
undefined

Create Options

创建项目参数

POST /v1/dubbing/project
takes
multipart/form-data
with either
file
or
source_url
(not both):
FieldRequiredNotes
file
one of file/source_urlSource media to dub (audio or video), up to 3 GiB
source_url
one of file/source_urlPublic URL to fetch the source media from
source_language
noISO 639 code (e.g.
en
). Omit to auto-detect — the detected language is reported on the source transcript's
language
field
reference
noFree-form label to identify the project on your end (max 500 chars)
model_id
no
dubbing_v2
(default)
target_language
noOptionally queue the first language target at creation; add more with
language.create
keyterms
noTerms 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/project
接收
multipart/form-data
格式请求,需二选一传入
file
source_url
(不可同时传入):
字段是否必填说明
file
二选一(file/source_url)要配音的源媒体(音频或视频),最大3 GiB
source_url
二选一(file/source_url)用于获取源媒体的公开URL
source_language
ISO 639代码(例如
en
)。留空将自动检测——检测到的语言会显示在源文稿的
language
字段中
reference
自定义标签,用于在你的系统中标识项目(最多500字符)
model_id
默认值为
dubbing_v2
target_language
可选择在创建项目时直接排队第一个目标语言;后续可通过
language.create
添加更多
keyterms
用于偏向转录/翻译的术语(产品/品牌名称)。最多100个术语,每个最多200字符;在multipart请求中需重复该字段一次以添加一个术语

Editing the Source Transcript

编辑源文稿

Once the project is
ready
, read the transcript, then correct it before adding languages. Every edit bumps the project's
revision
. Each segment has a stable
id
used to edit or delete it. (Enterprise workspaces only.)
python
undefined
项目进入
ready
(就绪)状态后,读取文稿并在添加目标语言前进行修正。每次编辑都会增加项目的
revision
版本号。每个片段都有一个稳定的
id
,用于编辑或删除该片段。(仅企业工作区可用。)
python
undefined

Read 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
translation
(
null
= not yet translated; segment ids match the source). Edit a single translation, then regenerate. (Enterprise workspaces only.)
python
undefined
目标语言的文稿将每个源片段与其
translation
(译文)配对(
null
表示尚未翻译;片段id与源文稿一致)。编辑单个译文后重新生成。(仅企业工作区可用。)
python
undefined

Read 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
language.list
instead of polling one by one:
python
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.list
接口跟踪所有目标语言的状态,而非逐个轮询:
python
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:
StatusMeaning
queued
Created; source fetch + preparation enqueued
preparing
Preparation (transcription) running
ready
Source transcript available; add/generate languages. Projects stay
ready
— per-language progress lives on the languages
failed
Preparation failed (e.g. source couldn't be fetched or decoded)
Language:
StatusMeaning
queued
Waiting on the project becoming
ready
, or on a generation worker
processing
The dub is being generated
completed
Finished;
outputs
populated with a signed download URL (valid ~1 hour — re-fetch for a fresh one)
stale
Previously completed, but the transcript changed; keeps the last output until regenerated
failed
Generation failed
You can add a language before the project is
ready
— it stays
queued
and starts automatically once the project becomes
ready
. Adding a language accepts optional
model_id
(defaults to the project's) and
voice_settings
(e.g.
{"cloning_strength": 7}
, range 0–10, default 7 — controls how strongly dubbed speakers clone the source voices).
项目状态:
状态含义
queued
已创建;源媒体获取与准备任务已排队
preparing
准备中(转录进行中)
ready
源文稿已就绪;可添加/生成目标语言。项目会保持
ready
状态——各语言的进度由其自身状态跟踪
failed
准备失败(例如无法获取或解码源媒体)
语言状态:
状态含义
queued
等待项目变为
ready
状态,或等待生成工作节点
processing
配音生成中
completed
已完成;
outputs
字段包含签名下载URL(有效期约1小时——重新获取语言信息可获得新的URL)
stale
此前已完成,但文稿已变更;会保留上一次的输出内容,直到重新生成
failed
生成失败
你可以在项目进入
ready
状态前添加目标语言——它会保持
queued
状态,待项目变为
ready
后自动开始处理。添加目标语言时可选择传入
model_id
(默认使用项目的model_id)和
voice_settings
(例如
{"cloning_strength": 7}
,范围0–10,默认7——控制配音说话人模仿源音色的程度)。

Error Handling

错误处理

  • 401: Invalid API key
  • 409 Conflict on regenerate: The project isn't
    ready
    or the language isn't settled (e.g. already generating) — wait and retry
  • Expired download URL:
    outputs.lossless_audio
    is signed and valid ~1 hour; re-fetch the language for a fresh URL
  • 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过期
    outputs.lossless_audio
    是签名URL,有效期约1小时;重新获取语言信息可获得新的URL
  • 文稿编辑/重新生成不可用:这些接口仅对企业版开放——其他套餐用户需使用定稿的源内容创建项目并直接添加目标语言

References

参考资料

  • Installation Guide
  • API Reference — every endpoint with full request/response schemas and SDK method names
  • 安装指南
  • API参考文档——包含所有端点的完整请求/响应 schema 以及SDK方法名称