首页
/ OpenMontage 中 HeyGen 数字人视频与 Remotion 合成集成实战:从 /v2/video/generate 到帧精确渲染

OpenMontage 中 HeyGen 数字人视频与 Remotion 合成集成实战:从 /v2/video/generate 到帧精确渲染

2026-09-05 16:40:43作者:郜逊炳

本篇基于 OpenMontage 仓库中 avatar-video 技能包下的参考文档 remotion-integration.md,系统讲解如何调用 HeyGen 生成数字人(avatar)视频,并将其以帧精确的方式嵌入 Remotion 合成工程中。读完后你将掌握:MP4 背景版与 WebM 透明版两种输出格式的选择依据、尺寸/帧率对齐方法、OffthreadVideo 的帧精确渲染原理、calculateMetadata 动态时长方案,以及完整的“生成—轮询—bundle—渲染”生产工作流。

1. 集成定位与整体工作流

该参考文档是 avatar-video 技能(SKILL.md)的“Integration”部分,专门回答一个问题:HeyGen 生成的数字人视频如何进入 Remotion 程序化合成流水线。在 OpenMontage 中,Remotion 工程位于 remotion-composer 目录,其 Root.tsx 注册了 TalkingHeadExplainerCinematicRenderer 等多个 Composition,其中 TalkingHead 合成正是“数字人视频 + 叠加层 + 字幕”的三层结构,与本文档描述的合成模式一致。

典型工作流四步:

  1. 调用 HeyGen 生成数字人视频;
  2. 轮询状态直至完成,获取视频 URL;
  3. 下载视频,或直接在 Remotion 中引用 URL;
  4. 在 Remotion 中与其他元素(背景、叠加层、动效)合成。

快速上手

// 1. Get avatar with default voice
const avatar = await getAvatarDetails(avatarId);

// 2. Generate video (MP4 with background - most common)
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. Poll for completion (10-15+ min)
// 4. Use in Remotion with motion graphics overlaid on top

生成接口为 POST https://api.heygen.com/v2/video/generate,请求需携带 X-Api-Key 头(技能包的 frontmatter 声明了环境变量要求 HEYGEN_API_KEY)。完整的请求字段表、多场景视频与 video_inputs 结构见同目录参考文档 video-generation.md;轮询实现、状态类型与下载重试见 video-status.md

注意区分:仓库中的 heygen_video.py 是一个以 HeyGen 为通道调度 VEO/Sora/Kling 等模型的云端视频生成工具,与本文讨论的 HeyGen 原生 avatar 接口是两回事;本地的照片驱动说话头工具则见 talking_head.py(基于 SadTalker)。avatar 集成工作流完全走 avatar-video 技能包的 HTTP API 路径。

2. 选择正确的输出格式:MP4 背景版 vs WebM 透明版

这是本集成中最关键的一个决策。参考文档给出的选择矩阵:

你的合成形态 推荐格式 原因
数字人作为主讲人,动效叠加在其上 MP4 + 背景色 更简单,叠加层直接放上层
Loom 风格(数字人悬浮于录屏之上) WebM + closeUp,Remotion 中加遮罩 需要透明背景,用 CSS 做圆形遮罩
数字人叠加在其他视频/内容之上 WebM(透明) 需要“看穿”到数字人背后的内容
全屏数字人 MP4 + 背景色 标准做法

多数场景直接用带背景的 MP4;只有当需要透过数字人看到其背后内容时才用 WebM。两个端点的差异:

  • POST /v2/video/generate → 输出 MP4,支持 normal / closeUp / circle 三种 avatar_style
  • POST /v1/video.webm → 输出透明 WebM,仅支持 normalcloseUp(圆形取景需在 Remotion 中用 CSS border-radius: 50% 实现)。

/v1/video.webm/v2/video/generate 的请求结构不同:前者是扁平字段(avatar_pose_idavatar_styleinput_textvoice_id 等),字段约束与“input_text + voice_id 二选一搭配 input_audio”的规则见 video-generation.md 的 WebM 章节。

3. 并行开发工作流:不要干等 10–15 分钟

