mcpField
V
video-translate

video-translate

github.com/heygen-com创意与媒体5251.2k 次安装15 周前更新
代码仓库

关于 video-translate

此技能通过 HeyGen 视频翻译 API,将已有视频翻译并配音为其他语言。可提供视频 URL 或 HeyGen 视频 ID,并支持口型同步、仅音频输出和多语言任务。

主要功能

  1. 01将视频翻译为支持的语言
  2. 02同步翻译语音与口型
  3. 03生成仅音频的翻译版本
  4. 04处理多说话人视频
  5. 05提交多语言翻译任务

适用场景

  1. 01将视频本地化为其他语言
  2. 02制作仅含翻译音频的版本
  3. 03翻译多说话人的访谈
  4. 04生成多种语言的视频版本

MCP 相关

README 介绍了通过 HeyGen HTTP API 创建和查询翻译任务的流程,未提及 MCP 工具。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/heygen-com/skills --skill video-translate

安装后在 Claude Code 中输入/video-translate确认已加载。

详细介绍

视频翻译(HeyGen)

将现有视频翻译并配音成多种语言,同时保留口型同步和自然的说话方式。提供视频 URL 或 HeyGen 视频 ID 即可,无需先在 HeyGen 上创建视频。

身份验证

所有请求都需要 X-Api-Key 标头。设置 HEYGEN_API_KEY 环境变量。

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"}'

默认工作流

  1. 提供视频 URL 或 HeyGen 视频 ID
  2. 调用 POST /v2/video_translate 并指定目标语言
  3. 轮询 GET /v2/video_translate/{translate_id},直到状态变为 completed
  4. 从返回的 URL 下载翻译后的视频

创建翻译任务

请求字段
字段类型必填描述
video_urlstringY*要翻译的视频 URL(*或 video_id)
video_idstringY*HeyGen 视频 ID(*或 video_url)
output_languagestringY目标语言代码(例如 "es-ES")
titlestring翻译后视频的名称
translate_audio_onlyboolean仅翻译音频,不进行口型同步(速度更快)
speaker_numnumber视频中的说话人数
callback_idstring用于 Webhook 跟踪的自定义 ID
callback_urlstring完成通知的 URL

必须提供 video_url 或 video_id。

curl
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"
  }'
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
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"]

支持的语言

语言代码备注
英语(美国)en-US默认源语言
西班牙语(西班牙)es-ES欧洲西班牙语
西班牙语(墨西哥)es-MX拉丁美洲西班牙语
法语fr-FR标准法语
德语de-DE标准德语
意大利语it-IT标准意大利语
葡萄牙语(巴西)pt-BR巴西葡萄牙语
日语ja-JP标准日语
韩语ko-KR标准韩语
中文(普通话)zh-CN简体中文
印地语hi-IN标准印地语
阿拉伯语ar-SA现代标准阿拉伯语

翻译选项

基础翻译(含口型同步)
const config = {
  video_url: "https://example.com/original.mp4",
  output_language: "es-ES",
  title: "Spanish Translation",
};
仅翻译音频(速度更快,不进行口型同步)
const config = {
  video_url: "https://example.com/original.mp4",
  output_language: "es-ES",
  translate_audio_only: true,
};
多说话人视频
const config = {
  video_url: "https://example.com/interview.mp4",
  output_language: "fr-FR",
  speaker_num: 2,
};

高级选项(v4 API)

可对翻译进行更多控制:

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;
}
多种输出语言
const config = {
  input_video_id: "original_video_id",
  output_languages: ["es-ES", "fr-FR", "de-DE"],
  name: "Multi-language translations",
};
自定义词汇(保留特定术语)
const config = {
  video_url: "https://example.com/product-demo.mp4",
  output_language: "ja-JP",
  vocabulary: ["SuperWidget", "Pro Max", "TechCorp"],
};
自定义 SRT 字幕
const config = {
  video_url: "https://example.com/video.mp4",
  output_language: "es-ES",
  srt_key: "path/to/custom-subtitles.srt",
  srt_role: "input",
};

检查翻译状态

curl
curl -X GET "https://api.heygen.com/v2/video_translate/{translate_id}" \
  -H "X-Api-Key: $HEYGEN_API_KEY"
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;
}

轮询直至完成

翻译耗时比标准视频生成更长,请预留最多 30 分钟。

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");
}

完整工作流

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"
);

批量翻译

并行翻译成多种语言:

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"]
);

功能

  • 口型同步 — 自动调整说话者的唇部动作,使其与翻译后的音频相匹配
  • 声音克隆 — 翻译后的音频会匹配原说话者的声音特征
  • 音乐轨道控制 — 可选移除背景音乐,设置 disable_music_track: true 即可
  • 语音增强 — 设置 enable_speech_enhancement: true 可提升音频质量

最佳实践

  1. 源视频质量很重要 — 使用高质量的源视频可获得更好的效果
  2. 音频清晰 — 语音清晰的视频翻译效果更好
  3. 单人说话 — 单人说话的内容效果最佳
  4. 语速适中 — 语速过快可能影响质量
  5. 先进行测试 — 翻译长视频前,先尝试较短的片段
  6. 预留更多时间 — 翻译比视频生成耗时更长(最多 30 分钟)

错误处理

常见错误及处理方法:

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 };
  }
}

评论

支持 Markdown