video-translate

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Video Translation (HeyGen)

视频翻译(HeyGen)

Translate and dub existing videos into multiple languages, preserving lip-sync and natural speech patterns. Provide a video URL or HeyGen video ID — no need to create the video on HeyGen first.
将现有视频翻译并配音为多种语言,同时保留唇形同步效果和自然的语音模式。只需提供视频URL或HeyGen视频ID——无需先在HeyGen平台创建视频。

Authentication

身份验证

All requests require the
X-Api-Key
header. Set the
HEYGEN_API_KEY
environment variable.
bash
curl -X POST "https://api.heygen.com/v2/video_translate" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"video_url": "https://example.com/video.mp4", "output_language": "es-ES"}'
所有请求都需要
X-Api-Key
请求头。请设置
HEYGEN_API_KEY
环境变量。
bash
curl -X POST "https://api.heygen.com/v2/video_translate" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"video_url": "https://example.com/video.mp4", "output_language": "es-ES"}'

Default Workflow

默认工作流程

  1. Provide a video URL or HeyGen video ID
  2. Call
    POST /v2/video_translate
    with the target language
  3. Poll
    GET /v2/video_translate/{translate_id}
    until status is
    completed
  4. Download the translated video from the returned URL
  1. 提供视频URL或HeyGen视频ID
  2. 调用
    POST /v2/video_translate
    接口并传入目标语言参数
  3. 轮询
    GET /v2/video_translate/{translate_id}
    接口,直到状态变为
    completed
  4. 从返回的URL下载翻译后的视频

Creating a Translation Job

创建翻译任务

Request Fields

请求字段