HeyGen 视频生成通常需要 10–15 分钟以上video-status.md 给出的超时建议是 15–20 分钟)。文档推荐的工作方式是提交即退出、并行开发

  1. 启动 HeyGen 生成 — 把 video_id 存到文件,进程立即退出(video-status.md 中的“Resumable Status Checking”章节给出了 pending-video.json 存状态 + 稍后查询的完整实现);
  2. 搭建 Remotion 合成 — 使用占位视频,或数字人的 preview_video_url(一段短循环片段);
  3. 定期查询 HeyGen 状态 — 构建完成后或周期性轮询;
  4. 就绪后替换占位 — 换成真实视频 URL。

两个实用的工程技巧:

  • 按文稿估算时长:按约 150 词/分钟的语速,wordCount / 150 * 60 * fps 即可得到近似的帧数,用于在视频就绪前就搭好合成骨架;
  • 组件解耦设计:让组件在“有/没有数字人视频”两种状态下都能工作,这样动效部分可以独立测试与预览。

4. 尺寸对齐:HeyGen 与 Remotion 共用一份常量

关键原则:HeyGen 的输出尺寸必须与 Remotion 合成完全一致。 文档给出共享的维度常量:

// Shared dimension constants for both HeyGen and 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;

这套预设与技能包 dimensions.md 的官方分辨率表一致:横屏 16:9(1280×720 / 1920×1080)、竖屏 9:16(720×1280 / 1080×1920)、方形 1:1(720×720 / 1080×1080)。

对应到 Remotion 侧的 Root.tsx 注册:

// remotion/src/Root.tsx
import { Composition } from "remotion";
import { AvatarComposition } from "./AvatarComposition";

export const RemotionRoot: React.FC = () => {
  return (
    <>
      <Composition
        id="AvatarVideo"
        component={AvatarComposition}
        durationInFrames={300} // Will be set dynamically
        fps={30}
        width={DIMENSIONS.landscape_1080p.width}
        height={DIMENSIONS.landscape_1080p.height}
        defaultProps={{ avatarVideoUrl: "" }}
      />
    </>
  );
};

仓库内的真实工程印证了这个模式:Root.tsx 注册 TalkingHead 合成时采用竖屏 1080×1920fps={30},而 TalkingHead.tsx 内部的 POSITION_STYLESlower_thirdleft_panel 等位置预设)正是按 9:16 的 1080×1920 画布坐标设计的——尺寸常量一旦错位,所有像素级定位都会跟着错位。

5. 生成带背景的 MP4:标准生成函数

async function generateHeyGenVideo(
  script: string,
  avatarId: string,
  voiceId: string,
  preset: DimensionPreset
): Promise<string> {
  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", // Green screen for compositing
          },
        },
      ],
      dimension,
    }),
  });

  const { data } = await response.json();
  return data.video_id;
}

封装成面向 Remotion 的生成函数时,把风格与背景色参数化:

async function generateAvatarForRemotion(
  script: string,
  avatarId: string,
  voiceId: string,
  options: {
    style?: "normal" | "closeUp" | "circle";
    backgroundColor?: string;
  } = {}
): Promise<string> {
  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;
}

请求字段补充说明(源自 video-generation.md 的字段表):

  • character.avatar_style 可取 "normal" / "closeUp" / "circle"
  • voice.type"text" 外还支持 "audio"(需 audio_url)与 "silence"(需 duration);speed 取值 0.5–2.0,pitch 取值 -20 到 20;
  • background.type"color" 外还支持 "image" / "video"(用 url + fit 字段);
  • 顶层还支持 test: true 测试模式(不扣额度、带水印)、caption 自动字幕、callback_url Webhook 通知——生产工作流建议开发阶段一律开测试模式。

6. 透明背景 WebM:/v1/video.webm 端点

只有在需要“看到数字人背后的内容”时才用 WebM(例如数字人悬浮在录屏之上):

// Use /v1/video.webm endpoint for transparent background
// Note: Different structure than /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,  // Required: avatar pose ID
    avatar_style: "normal",        // Required: "normal" or "closeUp" only
    input_text: script,            // Required (with voice_id)
    voice_id: voiceId,             // Required (with input_text)
    dimension: { width: 1920, height: 1080 },
  }),
});

注意 avatar_pose_id 来自数字人详情接口(GET /v2/avatar/{avatar_id}/details),avatar_style 只有 normal / closeUp 两个合法值。WebM 与 MP4 共用同一状态查询端点 GET /v2/videos/{video_id},完成后 video_url 指向 .webm 文件。

7. 在 Remotion 中使用 HeyGen 视频:务必使用 OffthreadVideo

