mcpField
V
video-translate

video-translate

github.com/calesthioクリエイティブ・メディア73.0k1.1k 回インストール1 日前に更新
リポジトリ

video-translate について

video-translateは、HeyGenで既存動画を翻訳・吹き替えするスキルです。動画URLまたはHeyGen動画IDから依頼でき、リップシンクや音声のみの翻訳、多言語出力を扱います。

主な機能

  1. 01URLまたは動画IDから翻訳ジョブを作成
  2. 02リップシンクまたは音声のみの翻訳を選択
  3. 03ジョブ状態の確認と動画URLの取得
  4. 04複数の出力言語を指定
  5. 05用語とSRT字幕のカスタマイズ

活用シーン

  1. 01製品デモ動画の他言語版の作成
  2. 02複数話者のインタビュー動画の翻訳
  3. 03複数言語の動画版をまとめて生成
  4. 04ブランド用語の保持やカスタム字幕の利用

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/calesthio/openmontage --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. ステータスが completed になるまで GET /v2/video_translate/{translate_id} をポーリングします
  4. 返された URL から翻訳済みの動画をダウンロードします

翻訳ジョブの作成

リクエストフィールド
フィールド型必須説明
video_urlstringY*翻訳する動画の URL(*または video_id)
video_idstringY*HeyGen の動画 ID(*または video_url)
output_languagestringY翻訳先の言語コード(例:"es-ES")
titlestring翻訳済み動画の名前
translate_audio_onlyboolean音声のみ、リップシンクなし(高速)
speaker_numnumber動画内の話者数
callback_idstringwebhook の追跡用カスタム 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. 話者は1人にします — 話者が1人のコンテンツで最良の結果が得られます
  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 };
  }
}

コメント