FieldTypeReqDescription
video_url
stringY*URL of video to translate (*or
video_id
)
video_id
stringY*HeyGen video ID (*or
video_url
)
output_language
stringYTarget language code (e.g.,
"es-ES"
)
title
stringName for the translated video
translate_audio_only
booleanAudio only, no lip-sync (faster)
speaker_num
numberNumber of speakers in video
callback_id
stringCustom ID for webhook tracking
callback_url
stringURL for completion notification
Either
video_url
or
video_id
must be provided.
字段类型必填描述
video_url
字符串是*待翻译视频的URL(*或传入
video_id
video_id
字符串是*HeyGen平台的视频ID(*或传入
video_url
output_language
字符串目标语言代码(例如:
"es-ES"
title
字符串翻译后视频的名称
translate_audio_only
布尔值仅翻译音频,不做唇形同步(速度更快)
speaker_num
数字视频中的说话人数量
callback_id
字符串用于Webhook追踪的自定义ID
callback_url
字符串任务完成通知的回调URL
必须提供
video_url
video_id
其中一个参数。

curl

curl示例

bash
curl -X POST "https://api.heygen.com/v2/video_translate" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "https://example.com/original-video.mp4",
    "output_language": "es-ES",
    "title": "Spanish Version"
  }'
bash
curl -X POST "https://api.heygen.com/v2/video_translate" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "https://example.com/original-video.mp4",
    "output_language": "es-ES",
    "title": "西班牙语版本"
  }'

TypeScript

TypeScript示例

typescript
interface VideoTranslateRequest {
  video_url?: string;
  video_id?: string;
  output_language: string;
  title?: string;
  translate_audio_only?: boolean;
  speaker_num?: number;
  callback_id?: string;
  callback_url?: string;
}

interface VideoTranslateResponse {
  error: null | string;
  data: {
    video_translate_id: string;
  };
}

async function translateVideo(config: VideoTranslateRequest): Promise<string> {
  const response = await fetch("https://api.heygen.com/v2/video_translate", {
    method: "POST",
    headers: {
      "X-Api-Key": process.env.HEYGEN_API_KEY!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(config),
  });

  const json: VideoTranslateResponse = await response.json();

  if (json.error) {
    throw new Error(json.error);
  }

  return json.data.video_translate_id;
}
typescript
interface VideoTranslateRequest {
  video_url?: string;
  video_id?: string;
  output_language: string;
  title?: string;
  translate_audio_only?: boolean;
  speaker_num?: number;
  callback_id?: string;
  callback_url?: string;
}

interface VideoTranslateResponse {
  error: null | string;
  data: {
    video_translate_id: string;
  };
}

async function translateVideo(config: VideoTranslateRequest): Promise<string> {
  const response = await fetch("https://api.heygen.com/v2/video_translate", {
    method: "POST",
    headers: {
      "X-Api-Key": process.env.HEYGEN_API_KEY!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(config),
  });

  const json: VideoTranslateResponse = await response.json();

  if (json.error) {
    throw new Error(json.error);
  }

  return json.data.video_translate_id;
}

Python

Python示例

python
import requests
import os

def translate_video(config: dict) -> str:
    response = requests.post(
        "https://api.heygen.com/v2/video_translate",
        headers={
            "X-Api-Key": os.environ["HEYGEN_API_KEY"],
            "Content-Type": "application/json"
        },
        json=config
    )

    data = response.json()
    if data.get("error"):
        raise Exception(data["error"])

    return data["data"]["video_translate_id"]
python
import requests
import os

def translate_video(config: dict) -> str:
    response = requests.post(
        "https://api.heygen.com/v2/video_translate",
        headers={
            "X-Api-Key": os.environ["HEYGEN_API_KEY"],
            "Content-Type": "application/json"
        },
        json=config
    )

    data = response.json()
    if data.get("error"):
        raise Exception(data["error"])

    return data["data"]["video_translate_id"]

Supported Languages

支持的语言

LanguageCodeNotes
English (US)en-USDefault source
Spanish (Spain)es-ESEuropean Spanish
Spanish (Mexico)es-MXLatin American
Frenchfr-FRStandard French
Germande-DEStandard German
Italianit-ITStandard Italian
Portuguese (Brazil)pt-BRBrazilian Portuguese
Japaneseja-JPStandard Japanese
Koreanko-KRStandard Korean
Chinese (Mandarin)zh-CNSimplified Chinese
Hindihi-INStandard Hindi
Arabicar-SAModern Standard Arabic
语言代码说明
英语(美国)en-US默认源语言
西班牙语(西班牙)es-ES欧洲西班牙语
西班牙语(墨西哥)es-MX拉丁美洲西班牙语
法语fr-FR标准法语
德语de-DE标准德语
意大利语it-IT标准意大利语
葡萄牙语(巴西)pt-BR巴西葡萄牙语
日语ja-JP标准日语
韩语ko-KR标准韩语
中文(普通话)zh-CN简体中文
印地语hi-IN标准印地语
阿拉伯语ar-SA现代标准阿拉伯语

Translation Options

翻译选项

Basic Translation (with lip-sync)

基础翻译(带唇形同步)

typescript
const config = {
  video_url: "https://example.com/original.mp4",
  output_language: "es-ES",
  title: "Spanish Translation",
};
typescript
const config = {
  video_url: "https://example.com/original.mp4",
  output_language: "es-ES",
  title: "西班牙语翻译版",
};

Audio-Only Translation (faster, no lip-sync)

仅音频翻译(速度更快,无唇形同步)

typescript
const config = {
  video_url: "https://example.com/original.mp4",
  output_language: "es-ES",
  translate_audio_only: true,
};
typescript
const config = {
  video_url: "https://example.com/original.mp4",
  output_language: "es-ES",
  translate_audio_only: true,
};

Multi-Speaker Videos

多说话人视频

typescript
const config = {
  video_url: "https://example.com/interview.mp4",
  output_language: "fr-FR",
  speaker_num: 2,
};
typescript
const config = {
  video_url: "https://example.com/interview.mp4",
  output_language: "fr-FR",
  speaker_num: 2,
};

Advanced Options (v4 API)

高级选项(v4 API)

For more control over translation:
typescript
interface VideoTranslateV4Request {
  input_video_id?: string;
  google_url?: string;
  output_languages: string[];        // Multiple languages in one call
  name: string;
  srt_key?: string;                  // Custom SRT subtitles
  instruction?: string;
  vocabulary?: string[];             // Terms to preserve as-is
  brand_voice_id?: string;
  speaker_num?: number;
  keep_the_same_format?: boolean;
  input_language?: string;
  enable_video_stretching?: boolean;
  disable_music_track?: boolean;
  enable_speech_enhancement?: boolean;
  srt_role?: "input" | "output";
  translate_audio_only?: boolean;
}
如需更精细的翻译控制:
typescript
interface VideoTranslateV4Request {
  input_video_id?: string;
  google_url?: string;
  output_languages: string[];        // 一次调用生成多语言版本
  name: string;
  srt_key?: string;                  // 自定义SRT字幕
  instruction?: string;
  vocabulary?: string[];             // 需保留原样的术语
  brand_voice_id?: string;
  speaker_num?: number;
  keep_the_same_format?: boolean;
  input_language?: string;
  enable_video_stretching?: boolean;
  disable_music_track?: boolean;
  enable_speech_enhancement?: boolean;
  srt_role?: "input" | "output";
  translate_audio_only?: boolean;
}

Multiple Output Languages

多输出语言

typescript
const config = {
  input_video_id: "original_video_id",
  output_languages: ["es-ES", "fr-FR", "de-DE"],
  name: "Multi-language translations",
};
typescript
const config = {
  input_video_id: "original_video_id",
  output_languages: ["es-ES", "fr-FR", "de-DE"],
  name: "多语言翻译版",
};

Custom Vocabulary (preserve specific terms)

自定义词汇表(保留特定术语)

typescript
const config = {
  video_url: "https://example.com/product-demo.mp4",
  output_language: "ja-JP",
  vocabulary: ["SuperWidget", "Pro Max", "TechCorp"],
};
typescript
const config = {
  video_url: "https://example.com/product-demo.mp4",
  output_language: "ja-JP",
  vocabulary: ["SuperWidget", "Pro Max", "TechCorp"],
};

Custom SRT Subtitles

自定义SRT字幕

typescript
const config = {
  video_url: "https://example.com/video.mp4",
  output_language: "es-ES",
  srt_key: "path/to/custom-subtitles.srt",
  srt_role: "input",
};
typescript
const config = {
  video_url: "https://example.com/video.mp4",
  output_language: "es-ES",
  srt_key: "path/to/custom-subtitles.srt",
  srt_role: "input",
};

Checking Translation Status

检查翻译状态

curl

curl示例

bash
curl -X GET "https://api.heygen.com/v2/video_translate/{translate_id}" \
  -H "X-Api-Key: $HEYGEN_API_KEY"
bash
curl -X GET "https://api.heygen.com/v2/video_translate/{translate_id}" \
  -H "X-Api-Key: $HEYGEN_API_KEY"

TypeScript

TypeScript示例

typescript
interface TranslateStatusResponse {
  error: null | string;
  data: {
    id: string;
    status: "pending" | "processing" | "completed" | "failed";
    video_url?: string;
    message?: string;
  };
}

async function getTranslateStatus(translateId: string): Promise<TranslateStatusResponse["data"]> {
  const response = await fetch(
    `https://api.heygen.com/v2/video_translate/${translateId}`,
    { headers: { "X-Api-Key": process.env.HEYGEN_API_KEY! } }
  );

  const json: TranslateStatusResponse = await response.json();

  if (json.error) {
    throw new Error(json.error);
  }

  return json.data;
}
typescript
interface TranslateStatusResponse {
  error: null | string;
  data: {
    id: string;
    status: "pending" | "processing" | "completed" | "failed";
    video_url?: string;
    message?: string;
  };
}

async function getTranslateStatus(translateId: string): Promise<TranslateStatusResponse["data"]> {
  const response = await fetch(
    `https://api.heygen.com/v2/video_translate/${translateId}`,
    { headers: { "X-Api-Key": process.env.HEYGEN_API_KEY! } }
  );

  const json: TranslateStatusResponse = await response.json();

  if (json.error) {
    throw new Error(json.error);
  }

  return json.data;
}

Polling for Completion

轮询等待完成

Translations take longer than standard video generation — allow up to 30 minutes.
typescript
async function waitForTranslation(
  translateId: string,
  maxWaitMs = 1800000,
  pollIntervalMs = 30000
): Promise<string> {
  const startTime = Date.now();

  while (Date.now() - startTime < maxWaitMs) {
    const status = await getTranslateStatus(translateId);

    switch (status.status) {
      case "completed":
        return status.video_url!;
      case "failed":
        throw new Error(status.message || "Translation failed");
      default:
        console.log(`Status: ${status.status}...`);
        await new Promise((r) => setTimeout(r, pollIntervalMs));
    }
  }

  throw new Error("Translation timed out");
}
翻译所需时间比标准视频生成更长——最多可能需要30分钟。
typescript
async function waitForTranslation(
  translateId: string,
  maxWaitMs = 1800000,
  pollIntervalMs = 30000
): Promise<string> {
  const startTime = Date.now();

  while (Date.now() - startTime < maxWaitMs) {
    const status = await getTranslateStatus(translateId);

    switch (status.status) {
      case "completed":
        return status.video_url!;
      case "failed":
        throw new Error(status.message || "翻译失败");
      default:
        console.log(`状态:${status.status}...`);
        await new Promise((r) => setTimeout(r, pollIntervalMs));
    }
  }

  throw new Error("翻译超时");
}

Complete Workflow

完整工作流程

typescript
async function translateAndDownload(
  videoUrl: string,
  targetLanguage: string
): Promise<string> {
  console.log(`Starting translation to ${targetLanguage}...`);
  const translateId = await translateVideo({
    video_url: videoUrl,
    output_language: targetLanguage,
  });
  console.log(`Translation ID: ${translateId}`);

  console.log("Processing translation...");
  const translatedVideoUrl = await waitForTranslation(translateId);
  console.log(`Translation complete: ${translatedVideoUrl}`);

  return translatedVideoUrl;
}

const spanishVideo = await translateAndDownload(
  "https://example.com/my-video.mp4",
  "es-ES"
);
typescript
async function translateAndDownload(
  videoUrl: string,
  targetLanguage: string
): Promise<string> {
  console.log(`开始翻译为${targetLanguage}...`);
  const translateId = await translateVideo({
    video_url: videoUrl,
    output_language: targetLanguage,
  });
  console.log(`翻译任务ID:${translateId}`);

  console.log(`处理翻译任务中...`);
  const translatedVideoUrl = await waitForTranslation(translateId);
  console.log(`翻译完成:${translatedVideoUrl}`);

  return translatedVideoUrl;
}

const spanishVideo = await translateAndDownload(
  "https://example.com/my-video.mp4",
  "es-ES"
);

Batch Translation

批量翻译

Translate to multiple languages in parallel:
typescript
async function translateToMultipleLanguages(
  sourceVideoUrl: string,
  targetLanguages: string[]
): Promise<Record<string, string>> {
  const results: Record<string, string> = {};

  const translatePromises = targetLanguages.map(async (lang) => {
    const translateId = await translateVideo({
      video_url: sourceVideoUrl,
      output_language: lang,
    });
    return { lang, translateId };
  });

  const translationJobs = await Promise.all(translatePromises);

  for (const job of translationJobs) {
    try {
      const videoUrl = await waitForTranslation(job.translateId);
      results[job.lang] = videoUrl;
    } catch (error) {
      results[job.lang] = `error: ${error.message}`;
    }
  }

  return results;
}

const translations = await translateToMultipleLanguages(
  "https://example.com/original.mp4",
  ["es-ES", "fr-FR", "de-DE", "ja-JP"]
);
并行翻译为多种语言:
typescript
async function translateToMultipleLanguages(
  sourceVideoUrl: string,
  targetLanguages: string[]
): Promise<Record<string, string>> {
  const results: Record<string, string> = {};

  const translatePromises = targetLanguages.map(async (lang) => {
    const translateId = await translateVideo({
      video_url: sourceVideoUrl,
      output_language: lang,
    });
    return { lang, translateId };
  });

  const translationJobs = await Promise.all(translatePromises);

  for (const job of translationJobs) {
    try {
      const videoUrl = await waitForTranslation(job.translateId);
      results[job.lang] = videoUrl;
    } catch (error) {
      results[job.lang] = `error: ${error.message}`;
    }
  }

  return results;
}

const translations = await translateToMultipleLanguages(
  "https://example.com/original.mp4",
  ["es-ES", "fr-FR", "de-DE", "ja-JP"]
);

Features

功能特性

  • Lip Sync — Automatically adjusts speaker's lip movements to match translated audio
  • Voice Cloning — Translated audio matches the original speaker's voice characteristics
  • Music Track Control — Optionally remove background music with
    disable_music_track: true
  • Speech Enhancement — Improve audio quality with
    enable_speech_enhancement: true
  • 唇形同步 — 自动调整说话人的唇形动作,使其与翻译后的音频匹配
  • 语音克隆 — 翻译后的音频与原说话人的语音特征一致
  • 背景音乐控制 — 通过
    disable_music_track: true
    选项移除背景音乐
  • 语音增强 — 通过
    enable_speech_enhancement: true
    提升音频质量

Best Practices

最佳实践

  1. Source quality matters — Use high-quality source videos for better results
  2. Clear audio — Videos with clear speech translate better
  3. Single speaker — Best results with single-speaker content
  4. Moderate pacing — Very fast speech may affect quality
  5. Test first — Try with shorter clips before translating long videos
  6. Allow extra time — Translation takes longer than video generation (up to 30 min)
  1. 源视频质量至关重要 — 使用高质量的源视频可获得更好的翻译效果
  2. 音频清晰 — 语音清晰的视频翻译效果更佳
  3. 单说话人内容 — 单说话人内容的翻译效果最好
  4. 语速适中 — 过快的语速可能影响翻译质量
  5. 先测试 — 翻译长视频前,先用短视频进行测试
  6. 预留足够时间 — 翻译所需时间比视频生成更长(最多30分钟)

Error Handling

错误处理

Common errors and how to handle them:
typescript
async function safeTranslate(
  videoUrl: string,
  targetLanguage: string
): Promise<{ success: boolean; result?: string; error?: string }> {
  try {
    const url = await translateAndDownload(videoUrl, targetLanguage);
    return { success: true, result: url };
  } catch (error) {
    if (error.message.includes("quota")) {
      return { success: false, error: "Insufficient credits" };
    }
    if (error.message.includes("duration")) {
      return { success: false, error: "Video too long" };
    }
    if (error.message.includes("format")) {
      return { success: false, error: "Unsupported video format" };
    }
    return { success: false, error: error.message };
  }
}
常见错误及处理方式:
typescript
async function safeTranslate(
  videoUrl: string,
  targetLanguage: string
): Promise<{ success: boolean; result?: string; error?: string }> {
  try {
    const url = await translateAndDownload(videoUrl, targetLanguage);
    return { success: true, result: url };
  } catch (error) {
    if (error.message.includes("quota")) {
      return { success: false, error: "可用额度不足" };
    }
    if (error.message.includes("duration")) {
      return { success: false, error: "视频时长过长" };
    }
    if (error.message.includes("format")) {
      return { success: false, error: "不支持的视频格式" };
    }
    return { success: false, error: error.message };
  }
}