ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

OpenMontage 集成 HeyGen:用 /v2/video/generate 精确生成 AI 数字人视频

OpenMontage 集成 HeyGen:用 /v2/video/generate 精确生成 AI 数字人视频 OpenMontage 集成 HeyGen用 /v2/video/generate 精确生成 AI 数字人视频【免费下载链接】OpenMontageWorlds first open-source, agentic video production system. 12 production pipelines, 100 tools, 700 agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage本文基于 OpenMontage 技能文件.agents/skills/avatar-video/references/video-generation.md展开系统讲解 HeyGenPOST /v2/video/generate接口的完整请求结构、多场景1–50 场景视频构建、文字/音频/静音三种语音输入方式、透明背景 WebM 的适用边界以及生产级工作流自动选数字人、默认音色匹配、轮询与超时策略。读完后你可以直接复制其中的 curl / TypeScript / Python 客户端与轮询逻辑并在 OpenMontage 的 avatar-spokesperson 数字人管线中落地文末还对照了仓库中heygen_video工具的实际实现帮助你理解该技能与仓库代码层的衔接关系。技能定位avatar-video 技能与 HeyGen MCP 工具这份文档是 OpenMontage 仓库中 avatar-video 技能 的核心参考文件之一。该技能的定位与 create-video 技能互补当你需要精确控制数字人、音色、逐句脚本和每个场景的背景时使用 avatar-video 技能如果只是想让 AI 自行完成脚本与画面则用 create-video。技能的标准工作流来自 SKILL.md共五步列出数字人—GET /v2/avatars选定avatar_id并记录default_voice_id详见 avatars.md列出音色—GET /v2/voices选择与数字人性别/语言匹配的音色详见 voices.md编写脚本— 每个场景一个核心概念详见 scripts.md生成视频— 即本文主角POST /v2/video/generate按场景配置数字人、音色、脚本与背景轮询完成—GET /v2/videos/{video_id}直到状态为completed详见 video-status.md。工具选择如果 HeyGen MCP 工具mcp__heygen__*可用应优先使用 MCP 工具而非直接 HTTP 调用——它们自动处理鉴权与请求格式化。常用对照关系如下任务MCP 工具直接 API 回退查询视频状态 / 获取 URLmcp__heygen__get_videoGET /v2/videos/{video_id}列出账号视频mcp__heygen__list_videosGET /v2/videos删除视频mcp__heygen__delete_videoDELETE /v2/videos/{video_id}注意视频生成POST /v2/video/generate与数字人/音色列表查询走的是直接 API 调用。所有请求都需要X-Api-Key请求头使用前需设置HEYGEN_API_KEY环境变量技能元数据中已声明该环境依赖。视频输出格式MP4 与 WebM 的选择HeyGen 提供两个视频生成端点二者的结构与用途完全不同端点格式用途/v2/video/generateMP4标准方案— 带背景的视频最常见/v1/video.webmWebM透明背景 — 仅在需要时使用选型原则绝大多数场景用 MP4 背景即可。只有当需要看到数字人背后的内容时例如把数字人叠加在屏幕录制之上才需要 WebM 的透明通道。场景格式原因数字人上方叠加动效/文字MP4叠加层在上层不需要透明度标准演讲人视频MP4更简单、兼容性更好Loom 风格数字人浮在屏幕录制上WebMnormal/closeUp需要透明通道圆形裁剪在后期做数字人悬浮于视频内容之上WebM需要看到数字人背后的内容基础视频生成第一个 curl 请求最小可用的生成请求如下使用avatar类型数字人 文字配音curl -X POST https://api.heygen.com/v2/video/generate \ -H X-Api-Key: $HEYGEN_API_KEY \ -H Content-Type: application/json \ -d { video_inputs: [ { character: { type: avatar, avatar_id: josh_lite3_20230714, avatar_style: normal }, voice: { type: text, input_text: Hello! Welcome to HeyGen., voice_id: 1bd001e7e50f421d891986aad5158bc8 } } ], dimension: { width: 1920, height: 1080 } }成功时返回{ error: null, data: { video_id: ... } }拿到video_id后进入轮询阶段见后文完整工作流。请求字段全解顶层字段字段类型必填说明video_inputsarray✓1–50 个视频输入对象的数组即 1–50 个场景dimensionobject视频尺寸{width, height}titlestring视频名称便于组织管理testboolean测试模式输出带水印不消耗积分captionboolean启用自动字幕callback_idstringWebhook 追踪用的自定义 IDcallback_urlstring完成通知 URLfolder_idstring存储文件夹 IDvideo_inputs[].character数字人/角色字段字段类型必填说明typestring✓avatar或talking_photoavatar_idstring✓*数字人 IDtype 为avatar时必填talking_photo_idstring✓*照片 IDtype 为talking_photo时必填avatar_stylestringnormal、closeUp或circlescalenumber数字人缩放因子offsetobject位置偏移{x, y}video_inputs[].voice语音字段字段类型必填说明typestring✓text、audio或silencevoice_idstring✓*音色 IDtype 为text时必填input_textstring✓*脚本文本type 为text时必填audio_urlstring✓*音频 URLtype 为audio时必填durationnumber✓*时长秒type 为silence时必填speednumber语速 0.5–2.0默认 1.0pitchnumber音调 -20 到 20默认 0video_inputs[].background背景字段字段类型必填说明typestringcolor、image或videovaluestring十六进制颜色type 为color时urlstring图片/视频 URLtype 为image/video时fitstringcover或containTypeScript 类型定义以下接口把条件必填用可选标记 注释表达带?的为可选字段是否真的必填取决于type取值// Required fields have no ? - optional fields have ? interface VideoInput { character: { type: avatar | talking_photo; // Required avatar_id?: string; // Required when typeavatar talking_photo_id?: string; // Required when typetalking_photo avatar_style?: normal | closeUp | circle; scale?: number; offset?: { x: number; y: number }; }; voice: { type: text | audio | silence; // Required input_text?: string; // Required when typetext voice_id?: string; // Required when typetext audio_url?: string; // Required when typeaudio duration?: number; // Required when typesilence speed?: number; pitch?: number; }; background?: { type?: color | image | video; value?: string; url?: string; fit?: cover | contain; }; } interface VideoGenerateRequest { video_inputs: VideoInput[]; // Required dimension?: { width: number; height: number }; test?: boolean; title?: string; caption?: boolean; callback_id?: string; callback_url?: string; folder_id?: string; } interface VideoGenerateResponse { error: null | string; data: { video_id: string; }; } async function generateVideo(config: VideoGenerateRequest): Promisestring { const response await fetch(https://api.heygen.com/v2/video/generate, { method: POST, headers: { X-Api-Key: process.env.HEYGEN_API_KEY!, Content-Type: application/json, }, body: JSON.stringify(config), }); const json: VideoGenerateResponse await response.json(); if (json.error) { throw new Error(json.error); } return json.data.video_id; }Python 客户端import requests import os def generate_video(config: dict) - str: response requests.post( https://api.heygen.com/v2/video/generate, headers{ X-Api-Key: os.environ[HEYGEN_API_KEY], Content-Type: application/json }, jsonconfig ) data response.json() if data.get(error): raise Exception(data[error]) return data[data][video_id]完整配置示例与多场景视频全量配置示例下面是一个把顶层字段与场景内各配置项都用到的完整请求const fullConfig: VideoGenerateRequest { // Test mode (no credits consumed, watermarked output) test: false, // Video title (for organization) title: Product Demo Video, // Video dimensions dimension: { width: 1920, height: 1080, }, // Video scenes/inputs video_inputs: [ { // Avatar configuration character: { type: avatar, avatar_id: josh_lite3_20230714, avatar_style: normal, }, // Voice configuration voice: { type: text, input_text: Welcome to our product demonstration!, voice_id: 1bd001e7e50f421d891986aad5158bc8, speed: 1.0, pitch: 0, }, // Background configuration background: { type: color, value: #FFFFFF, }, }, ], };多场景视频video_inputs数组的每个元素就是一个场景场景之间可以切换数字人样式、背景类型纯色 / 图片与脚本内容。以下是开场 — 功能点 — 结尾三场景示例const multiSceneConfig { video_inputs: [ // Scene 1: Introduction { character: { type: avatar, avatar_id: josh_lite3_20230714, avatar_style: normal, }, voice: { type: text, input_text: Hello! Today Ill show you three key features., voice_id: 1bd001e7e50f421d891986aad5158bc8, }, background: { type: color, value: #1a1a2e, }, }, // Scene 2: Feature 1 { character: { type: avatar, avatar_id: josh_lite3_20230714, avatar_style: closeUp, }, voice: { type: text, input_text: First, lets look at our dashboard., voice_id: 1bd001e7e50f421d891986aad5158bc8, }, background: { type: image, url: https://example.com/dashboard-bg.jpg, }, }, // Scene 3: Conclusion { character: { type: avatar, avatar_id: josh_lite3_20230714, avatar_style: normal, }, voice: { type: text, input_text: Thanks for watching! Try it today., voice_id: 1bd001e7e50f421d891986aad5158bc8, }, background: { type: color, value: #1a1a2e, }, }, ], dimension: { width: 1920, height: 1080 }, };角色类型与语音输入类型两种角色类型Avatar数字人{ character: { type: avatar, avatar_id: josh_lite3_20230714, avatar_style: normal } }Talking Photo会说话的照片——用照片 ID 代替avatar_id{ character: { type: talking_photo, talking_photo_id: your_talking_photo_id } }三种语音输入类型1. 文字转语音text-to-speech{ voice: { type: text, input_text: Your script here, voice_id: 1bd001e7e50f421d891986aad5158bc8, speed: 1.0, // 0.5 - 2.0 pitch: 0 // -20 to 20 } }2. 自定义音频audio——传入现成音频 URL数字人做口型同步{ voice: { type: audio, audio_url: https://example.com/your-audio.mp3 } }3. 静音silence——只填duration秒用于插入纯视觉的静默段。完整工作流生成、轮询与错误处理生成接口是异步的提交后返回video_id真正的成片要通过GET /v2/videos/{video_id}轮询获得。下面是把生成 轮询串起来的完整 TypeScript 示例async function createVideo(script: string, avatarId: string, voiceId: string) { // 1. Generate video console.log(Starting video generation...); const videoId await generateVideo({ video_inputs: [ { character: { type: avatar, avatar_id: avatarId, avatar_style: normal, }, voice: { type: text, input_text: script, voice_id: voiceId, }, background: { type: color, value: #FFFFFF, }, }, ], dimension: { width: 1920, height: 1080 }, }); console.log(Video ID: ${videoId}); // 2. Poll for completion console.log(Waiting for video completion...); const videoUrl await waitForVideo(videoId); console.log(Video ready: ${videoUrl}); return videoUrl; } // Helper function for polling async function waitForVideo(videoId: string): Promisestring { const maxAttempts 60; const pollInterval 10000; // 10 seconds for (let i 0; i maxAttempts; i) { const response await fetch( https://api.heygen.com/v2/videos/${videoId}, { headers: { X-Api-Key: process.env.HEYGEN_API_KEY! } } ); const { data } await response.json(); if (data.status completed) { return data.video_url; } else if (data.status failed) { throw new Error(data.failure_message || Video generation failed); } await new Promise((r) setTimeout(r, pollInterval)); } throw new Error(Video generation timed out); }状态接口的完整字段含thumbnail_url、gif_url、captioned_video_url、failure_code、failure_message等在 video-status.md 中有专门定义状态枚举为pending/processing/completed/failed。错误处理按错误信息关键词分类是文档推荐的处理方式async function generateVideoSafe(config: VideoGenerateRequest) { try { const videoId await generateVideo(config); return { success: true, videoId }; } catch (error) { // Common errors if (error.message.includes(quota)) { console.error(Insufficient credits); } else if (error.message.includes(avatar)) { console.error(Invalid avatar ID); } else if (error.message.includes(voice)) { console.error(Invalid voice ID); } else if (error.message.includes(script)) { console.error(Script too long or invalid); } return { success: false, error: error.message }; } }脚本长度限制与 停顿标签脚本长度按账户层级有上限层级最大字符数Free约 500Creator约 1,500Team约 3,000Enterprise约 5,000停顿标签在脚本中使用break标签插入停顿const script Welcome to our demo. break time\1s\/ Let me show you the features.;格式break timeXs/X 为秒数如1s、1.5s、0.5s重要break 标签前后必须留空格更完整的 break 标签文档见 voices.md。测试模式不消耗积分的调试通道开发调试阶段把test设为true输出会带水印但不消耗积分const config { test: true, // Watermarked output, no credits consumed video_inputs: [...], };生产级工作流自动选数字人 默认音色以下是一个开箱即用的生产级示例包含三个关键实践未指定数字人时自动取列表第一个、优先使用数字人自带的default_voice_id多数数字人有预匹配的默认音色效果更自然、20 分钟超时生成通常需要 5–15 分钟有时更长interface VideoGenerationResult { videoId: string; videoUrl: string; duration: number; avatarId: string; voiceId: string; avatarName: string; } async function generateAvatarVideo( script: string, options: { avatarId?: string; // Specific avatar, or will pick first available width?: number; height?: number; } {} ): PromiseVideoGenerationResult { const { width 1920, height 1080 } options; let { avatarId } options; // 1. List avatars if no specific one provided if (!avatarId) { console.log(Listing available avatars...); const listResponse await fetch(https://api.heygen.com/v2/avatars, { headers: { X-Api-Key: process.env.HEYGEN_API_KEY! }, }); const listData await listResponse.json(); if (!listData.data?.avatars?.length) { throw new Error(No avatars available); } avatarId listData.data.avatars[0].avatar_id; } // 2. Get avatar details including default_voice_id console.log(Getting details for avatar: ${avatarId}); const detailsResponse await fetch( https://api.heygen.com/v2/avatar/${avatarId}/details, { headers: { X-Api-Key: process.env.HEYGEN_API_KEY! } } ); const { data: avatar } await detailsResponse.json(); if (!avatar.default_voice_id) { throw new Error(Avatar ${avatar.name} has no default voice - select voice manually); } console.log(Using avatar: ${avatar.name} with default voice: ${avatar.default_voice_id}); // 3. Generate video using avatars default voice const videoId await generateVideo({ video_inputs: [{ character: { type: avatar, avatar_id: avatar.id, // from details response avatar_style: normal, }, voice: { type: text, input_text: script, voice_id: avatar.default_voice_id, // pre-matched default voice speed: 1.0, }, background: { type: color, value: #1a1a2e, }, }], dimension: { width, height }, }); console.log(Video ID: ${videoId}); // 4. Wait for completion (20 minute timeout - generation can take 15 min) console.log(Waiting for video generation (typically 5-15 minutes, can be longer)...); const result await waitForVideo( videoId, process.env.HEYGEN_API_KEY!, (status, elapsed) { console.log( [${Math.round(elapsed / 1000)}s] ${status}); }, 1200000 // 20 minute timeout for safety ); return { videoId, videoUrl: result.video_url!, duration: result.duration!, avatarId: avatar.id, voiceId: avatar.default_voice_id, avatarName: avatar.name, }; } // Usage - let it pick an avatar automatically const result await generateAvatarVideo( Hello! Welcome to our product demonstration. ); console.log(Video ready: ${result.videoUrl}); // Or specify a known avatar_id const result2 await generateAvatarVideo( Hello! Welcome to our product demonstration., { avatarId: josh_lite3_20230714 } );透明背景视频WebM端点结构不同字段不同WebM 端点/v1/video.webm与/v2/video/generate的请求结构完全不同不能直接套用 v2 的video_inputs结构。它只在你需要透明通道数字人背后内容要可见时才使用。不需要 WebM 的情况在数字人上方叠加动效/文字纯色背景的画中画标准演讲人视频。需要 WebM 的情况数字人叠加在屏幕录制上数字人悬浮于视频背景之上真正的 alpha 通道合成。WebM 请求字段字段类型必填说明avatar_pose_idstring✓数字人姿势 ID来自 avatar detailsavatar_stylestring✓仅支持normal或closeUp无 circleinput_textstring✓*脚本文本不使用 input_audio 时必填voice_idstring✓*音色 ID与 input_text 搭配必填input_audiostring✓*音频 URL不使用 input_text 时必填dimensionobject{width, height}默认 1280x720二选一规则input_textvoice_id与input_audio二者必须提供其一且不可同时提供。curl 示例curl -X POST https://api.heygen.com/v1/video.webm \ -H X-Api-Key: $HEYGEN_API_KEY \ -H Content-Type: application/json \ -d { avatar_pose_id: josh_lite3_20230714, avatar_style: normal, input_text: Hello! This video has a transparent background., voice_id: 1bd001e7e50f421d891986aad5158bc8, dimension: { width: 1920, height: 1080 } }TypeScript 客户端interface WebMVideoRequest { avatar_pose_id: string; // Required avatar_style: normal | closeUp; // Required (no circle support) input_text?: string; // Required if not using input_audio voice_id?: string; // Required with input_text input_audio?: string; // Required if not using input_text dimension?: { width: number; height: number }; } async function generateTransparentVideo( script: string, avatarPoseId: string, voiceId: string ): Promisestring { const response await fetch(https://api.heygen.com/v1/video.webm, { method: POST, headers: { X-Api-Key: process.env.HEYGEN_API_KEY!, Content-Type: application/json, }, body: JSON.stringify({ avatar_pose_id: avatarPoseId, // Required avatar_style: normal, // Required: normal or closeUp input_text: script, // Required (with voice_id) voice_id: voiceId, // Required (with input_text) dimension: { width: 1920, height: 1080 }, }), }); const { data } await response.json(); return data.video_id; }注意WebM 仅支持normal和closeUp两种样式不支持 circle——圆形遮罩需要在视频编辑器或 Remotion 中后处理实现。Loom 风格实例WebM 数字人 Remotion 圆形遮罩先生成透明背景数字人normal或closeUp样式const videoId await fetch(https://api.heygen.com/v1/video.webm, { method: POST, headers: { X-Api-Key: apiKey, Content-Type: application/json }, body: JSON.stringify({ avatar_pose_id: avatarPoseId, // Required avatar_style: closeUp, // Required: normal or closeUp only input_text: script, // Required (with voice_id) voice_id: voiceId, // Required (with input_text) dimension: { width: 1920, height: 1080 }, }), }).then(r r.json()).then(d d.data.video_id);再在 Remotion 中用 CSS 圆形遮罩合成到屏幕录制之上import { Video, AbsoluteFill } from remotion; export const LoomStyleVideo: React.FC{ screenRecordingUrl: string; avatarWebmUrl: string; } ({ screenRecordingUrl, avatarWebmUrl }) { return ( AbsoluteFill {/* Screen recording as base layer */} Video src{screenRecordingUrl} style{{ width: 100%, height: 100% }} / {/* Avatar with circular mask applied in CSS */} Video src{avatarWebmUrl} style{{ position: absolute, bottom: 20, left: 20, width: 150, height: 150, borderRadius: 50%, // Circular mask overflow: hidden, objectFit: cover, }} / /AbsoluteFill ); };与 Remotion 集成的更多细节可参考 remotion-integration.md。状态轮询WebM 视频与 MP4 使用同一个状态端点GET /v2/videos/{video_id}只是返回的video_url指向.webm文件// Same polling as regular videos const status await getVideoStatus(videoId); // status.video_url will be a .webm file最佳实践清单技能文档给出的 10 条最佳实践原文完整保留并附对应参考文件生成前先预览数字人— 下载preview_image_url让用户在投入生成前看到数字人形象见 avatars.md优先使用数字人默认音色— 多数数字人有预匹配的default_voice_id效果更自然见 avatars.md回退方案手动匹配性别— 若没有默认音色确保数字人与音色性别一致见 voices.md校验输入— 生成前检查 avatar 与 voice ID 是否有效使用测试模式— 不消耗积分地验证配置设置宽松的超时— 建议 15–20 分钟生成常需 10–15 分钟甚至更长考虑异步模式— 长视频先保存video_id稍后查状态见 video-status.md优雅处理错误— 实现上述错误分类逻辑监控进度— 轮询时输出进度反馈优化脚本— 保持简洁自然并让尺寸匹配使用场景见 dimensions.md。结合仓库源码avatar-video 技能与 heygen_video 工具的分工把技能文档放回 OpenMontage 仓库的整体结构中看两者承担的是互补而非重叠的角色技能文档本文主体面向的是 HeyGenv2 数字人 API/v2/video/generate与/v1/video.webm核心是精确控制 avatar、音色、逐场景脚本与背景。它的参考文件集还包括 背景、文字叠加、字幕、模板、照片数字人、Webhook、资产上传、尺寸 与 配额。仓库工具实现tools/video/heygen_video.py 中的HeyGenVideo工具走的是 HeyGen 的Workflow 执行端点POST /v1/workflows/executionsworkflow_type: GenerateVideoNode底层实现在 tools/video/_shared.py 的generate_heygen_video()与poll_heygen()5 秒间隔轮询、默认 600 秒超时。从源码结构看该工具面向的是 VEO、Kling、Seedance 等文生视频/图生视频模型变体HEYGEN_PROVIDERS矩阵与本技能讲解的数字人口播视频/v2/video/generate是两条不同的 API 路径——这正是技能文档独立存在的意义v2 数字人端点没有对应的单点工具封装直接按本文的 API 调用执行。状态可发现性HeyGenVideo的get_status()以HEYGEN_API_KEY环境变量是否存在作为可用判据设置该变量即从UNAVAILABLE变为AVAILABLE重试策略为最多 2 次、退避 10 秒、仅对rate_limit/timeout/server_error重试。管线层引用在 avatar-spokesperson 管线的制片人技能 中数字人视频路径被抽象为avatar_path配置项heygen_api / sadtalker / musetalk / stock并说明talking_head工具常见不可用依赖 GPU 或 HeyGen API key、受阻时制片人必须显式路由而非临场发挥。这说明 HeyGen API 是该管线数字人路径的主要云端选项之一与本文技能形成从策略层路由到执行层 API 调用的完整链路。适用前提与限制文中所有 API 行为字段、限制、状态枚举均以该技能参考文档的描述为准端点为https://api.heygen.com脚本长度上限、积分消耗等随账户层级变化实际以 HeyGen 账户为准。仓库内示例使用的avatar_id与voice_id是文档中的占位示例值实际生产前应先通过GET /v2/avatars与GET /v2/voices确认可用 ID。【免费下载链接】OpenMontageWorlds first open-source, agentic video production system. 12 production pipelines, 100 tools, 700 agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表