核心结论:数字人视频必须用 OffthreadVideo 而非 Video 基础 Video 组件依赖浏览器解码器,渲染时并非帧精确,会产生抖动(jitter);OffthreadVideo 通过 FFmpeg 逐帧抽帧,得到平滑、帧精确的输出。它包含在 remotion 核心包中,无需额外安装。

仓库源码可以直接印证这一实践:TalkingHead.tsx 的第一层就是 OffthreadVideo,并且素材先经过 resolveAsset(videoSrc) 归一化为本地路径(对应后文“先下载再用”策略):

// Layer 1: Video background
<OffthreadVideo
  src={resolveAsset(videoSrc)}
  style={{ width: "100%", height: "100%", objectFit: "cover" }}
/>

基本用法

// remotion/src/AvatarComposition.tsx
import { OffthreadVideo, useVideoConfig } from "remotion";

interface AvatarCompositionProps {
  avatarVideoUrl: string;
}

export const AvatarComposition: React.FC<AvatarCompositionProps> = ({
  avatarVideoUrl,
}) => {
  return (
    <div style={{ flex: 1, backgroundColor: "#1a1a2e" }}>
      <OffthreadVideo
        src={avatarVideoUrl}
        style={{
          width: "100%",
          height: "100%",
          objectFit: "contain",
        }}
      />
    </div>
  );
};

WebM 透明背景(三层结构)

使用 /v1/video.webm 产物时不需要任何色度键(chroma key)处理,加 transparent 属性即可:

import { OffthreadVideo, AbsoluteFill, Sequence } from "remotion";

export const AvatarWithMotionGraphics: React.FC<{
  avatarWebmUrl: string
}> = ({ avatarWebmUrl }) => {
  return (
    <AbsoluteFill>
      {/* Layer 1: Your background/content */}
      <AbsoluteFill style={{ backgroundColor: "#1a1a2e" }}>
        <YourMotionGraphics />
      </AbsoluteFill>

      {/* Layer 2: Avatar with transparent background */}
      <OffthreadVideo
        src={avatarWebmUrl}
        transparent
        style={{
          position: "absolute",
          bottom: 0,
          right: 0,
          width: "50%",
          height: "auto",
        }}
      />

      {/* Layer 3: Overlays on top of avatar */}
      <Sequence from={30}>
        <AnimatedTitle text="Welcome!" />
      </Sequence>
    </AbsoluteFill>
  );
};

Loom 风格:圆形数字人悬浮于录屏之上

closeUp 风格 + WebM,圆形取景在 Remotion 侧用 CSS 实现:

import { OffthreadVideo, AbsoluteFill } from "remotion";

export const LoomStyleComposition: React.FC<{
  screenRecordingUrl: string;
  avatarWebmUrl: string; // Generated with avatar_style: "closeUp" via /v1/video.webm
}> = ({ screenRecordingUrl, avatarWebmUrl }) => {
  return (
    <AbsoluteFill>
      {/* Screen recording fills the frame */}
      <OffthreadVideo src={screenRecordingUrl} style={{ width: "100%", height: "100%" }} />

      {/* Avatar with circular mask - transparent bg shows screen behind */}
      <OffthreadVideo
        src={avatarWebmUrl}
        transparent
        style={{
          position: "absolute",
          bottom: 40,
          left: 40,
          width: 180,
          height: 180,
          borderRadius: "50%", // Circular mask applied in CSS
          overflow: "hidden",
          objectFit: "cover",
        }}
      />
    </AbsoluteFill>
  );
};

再次强调:WebM 不支持 circle 风格,圆形必须靠 borderRadius: "50%" 遮罩。

分层合成(背景图 + 数字人 + 标题 + Logo)

import { OffthreadVideo, Sequence, useVideoConfig, Img } from "remotion";

interface LayeredAvatarProps {
  avatarVideoUrl: string;
  backgroundUrl: string;
  logoUrl: string;
  title: string;
}

export const LayeredAvatarComposition: React.FC<LayeredAvatarProps> = ({
  avatarVideoUrl, backgroundUrl, logoUrl, title,
}) => {
  const { fps } = useVideoConfig();

  return (
    <div style={{ position: "relative", width: "100%", height: "100%" }}>
      {/* Layer 1: Background */}
      <Img src={backgroundUrl} style={{
        position: "absolute", width: "100%", height: "100%", objectFit: "cover",
      }} />

      {/* Layer 2: Avatar video - use OffthreadVideo to prevent jitter */}
      <OffthreadVideo src={avatarVideoUrl} style={{
        position: "absolute", bottom: 0, right: 0, width: "40%", height: "auto",
      }} />

      {/* Layer 3: Title (appears after 1 second) */}
      <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>
  );
};

