HeyGen MP3 → MP4(单一用途)
接收一个MP3配音,返回一个HeyGen头像唇同步MP4。除此之外,不执行任何其他操作。
本技能的存在是因为现有的 heygen-short-video 技能需要完整的制作计划 + SRT + 分块片段——当用户只有一个完成的配音并希望获得说话头视频时,这显得过于繁琐。
为什么采用混合REST + MCP(而不是纯MCP)
本技能的早期版本强制执行“仅使用MCP——绝不调用REST”的规则。但自2026年HeyGen MCP重构以来,此规则已不再可行:MCP服务器仅暴露 create_video_from_avatar、get_video、create_lipsync、list_avatar_looks 等工具——不再提供资产上传工具。要从本地MP3实现唇同步,API仍然需要一个 audioAssetId(上传的资产)或 audioUrl(公共HTTPS URL)。托管公共URL存在脆弱性(链接失效、泄露),因此我们通过一个轻量级辅助脚本使用文档化的REST上传端点,然后继续通过MCP进行视频创建、轮询和下载。
硬性约束
| 约束条件 | 允许值 |
|---|---|
| 资产上传 | REST POST https://upload.heygen.com/v1/asset 通过 scripts/upload_asset.py(使用 HEYGEN_API_KEY) |
| 视频创建 / 状态 / 列表 | 仅使用HeyGen MCP(mcp__heygen__create_video_from_avatar、mcp__heygen__get_video) |
| 头像外观ID | HEYGEN_AVATAR_LOOKS 环境变量中的ID之一(逗号分隔的允许列表) |
| 语音ID(仅当MCP路径强制要求TTS时) | 来自 .env 的 HEYGEN_VOICE_ID(不允许使用其他语音ID) |
| MP3时长 | ≤ 300秒(5分钟)。如果超过,快速失败;不要自动分割 |
| 宽高比(MCP枚举) | 默认为 9:16(TikTok / Reels)。仅在父协调器覆盖时使用 16:9 |
| 分辨率(MCP枚举) | 默认为 720p(9:16 时生成 720×1280,16:9 时生成 1280×720) |
对于MP3唇同步,语音类型为 audio,并提供 audioAssetId——不发送 voiceId。上述语音ID允许列表仅在未来的MCP签名要求时才有意义。
输入
- MP3路径(必需)——配音文件的绝对路径。
- 头像外观ID(可选)——允许的ID之一。如果省略,从允许集合中随机选取,以在不同运行中产生视觉多样性。
- 输出路径(可选)——默认为项目根目录下的
workspace/heygen-clips/<mp3-stem>/<mp3-stem>_<YYYYMMDD-HHMMSS>.mp4。 - 宽高比(可选)——
9:16(默认)或16:9。
工作流程
按顺序执行以下步骤。每个步骤都有停止条件;不要越过失败的步骤继续执行。
0. 认证检查(仅在首次调用时)
HeyGen MCP服务器使用OAuth。在新会话中,仅暴露 mcp__heygen__authenticate 和 mcp__heygen__complete_authentication;真正的工具(create_video_from_avatar、get_video 等)在认证完成后才会出现。如果会话中未加载这些工具,请调用 mcp__heygen__authenticate 并向用户显示返回的授权URL。用户点击该链接 → 浏览器可能显示本地回调的“连接错误”(这是预期的)→ 用户将完整的回调URL粘贴回来,您调用 mcp__heygen__complete_authentication。一旦认证后的工具出现在延迟工具列表中,继续执行。
1. 验证MP3
uv run .claude/skills/heygen-mp3-to-mp4/scripts/check_duration.py "<mp3_path>"
输出 OK <seconds> / TOO_LONG <seconds> / MISSING。退出码0表示OK,非零表示停止。
如果输出 TOO_LONG:告知用户时长以及HeyGen单个视频的上限约为5分钟,并建议使用现有的 heygen-short-video 技能(它会进行分块)。不要继续执行。
2. 选择头像外观
从 HEYGEN_AVATAR_LOOKS(逗号分隔的允许列表)中读取:
HEYGEN_AVATAR_LOOKS=$(
grep -h '^HEYGEN_AVATAR_LOOKS=' .env.local .env 2>/dev/null \
| head -1 | cut -d'=' -f2- | tr -d '"' | tr -d "'"
)
echo "$HEYGEN_AVATAR_LOOKS" | tr ',' '\n' | awk 'BEGIN{srand()} {a[NR]=$0} END{print a[int(rand()*NR)+1]}'
占位符陷阱——claudeclaw-os/.env.local 中带有占位符桩(avatar_look_id_1,avatar_look_id_2)。真实值通常位于 ~/Documents/GitHub/hoang-ai-marketing/.env:
grep '^HEYGEN_AVATAR_LOOKS=' ~/Documents/GitHub/hoang-ai-marketing/.env
如果该值匹配 ^(your_|avatar_look_id_|placeholder),则视为缺失并回退到营销仓库的 .env。如果两者都是占位符/缺失,则停止并要求用户填写真实的ID。
在继续之前告知用户您选择了哪个头像外观——他们可能希望覆盖。
3. 将MP3作为HeyGen资产上传(REST)
uv run .claude/skills/heygen-mp3-to-mp4/scripts/upload_asset.py "<mp3_path>"
# → 成功时输出 "OK <asset_id>"
该辅助脚本处理 X-Api-Key 头信息,为音频扩展选择正确的 Content-Type,并按以下顺序解析 HEYGEN_API_KEY:--key-file 标志 → HEYGEN_API_KEY 环境变量 → .env.local → .env → ~/Documents/GitHub/hoang-ai-marketing/.env。占位符桩(your_*)会被自动跳过。
捕获标准输出中打印的 asset_id。
4. 生成头像视频(MCP)
使用新模式调用 mcp__heygen__create_video_from_avatar(旧的 dimension: {width, height} 形状已消失——该工具现在接受 aspectRatio 枚举 + resolution 枚举):
avatarId: <从允许列表中选取>
audioAssetId: <来自步骤3>
aspectRatio: "9:16" # 或当父协调器覆盖时为 "16:9"
resolution: "720p" # 720p · 1080p · 4k
title: "<mp3-stem>-<timestamp>"
捕获返回的 video_id(初始状态为 waiting)。
为什么使用音频(而非文本): 从现有MP3进行唇同步需要HeyGen直接消费音频。在此处发送 script + voiceId 会将HeyGen切换到TTS模式,并完全忽略上传的MP3。
5. 轮询直到完成
每隔约10-15秒调用 mcp__heygen__get_video,传入 video_id。状态:
waiting/processing/pending→ 继续轮询completed→ 从响应中获取video_url并继续执行failed→ 停止,向用户显示failure_message
等待上限约为10分钟;如果仍在处理,告知用户并让他们决定。
zsh轮询循环的陷阱——status 变量名在zsh中是只读的。如果在轮询循环中写入 status=$(…),脚本会因 read-only variable: status 而崩溃。请使用不同的名称(vstate、phase、ready)。
6. 下载MP4
uv run .claude/skills/heygen-mp3-to-mp4/scripts/download_video.py "<video_url>" "<output_path>"
直接通过HTTPS下载HeyGen返回的URL——不是用于创建或修改视频的API调用。
7. 报告结果
在一个简短回复中告知用户三件事:
- MP4的输出路径
- 使用了哪个头像外观
- 结果的时长和文件大小
示例
用户:tạo video heygen từ mp3 workspace/audio/episode-3.mp3
您应:
- 认证检查 → 如果HeyGen工具已存在,跳过;否则执行
mcp__heygen__authenticate+ 完成OAuth流程。 check_duration.py workspace/audio/episode-3.mp3→OK 87.4- 从
HEYGEN_AVATAR_LOOKS中随机选取(例如66e75e22e6584bbdaa56a19088286dc8)。告知用户。 upload_asset.py workspace/audio/episode-3.mp3→OK 36922ca92326480f8dbb0f57fae1a144mcp__heygen__create_video_from_avatar(avatarId=…, audioAssetId=…, aspectRatio="9:16", resolution="720p", title="episode-3-…")→video_id: 874793a8…- 每隔约15秒轮询
mcp__heygen__get_video,直到状态为completed→ 获取video_url download_video.py <url> workspace/heygen-clips/episode-3/episode-3_20260510-143022.mp4- 报告路径、外观ID和时长。
本技能明确不执行的操作
- 不写入/转录SRT(那是
mkt-ai-video-extract-srt-segment的职责)。 - 不规划视觉元素、补充素材、片段(那是
mkt-plan-short-video-edit-16-9的职责)。 - 不对MP3进行分块(那是
heygen-short-video配合split_audio.py的职责)。 - 不使用Remotion或HyperFrames进行合成(那是父协调器的职责)。
如果用户需要上述任何功能,请将其引导至正确的技能,而不是扩展本技能。
失败模式及消息
| 症状 | 告知用户的内容 |
|---|---|
| MP3文件缺失 | MP3 không tìm thấy ở <path>. Kiểm tra lại đường dẫn. |
| MP3 > 300秒 | MP3 dài <X>s, vượt giới hạn 5 phút của HeyGen. Dùng skill heygen-short-video (có chunking) thay thế. |
| HeyGen MCP未认证 | 显示 mcp__heygen__authenticate URL,要求用户授权,然后执行 mcp__heygen__complete_authentication。 |
HEYGEN_API_KEY 未找到/占位符 | Không tìm thấy HEYGEN_API_KEY. Helper đã thử .env.local, .env, và ~/Documents/GitHub/hoang-ai-marketing/.env. Bạn cần thêm key thật (không phải stub your_*) vào 1 trong các file đó. |
HEYGEN_AVATAR_LOOKS 是占位符(avatar_look_id_1,…) | 与API密钥相同的回退策略——从营销仓库读取,或要求用户填写真实的头像ID。 |
| HeyGen返回失败 | HeyGen render failed: <failure_message>. Có thể avatar look bị xoá hoặc audio asset không hợp lệ. |
| 积分不足 | 显示来自HeyGen的错误——此服务器版本中未暴露MCP get_remaining_credits。引导用户访问 https://app.heygen.com/billing。 |
工具名称未找到(upload_asset / generate_avatar_video / get_avatar_video_status) | 旧的MCP名称——已替换为REST上传 + create_video_from_avatar + get_video。更新任何仍使用旧名称的调用者。 |