HeyGen 数字人视频与 Remotion 合成集成实战指南(OpenMontage remotion-composer 实践)

发布时间:2026/9/10 15:47:45
HeyGen 数字人视频与 Remotion 合成集成实战指南(OpenMontage remotion-composer 实践) HeyGen 数字人视频与 Remotion 合成集成实战指南OpenMontage remotion-composer 实践【免费下载链接】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 仓库中 avatar-video 技能 的 Remotion 集成指南为主体系统讲解如何用 HeyGen API 生成 AI 数字人Avatar视频并将其嵌入 Remotion 合成Composition完成字幕、图形动画、图表等动效叠加与最终渲染。读完本文你将掌握 HeyGen MP4/WebM 两种输出格式的选型、基于OffthreadVideo的帧精确播放、并行开发工作流、动态时长计算以及一整套可直接运行的生成–合成–渲染代码模板。一、整体工作流从 HeyGen 生成到 Remotion 合成在 OpenMontage 中HeyGen 数字人视频被用于 talking-head讲解头类视频生产。典型的工作流分为四步调用 HeyGen/v2/video/generate接口生成数字人视频轮询视频状态直至完成拿到可用的视频 URL将视频 URL或本地下载文件作为素材喂给 Remotion 合成在 Remotion 中叠加背景、图形动效、字幕、图表等元素并渲染成片。对应到仓库里的实际实现remotion-composer 是一个基于 Remotion 4.xremotion: ^4.0.484的合成渲染工程其中的 TalkingHead.tsx 就是数字人视频 动态叠加层 字幕三层结构的典型落地Layer 1OffthreadVideo播放数字人视频videoSrcobjectFit: cover铺满画面Layer 2按时间轴in_seconds/out_seconds通过Sequence挂载图表、统计卡片、Callout、对比卡片等 13 类叠加组件Layer 3最上层渲染逐词高亮字幕CaptionOverlay。下面按选型 → 生成 → 合成 → 渲染 → 排障的顺序完整展开。二、Quick Start最小可运行示例// 1. 获取数字人详情含默认音色 const avatar await getAvatarDetails(avatarId); // 2. 生成视频带背景的 MP4 是最常用形态 const videoId await generateVideo({ video_inputs: [{ character: { type: avatar, avatar_id: avatar.id, avatar_style: normal }, voice: { type: text, input_text: script, voice_id: avatar.default_voice_id }, background: { type: color, value: #1a1a2e }, }], dimension: { width: 1920, height: 1080 }, }); // 3. 轮询等待完成通常耗时 10-15 分钟以上 // 4. 在 Remotion 中使用并在其上叠加动态图形三点关键提醒所有请求都要携带X-Api-Key请求头密钥通过环境变量HEYGEN_API_KEY提供见 avatar-video/SKILL.md优先使用数字人自带的default_voice_id这是 HeyGen 预先匹配好的音色效果最自然视频生成是异步的不要同步阻塞等待详见下文并行开发工作流。三、输出格式选型MP4 还是 WebMHeyGen 提供两个端点、两种输出形态选型直接决定合成层的复杂度你的合成场景推荐格式原因数字人主讲 叠加图形MP4 背景更简单叠加层直接放在上层Loom 风格数字人浮在屏幕录制上WebM closeUp在 Remotion 里做圆形遮罩需要透明通道用 CSS 做圆形裁切数字人叠加在其它视频/内容之上WebM透明背景需要看到背后的内容全屏数字人MP4 背景标准做法核心结论大多数场景直接用带背景的 MP4只有需要看到数字人背后的内容时才用 WebM。注意WebM 只支持normal和closeUp两种avatar_style不支持circle。需要圆形构图时在 Remotion 中用 CSSborder-radius: 50%实现。两个端点的结构差异详见 video-generation.md端点格式用途/v2/video/generateMP4标准——带背景的视频最常用/v1/video.webmWebM透明背景——仅当需要露出背景时使用WebM 端点使用与/v2/video/generate完全不同的请求结构扁平字段而非video_inputs数组且要求avatar_pose_id必填input_textvoice_id或input_audio二者必居其一不能同时提供。四、并行开发工作流不要干等 15 分钟HeyGen 视频生成通常需要10-15 分钟甚至更久最佳实践是让生成与合成开发并行推进先发起 HeyGen 生成——把返回的video_id存到文件立即退出并行搭建 Remotion 合成——先用占位素材或直接使用数字人的preview_video_url一段短视频循环搭建完成后轮询 HeyGen 状态把占位素材替换为真实视频 URL。两个实用技巧估算时长按约 150 词/分钟的语速估算wordCount / 150 * 60 * fps即为近似总帧数组件设计让动效组件在有无数字人视频两种情况下都能独立工作这样动效可以先脱离视频单独测试。这一思路与仓库中的 TitledVideo.tsx 一致——它把衬线标题叠加组件与底层视频解耦视频未就绪时组件仍可单独渲染测试。五、尺寸对齐HeyGen 输出必须匹配 Remotion 画布关键原则HeyGen 输出分辨率必须与 Remotion 合成画布完全一致否则会出现拉伸、裁切或黑边。5.1 通用尺寸预设// HeyGen 与 Remotion 共用的尺寸常量 const DIMENSIONS { landscape_1080p: { width: 1920, height: 1080 }, landscape_720p: { width: 1280, height: 720 }, portrait_1080p: { width: 1080, height: 1920 }, portrait_720p: { width: 720, height: 1280 }, square_1080p: { width: 1080, height: 1080 }, square_720p: { width: 720, height: 720 }, } as const; type DimensionPreset keyof typeof DIMENSIONS;5.2 按预设生成 HeyGen 视频async function generateHeyGenVideo( script: string, avatarId: string, voiceId: string, preset: DimensionPreset ): Promisestring { const dimension DIMENSIONS[preset]; 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({ video_inputs: [ { character: { type: avatar, avatar_id: avatarId, avatar_style: normal, }, voice: { type: text, input_text: script, voice_id: voiceId, }, background: { type: color, value: #00FF00, // 绿幕用于后续合成 }, }, ], dimension, }), }); const { data } await response.json(); return data.video_id; }5.3 Remotion 合成画布设置// remotion-composer/src/Root.tsx import { Composition } from remotion; import { AvatarComposition } from ./AvatarComposition; const DIMENSIONS { landscape_1080p: { width: 1920, height: 1080 }, // ... 与上方一致 }; export const RemotionRoot: React.FC () { return ( Composition idAvatarVideo component{AvatarComposition} durationInFrames{300} // 后续改为动态计算 fps{30} width{DIMENSIONS.landscape_1080p.width} height{DIMENSIONS.landscape_1080p.height} defaultProps{{ avatarVideoUrl: , }} / / ); };尺寸约束与建议来自 dimensions.mdHeyGen 自定义尺寸限制任一边最小128px、最大4096px且宽高都必须是偶数分辨率影响配额消耗1080p 约为 720p 的 1.5 倍成本建议草稿用 720p、终稿用 1080p平台推荐YouTube 用 1920×108016:9、TikTok/Reels/Shorts 用 1080×19209:16、Instagram 信息流用 1080×10801:1。六、为 Remotion 生成数字人视频6.1 标准方案带背景的 MP4大多数 Remotion 合成用 MP4 背景最合适动效与图形叠加在上层即可async function generateAvatarForRemotion( script: string, avatarId: string, voiceId: string, options: { style?: normal | closeUp | circle; backgroundColor?: string; } {} ): Promisestring { const { style normal, backgroundColor #1a1a2e } options; 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({ video_inputs: [{ character: { type: avatar, avatar_id: avatarId, avatar_style: style, }, voice: { type: text, input_text: script, voice_id: voiceId, }, background: { type: color, value: backgroundColor, }, }], dimension: { width: 1920, height: 1080 }, }), }); const { data } await response.json(); return data.video_id; }6.2 透明背景方案WebM仅在需要看到数字人背后的内容时使用例如数字人叠加在屏幕录制上// 使用 /v1/video.webm 端点获取透明背景 // 注意该端点结构与 /v2/video/generate 不同 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, // 必填数字人姿态 ID avatar_style: normal, // 必填仅支持 normal 或 closeUp input_text: script, // 必填与 voice_id 搭配 voice_id: voiceId, // 必填与 input_text 搭配 dimension: { width: 1920, height: 1080 }, }), });请求体字段速查表字段必填说明avatar_pose_id✓数字人姿态 ID来自数字人详情avatar_style✓仅normal或closeUp不支持 circleinput_text✓*脚本文本不使用input_audio时必填voice_id✓*音色 ID与input_text搭配input_audio✓*音频 URL不使用input_text时必填dimension默认 1280×720WebM 视频与 MP4 使用同一套状态轮询端点只是完成后返回的video_url是.webm文件。七、在 Remotion 中使用数字人视频7.1 关键渲染必须用 OffthreadVideo始终使用OffthreadVideo而不是Video来播放 HeyGen 数字人视频。基础Video组件依赖浏览器的视频解码器帧不精确渲染时会产生抖动jitter。OffthreadVideo通过 FFmpeg 提取帧保证平滑、精确的播放。OffthreadVideo属于remotion核心包无需额外安装。基本用法// remotion-composer/src/AvatarComposition.tsx import { OffthreadVideo, useVideoConfig } from remotion; interface AvatarCompositionProps { avatarVideoUrl: string; } export const AvatarComposition: React.FCAvatarCompositionProps ({ avatarVideoUrl, }) { return ( div style{{ flex: 1, backgroundColor: #1a1a2e }} OffthreadVideo src{avatarVideoUrl} style{{ width: 100%, height: 100%, objectFit: contain, }} / /div ); };仓库中的实际印证无论是 TalkingHead.tsx 的数字人底层视频还是 TitledVideo.tsx 的全屏背景视频都统一使用OffthreadVideo而不是Video。7.2 透明 WebM 叠加推荐使用/v1/video.webm输出的 WebM 时无需绿幕抠像透明通道直接生效import { OffthreadVideo, AbsoluteFill, Sequence } from remotion; export const AvatarWithMotionGraphics: React.FC{ avatarWebmUrl: string } ({ avatarWebmUrl }) { return ( AbsoluteFill {/* Layer 1: 背景/内容 */} AbsoluteFill style{{ backgroundColor: #1a1a2e }} YourMotionGraphics / /AbsoluteFill {/* Layer 2: 透明背景数字人 - 用 OffthreadVideo 保证帧精确 */} OffthreadVideo src{avatarWebmUrl} transparent style{{ position: absolute, bottom: 0, right: 0, width: 50%, height: auto, }} / {/* Layer 3: 叠加在数字人上层的动效 */} Sequence from{30} AnimatedTitle textWelcome! / /Sequence /AbsoluteFill ); };7.3 Loom 风格屏幕录制上的圆形数字人closeUp风格 WebM在 Remotion 中用 CSS 圆形遮罩import { OffthreadVideo, AbsoluteFill } from remotion; export const LoomStyleComposition: React.FC{ screenRecordingUrl: string; avatarWebmUrl: string; // 通过 /v1/video.webm 以 avatar_style: closeUp 生成 } ({ screenRecordingUrl, avatarWebmUrl }) { return ( AbsoluteFill {/* 屏幕录制铺满全屏 */} OffthreadVideo src{screenRecordingUrl} style{{ width: 100%, height: 100% }} / {/* 圆形遮罩数字人 - 透明背景让屏幕透出 */} OffthreadVideo src{avatarWebmUrl} transparent style{{ position: absolute, bottom: 40, left: 40, width: 180, height: 180, borderRadius: 50%, // CSS 圆形遮罩 overflow: hidden, objectFit: cover, }} / /AbsoluteFill ); };再次强调WebM 不支持circle风格必须用normal或closeUp圆形裁切交给 CSS 完成。7.4 遗留方案绿幕 色度键不推荐若手上只有绿幕背景的 MP4不推荐请优先使用 WebM// 注意真正的色度键需要 WebGL 或后期处理 // WebM 透明背景要简单得多 OffthreadVideo src{avatarVideoUrl} style{{ mixBlendMode: multiply, // 仅基础合成 }} /7.5 多层合成模板import { OffthreadVideo, Sequence, useVideoConfig, Img } from remotion; interface LayeredAvatarProps { avatarVideoUrl: string; backgroundUrl: string; logoUrl: string; title: string; } export const LayeredAvatarComposition: React.FCLayeredAvatarProps ({ avatarVideoUrl, backgroundUrl, logoUrl, title, }) { const { fps } useVideoConfig(); return ( div style{{ position: relative, width: 100%, height: 100% }} {/* Layer 1: 背景 */} Img src{backgroundUrl} style{{ position: absolute, width: 100%, height: 100%, objectFit: cover, }} / {/* Layer 2: 数字人视频 - 用 OffthreadVideo 防止抖动 */} OffthreadVideo src{avatarVideoUrl} style{{ position: absolute, bottom: 0, right: 0, width: 40%, height: auto, }} / {/* Layer 3: 标题1 秒后出现 */} Sequence from{fps} div style{{ position: absolute, top: 50, left: 50, color: white, fontSize: 48, fontWeight: bold, }} {title} /div /Sequence {/* Layer 4: Logo */} Img src{logoUrl} style{{ position: absolute, top: 20, right: 20, width: 100, height: auto, }} / /div ); };7.6 素材路径解析当数字人视频 URL 可能为空或需要本地回退时可参考仓库的 resolveAsset.ts它统一处理三类素材来源——远程 URLhttp(s)://、data:直接放行、绝对文件路径Unix 与 Windows 路径均归一化为file://、public/目录下的相对资源转staticFile()。合成组件的videoSrc统一经它解析保证开发预览与命令行渲染行为一致。八、完整端到端工作流8.1 生成并合成import { bundle } from remotion/bundler; import { renderMedia, selectComposition } from remotion/renderer; async function generateAvatarVideoForRemotion( script: string, outputPath: string ) { // 1. 生成 HeyGen 视频 console.log(Generating HeyGen avatar video...); const videoId await generateHeyGenVideo( script, josh_lite3_20230714, 1bd001e7e50f421d891986aad5158bc8, landscape_1080p ); // 2. 等待完成 console.log(Waiting for HeyGen video...); const avatarVideoUrl await waitForVideo(videoId); console.log(HeyGen video ready: ${avatarVideoUrl}); // 3. 读取视频时长换算为 Remotion 帧数 const avatarDuration await getVideoDuration(avatarVideoUrl); const durationInFrames Math.ceil(avatarDuration * 30); // 30 fps // 4. 打包 Remotion 工程 console.log(Bundling Remotion project...); const bundleLocation await bundle({ entryPoint: ./remotion/src/index.ts, }); // 5. 选中合成 const composition await selectComposition({ serveUrl: bundleLocation, id: AvatarVideo, inputProps: { avatarVideoUrl, }, }); // 6. 渲染成片 console.log(Rendering final composition...); await renderMedia({ composition: { ...composition, durationInFrames, }, serveUrl: bundleLocation, codec: h264, outputLocation: outputPath, inputProps: { avatarVideoUrl, }, }); console.log(Final video rendered: ${outputPath}); return outputPath; }轮询实现可参考 video-status.md 的规范状态流转为pending → processing → completed / failedcompleted时返回video_url同时带thumbnail_url、duration、captioned_video_url、subtitle_url等元数据若 MCP 工具可用mcp__heygen__get_video优先使用它替代手写轮询。8.2 用 calculateMetadata 实现动态时长数字人视频时长事先未知正确做法是用calculateMetadata在渲染前探测视频真实时长// remotion-composer/src/AvatarComposition.tsx import { CalculateMetadataFunction } from remotion; export const calculateAvatarMetadata: CalculateMetadataFunction AvatarCompositionProps async ({ props }) { // 从 HeyGen 视频读取时长 const duration await getVideoDurationInSeconds(props.avatarVideoUrl); return { durationInFrames: Math.ceil(duration * 30), fps: 30, width: 1920, height: 1080, }; }; // 在 Root.tsx 中注册 Composition idAvatarVideo component{AvatarComposition} calculateMetadata{calculateAvatarMetadata} defaultProps{{ avatarVideoUrl: , }} /仓库的实战对照在 TitledVideo.tsx 中calculateTitledVideoMetadata通过remotion/media-utils的getVideoMetadata()探测源视频真实时长并换算为帧数Math.round(meta.durationInSeconds * 30)探测失败时回退到 60 秒兜底Root.tsx 中Explainer、CinematicRenderer等合成同样注册了calculateMetadata。这套模式正是数字人类合成动态时长的标准做法。九、最佳实践清单9.1 绿幕用于灵活合成需要后期合成时让 HeyGen 输出纯绿背景#00FF00background: { type: color, value: #00FF00, // 纯绿供色度键使用 }但优先选 WebM 透明背景它比绿幕抠像简单可靠得多。9.2 帧率匹配HeyGen 默认25 fps设置 Remotion fps 时要考虑对齐// 方案 1与 HeyGen 的 25 fps 对齐 fps: 25 // 方案 2使用 30 fps 并微调播放速率 OffthreadVideo src{avatarVideoUrl} playbackRate{25/30} // 轻微放慢以对齐 /9.3 URL 直用 vs 本地下载直接使用 URL 的场景在 Remotion Studio 中预览npm run dev/npx remotion studioURL 在渲染完成前不会过期开发期需要快速迭代。// 直接使用 URL - 开发期更简单快速 OffthreadVideo src{avatarVideoUrl} /先下载再用的场景URL 会过期HeyGen 的 URL 大约24 小时后失效渲染将在之后进行或需要重复渲染网络可靠性是顾虑需要离线渲染。// 带重试的可靠下载 async function downloadVideoWithRetry( url: string, outputPath: string, maxRetries 5 ): Promisestring { for (let attempt 0; attempt maxRetries; attempt) { try { const response await fetch(url); if (!response.ok) throw new Error(HTTP ${response.status}); const buffer await response.arrayBuffer(); await fs.promises.writeFile(outputPath, Buffer.from(buffer)); return outputPath; } catch (error) { const delay 2000 * Math.pow(2, attempt); console.log(Retry ${attempt 1}/${maxRetries} in ${delay}ms...); await new Promise((r) setTimeout(r, delay)); } } throw new Error(Download failed after retries); } // 在 Remotion 中使用本地文件 const localPath await downloadVideoWithRetry(avatarVideoUrl, ./public/avatar.mp4);混合方案生产环境推荐// 同时保存 URL 与本地路径到元数据 const metadata { videoUrl: result.video_url, // 快速预览用 localPath: ./public/avatar.mp4, // 可靠渲染用 expiresAt: Date.now() 24 * 60 * 60 * 1000, // URL 过期时间 }; // 组件内本地文件存在则优先使用 const videoSrc fs.existsSync(localPath) ? staticFile(avatar.mp4) : avatarVideoUrl;9.4 数字人位置预设const AVATAR_POSITIONS { fullscreen: { width: 100%, height: 100%, position: center }, bottomRight: { width: 40%, bottom: 0, right: 0 }, bottomLeft: { width: 40%, bottom: 0, left: 0 }, pictureInPicture: { width: 25%, bottom: 20, right: 20 }, leftThird: { width: 33%, left: 0, height: 100% }, };仓库中的位置预设思路可进一步参考 TalkingHead.tsx 的POSITION_STYLES——它为 9:161080×1920画布定义了lower_third、upper_third、left_panel、right_panel、full_overlay五档叠加层位置并配套 8 帧淡入淡出动画这正是数字人 动态信息层合成的生产级细节。十、输出格式与编码参数HeyGen 输出格式MP4H.264音频AAC分辨率按请求指定Remotion 输出编码器H.264默认、VP8、VP9、ProRes质量设置建议匹配或超过 HeyGen 源素材await renderMedia({ codec: h264, crf: 18, // 高质量 // ... });仓库 package.json 提供了可直接复用的渲染命令npx remotion render src/index.tsx Explainer out/video.mp4对应npm run build开发预览用npm run start即npx remotion studio。十一、故障排查视频在 Remotion 中不播放检查 URL 可访问性CORS 问题确认视频格式兼容性尝试先下载到本地再引用。尺寸不匹配确保 HeyGen 与 Remotion 使用完全相同的尺寸// 共享配置 const VIDEO_CONFIG { width: 1920, height: 1080, fps: 30, }; // HeyGen dimension: { width: VIDEO_CONFIG.width, height: VIDEO_CONFIG.height } // Remotion Composition width{VIDEO_CONFIG.width} height{VIDEO_CONFIG.height} /渲染出现视频抖动数字人视频在成片中抖动或卡顿用OffthreadVideo替换Video——基础Video组件走浏览器解码器帧不精确更新 import无需额外安装属remotion核心包// 之前导致抖动 import { Video } from remotion; // 之后帧精确 import { OffthreadVideo } from remotion;WebM 透明视频加上transparent属性OffthreadVideo src{avatarWebmUrl} transparent /音画不同步核实源视频帧率检查编码问题考虑用一致的设置重新编码。十二、深入阅读数字人技能总览与工具选型.claude/skills/avatar-video/SKILL.mdHeyGen 视频生成完整字段与 WebM 端点.claude/skills/avatar-video/references/video-generation.md状态轮询与下载 URL 规范.claude/skills/avatar-video/references/video-status.md分辨率、宽高比与配额成本.claude/skills/avatar-video/references/dimensions.mdRemotion 合成入口与注册方式remotion-composer/src/Root.tsx、remotion-composer/src/index.tsx数字人叠加合成实现remotion-composer/src/TalkingHead.tsx动态时长计算与素材解析remotion-composer/src/TitledVideo.tsx、remotion-composer/src/lib/resolveAsset.ts【免费下载链接】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),仅供参考