这种“底层视频 + 中层人物 + 上层动效”的三层结构,与 TalkingHead.tsx 的实现完全同构:Layer 1 是 OffthreadVideo 视频底,Layer 2 是带 Sequence 时间轴的叠加卡片(通过 in_seconds / out_seconds 换算成帧),Layer 3 是最顶层的字幕 CaptionOverlay。仓库还实现了 lower_third / upper_third / left_panel / right_panel / full_overlay 五种位置预设,每个叠加层带 8 帧淡入淡出——这些细节正是“叠加层放在数字人视频之上”这一思路的完整落地。

旧方案:绿幕 + 色度键(不推荐)

若你手里只有绿底 MP4,文档给出的“旧方案”仅是基础混合模式:

// Note: True chroma key requires WebGL or post-processing
// WebM transparent background is much simpler
<OffthreadVideo
  src={avatarVideoUrl}
  style={{ mixBlendMode: "multiply" }} // Basic compositing only
/>

文档明确建议:真正的色度键需要 WebGL 或后处理,优先改用 WebM 透明背景。

8. 完整工作流:生成、轮询、Bundle、渲染

把生成与渲染串起来的端到端函数:

import { bundle } from "@remotion/bundler";
import { renderMedia, selectComposition } from "@remotion/renderer";

async function generateAvatarVideoForRemotion(
  script: string,
  outputPath: string
) {
  // 1. Generate HeyGen video
  console.log("Generating HeyGen avatar video...");
  const videoId = await generateHeyGenVideo(
    script,
    "josh_lite3_20230714",
    "1bd001e7e50f421d891986aad5158bc8",
    "landscape_1080p"
  );

  // 2. Wait for completion
  console.log("Waiting for HeyGen video...");
  const avatarVideoUrl = await waitForVideo(videoId);
  console.log(`HeyGen video ready: ${avatarVideoUrl}`);

  // 3. Get video duration for Remotion
  const avatarDuration = await getVideoDuration(avatarVideoUrl);
  const durationInFrames = Math.ceil(avatarDuration * 30); // 30 fps

  // 4. Bundle Remotion project
  console.log("Bundling Remotion project...");
  const bundleLocation = await bundle({
    entryPoint: "./remotion/src/index.ts",
  });

  // 5. Select composition
  const composition = await selectComposition({
    serveUrl: bundleLocation,
    id: "AvatarVideo",
    inputProps: { avatarVideoUrl },
  });

  // 6. Render final video
  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;
}

其中 waitForVideovideo-status.md 中的轮询实现:每 5 秒查询一次 GET /v2/videos/{video_id},状态为 pending / processing 时继续等待,completed 时返回 video_urlfailed 时抛出 failure_message。状态机四态(pendingprocessingcompleted / failed)以及“状态显示 completed 后 URL 可能还不可立即访问、下载要带指数退避重试”的细节都在该文档中。

动态时长:calculateMetadata

数字人视频的实际时长取决于文稿长度,硬编码 durationInFrames 并不合理。Remotion 的 calculateMetadata 可以在渲染前根据 inputProps 动态计算合成元数据:

// remotion/src/AvatarComposition.tsx
import { CalculateMetadataFunction } from "remotion";

export const calculateAvatarMetadata: CalculateMetadataFunction<
  AvatarCompositionProps
> = async ({ props }) => {
  // Fetch video duration from HeyGen video
  const duration = await getVideoDurationInSeconds(props.avatarVideoUrl);

  return {
    durationInFrames: Math.ceil(duration * 30),
    fps: 30,
    width: 1920,
    height: 1080,
  };
};

// In Root.tsx
<Composition
  id="AvatarVideo"
  component={AvatarComposition}
  calculateMetadata={calculateAvatarMetadata}
  defaultProps={{ avatarVideoUrl: "" }}
/>

这个模式在仓库真实工程中同样是标准做法:Root.tsxExplainer 合成的 calculateMetadata 依据 cuts 的最后一个 out_seconds 计算 durationInFrames(外加 1 秒收尾淡出),CinematicRendererTitledVideo 也各自挂载了 calculateCinematicMetadatacalculateTitledVideoMetadata——可见“按素材动态算时长”是 OpenMontage Remotion 工程的一贯范式。

9. 最佳实践

9.1 用绿幕换取合成灵活性

希望后期合成时,生成阶段直接给绿底:

background: {
  type: "color",
  value: "#00FF00", // Pure green for chroma key
}

(配合 7 节末尾的说明:真色度键成本较高,能走 WebM 透明背景就走 WebM。)

9.2 帧率对齐:HeyGen 默认 25 fps

HeyGen 输出默认 25 fps,Remotion 合成帧率与之不一致时需要显式处理:

// Option 1: Match HeyGen's 25 fps
fps: 25

// Option 2: Use 30 fps with playback rate adjustment
<OffthreadVideo
  src={avatarVideoUrl}
  playbackRate={25/30} // Slow down slightly to match
/>

9.3 URL 直连 vs 先下载

直接用 URL 的适用条件:Remotion Studio 预览(npm run dev)、URL 在渲染完成前不会过期、追求开发期快速迭代:

// Direct URL usage - simpler, faster for dev
<OffthreadVideo src={avatarVideoUrl} />

先下载的适用条件:HeyGen 的 URL 约 24 小时后过期;渲染会延后或重复进行;网络可靠性存疑;需要离线渲染。带指数退避的下载实现:

// Download with retry for reliability
async function downloadVideoWithRetry(
  url: string,
  outputPath: string,
  maxRetries = 5
): Promise<string> {
  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");
}

// Use local file in Remotion
const localPath = await downloadVideoWithRetry(avatarVideoUrl, "./public/avatar.mp4");

混合方案(生产推荐):元数据中同时保存 URL 与本地路径,本地优先:

// Save both URL and local path in metadata
const metadata = {
  videoUrl: result.video_url,           // For quick preview
  localPath: "./public/avatar.mp4",     // For reliable rendering
  expiresAt: Date.now() + 24 * 60 * 60 * 1000, // URL expiration
};

// In Remotion component, prefer local if available
const videoSrc = fs.existsSync(localPath) ? staticFile("avatar.mp4") : avatarVideoUrl;

resolveAsset.ts 在仓库中扮演的正是“URL/本地路径归一化”的角色:TalkingHead 合成入口的 resolveAsset(videoSrc) 保证渲染时拿到的始终是可访问的资源引用。

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%" },
};

10. 输出格式与质量参数

  • HeyGen 输出:MP4(H.264),音频 AAC,分辨率即请求时指定的 dimension
  • Remotion 输出:可选 H.264(默认)、VP8、VP9、ProRes,质量设置应不低于 HeyGen 源:
await renderMedia({
  codec: "h264",
  crf: 18, // High quality
  // ...
});

11. 故障排查

视频在 Remotion 中不播放

  1. 检查 URL 可访问性(CORS 问题);
  2. 确认视频格式兼容;
  3. 先下载到本地再试。

尺寸不匹配 HeyGen 与 Remotion 必须使用完全相同的尺寸,建议共用一份配置:

// Shared config
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} />

渲染时视频抖动

  1. OffthreadVideo 替换 Video——基础 Video 使用浏览器解码器,非帧精确;
  2. 只需改导入(核心包已包含,无需额外安装):
// Before (causes jitter)
import { Video } from "remotion";

// After (frame-accurate)
import { OffthreadVideo } from "remotion";
  1. 透明 WebM 记得加 transparent 属性:<OffthreadVideo src={avatarWebmUrl} transparent />

音画不同步(音频漂移)

  • 核对源视频帧率;
  • 检查是否存在编码问题;
  • 考虑用一致参数重新编码。

12. 小结:把该文档放回仓库语境

这篇参考文档在 avatar-video 技能中承担“Integration”角色,与技能包其他参考文档形成完整闭环:avatars.md 选数字人与默认音色、video-generation.md 管请求构造、video-status.md 管轮询与下载、dimensions.md 管分辨率,而本文聚焦的 remotion-integration 则负责“最后一公里”——把云生成的 MP4/WebM 以帧精确、透明安全、尺寸一致的方式嵌进 Remotion 程序化合成。OpenMontage 的 remotion-composer 工程(OffthreadVideo 底座、位置预设叠加层、calculateMetadata 动态时长)与 talking_head.py 本地工具共同构成了数字人视频从生成到合成的完整技术栈,照本文档的步骤即可复制出一套可运行的 avatar 成片流水线。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384