首页
/ OpenMontage avatar-video 技能详解:HeyGen AI 数字人视频的文字叠加层(Text Overlays)精准控制

OpenMontage avatar-video 技能详解:HeyGen AI 数字人视频的文字叠加层(Text Overlays)精准控制

2026-09-05 10:44:24作者:郜逊炳

本文基于 OpenMontage 仓库中 avatar-video 技能的参考文档 展开,讲解如何在 HeyGen v2 API 生成的 AI 数字人视频中叠加标题、下三分之一(lower third)、行动号召(CTA)等屏幕文字元素。读完本文,你可以完整掌握文字叠加层的数据结构、坐标定位规则、字体样式配置、模板化封装与时间轴对齐方法,并了解它在 OpenMontage 的 Remotion 合成链路中的实际落位方式。

一、文字叠加层在 avatar-video 技能中的定位

OpenMontage 仓库中,.agents/skills/avatar-video/ 是一个面向 AI 编码助手的"数字人视频制作"技能包,其 SKILL.md 定义了标准工作流:

  1. 列出数字人GET /v2/avatars,选定 avatar_iddefault_voice_id
  2. 列出声音GET /v2/voices,为数字人匹配合适音色;
  3. 撰写脚本 — 每个场景承载一个概念;
  4. 生成视频POST /v2/video/generate,逐场景配置数字人、声音、背景;
  5. 轮询状态GET /v2/videos/{video_id} 直至 completed

文字叠加层属于其中的**视频自定义(Video Customization)**环节。技能文档的 Quick Reference 表中明确将其归类为定制能力之一,与背景(backgrounds.md)、字幕(captions.md)并列,所有请求需携带 X-Api-Key 请求头,并从环境变量 HEYGEN_API_KEY 读取密钥。

需要先区分两个易混淆的概念:

能力 内容来源 适用场景
文字叠加层(Text Overlays) 你手动指定文本、位置、样式、出现时间 标题卡、人名条、CTA 等设计性文字
自动字幕(Captions) 由语音自动转录生成 口播内容的听障可访问性、无声播放场景

两者可叠加使用:数字人口播时挂自动字幕,同时用文字叠加层强调章节标题与关键信息。

二、基础用法与 TextOverlay 数据结构

在视频配置中,基础用法是先构建 video_inputs(数字人 + 声音 + 背景),再叠加文字配置。原文档给出的示例骨架如下(文字叠加能力随订阅档位不同而开放):

const videoConfig = {
  video_inputs: [
    {
      character: {
        type: "avatar",
        avatar_id: "josh_lite3_20230714",
        avatar_style: "normal",
      },
      voice: {
        type: "text",
        input_text: "Welcome to our presentation!",
        voice_id: "1bd001e7e50f421d891986aad5158bc8",
      },
      background: {
        type: "color",
        value: "#1a1a2e",
      },
    },
  ],
  // Text overlay configuration (if supported in your API tier)
  // Note: Availability varies by plan
};

单个文字叠加层由 TextOverlay 接口描述,这是整个能力的数据核心:

interface TextOverlay {
  text: string;
  x: number;          // X 坐标(像素或百分比)
  y: number;          // Y 坐标(像素或百分比)
  width?: number;     // 文本框宽度
  height?: number;    // 文本框高度
  font_family?: string;
  font_size?: number;
  font_color?: string;
  background_color?: string;
  text_align?: "left" | "center" | "right";
  duration?: {
    start: number;    // 出现时间(秒)
    end: number;      // 消失时间(秒)
  };
}

关键属性说明:

  • x / y:定位锚点,单位为像素或视频尺寸的百分比,坐标系见下一节;
  • width / height:文本框尺寸,用于控制换行与包裹范围;
  • font_family / font_size / font_color / font_weight / background_color:字体族、字号、字色、字重与文字背景色(半透明背景可显著提升复杂画面上的可读性);
  • text_alignleft / center / right 三档对齐;
  • duration:以为单位的出现/消失时间窗,是文字叠加层与脚本节奏对齐的关键。

三、坐标系与常用定位

坐标系规则

  • 原点:左上角 (0, 0)
  • X 轴:向右增大;
  • Y 轴:向下增大;
  • 单位:像素,或相对视频宽高的百分比。

常用位置速查表(以 1920×1080 为例)

位置 X Y 说明
左上角 50 50 上左侧
顶部居中 960 50 顶部中央
右上角 1870 50 上右侧
正中央 960 540 画面正中
左下 50 1030 下三分之一区域左侧
底部居中 960 1030 下三分之一区域中央

注意该表的取值依赖分辨率:1920×1080 来自 dimensions.md 中 16:9 横屏 1080p 的标准规格。若改用竖屏 1080×1920 或方形 1080×1080,"居中"与"下三分之一"的坐标必须按实际宽高重新计算,不能照抄上表。

位置辅助函数

原文档给出了一个把语义化位置名映射到坐标的辅助函数,可直接复用:

interface Position {
  x: number;
  y: number;
}

function getTextPosition(
  location: "top-left" | "top-center" | "top-right" | "center" | "bottom-left" | "bottom-center" | "bottom-right",
  videoWidth: number,
  videoHeight: number,
  padding: number = 50
): Position {
  const positions: Record<string, Position> = {
    "top-left": { x: padding, y: padding },
    "top-center": { x: videoWidth / 2, y: padding },
    "top-right": { x: videoWidth - padding, y: padding },
    "center": { x: videoWidth / 2, y: videoHeight / 2 },
    "bottom-left": { x: padding, y: videoHeight - padding },
    "bottom-center": { x: videoWidth / 2, y: videoHeight - padding },
    "bottom-right": { x: videoWidth - padding, y: videoHeight - padding },
  };

  return positions[location];
}

这个设计的好处是把"位置语义"与"像素坐标"解耦:换分辨率时只需换 videoWidth / videoHeight 两个入参,padding 默认 50px 用于留出安全边距,避免文字贴边。

四、字体样式配置

样式属性示例

const textStyle = {
  font_family: "Arial",
  font_size: 48,
  font_color: "#FFFFFF",
  font_weight: "bold",
  background_color: "rgba(0, 0, 0, 0.5)",
  text_align: "center",
};

其中 background_color 使用 rgba 半透明黑色是常见手法——文字压在任意背景上都保持对比度,而不需要预判背景明暗。

常用字体族选择

字体 风格 适用场景
Arial 无衬线 干净、通用
Helvetica 无衬线 现代、专业
Times New Roman 衬线 传统、正式
Georgia 衬线 优雅、易读
Roboto 无衬线 现代、数字感
Open Sans 无衬线 亲和、易读性好

五、三种典型叠加模式

原文档给出三类高频模式的完整配置,均可直接复制改造:

1. 标题卡(Title Card)

画面正中、开场 0~3 秒展示的大标题:

const titleOverlay = {
  text: "Product Demo",
  x: 960,
  y: 540,
  font_family: "Arial",
  font_size: 72,
  font_color: "#FFFFFF",
  text_align: "center",
  duration: {
    start: 0,
    end: 3,
  },
};

2. 下三分之一条(Lower Third,人名/头衔)

左下角带半透明蓝底的两行文字,第 2 秒出现、第 8 秒消失:

const lowerThirdOverlay = {
  text: "John Smith\nCEO, Company Inc.",
  x: 100,
  y: 900,
  font_family: "Arial",
  font_size: 36,
  font_color: "#FFFFFF",
  background_color: "rgba(0, 102, 204, 0.9)",
  text_align: "left",
  duration: {
    start: 2,
    end: 8,
  },
};

注意 text 中用 \n 分隔姓名与头衔两行,配合左对齐形成经典的"人名条"版式。

3. 行动号召(Call to Action)

收尾段落的引导文字,用金色(#FFD700)突出:

const ctaOverlay = {
  text: "Visit example.com",
  x: 960,
  y: 1000,
  font_family: "Arial",
  font_size: 42,
  font_color: "#FFD700",
  text_align: "center",
  duration: {
    start: 25,
    end: 30,
  },
};

六、模板化封装:TextOverlayTemplate

为避免每个视频重复调参,原文档定义了一套"模板 + 工厂函数"的封装方式:模板只存样式,位置与时长由调用方注入。

interface TextOverlayTemplate {
  name: string;
  style: Partial<TextOverlay>;
}

const templates: TextOverlayTemplate[] = [
  {
    name: "title",
    style: {
      font_family: "Arial",
      font_size: 72,
      font_color: "#FFFFFF",
      text_align: "center",
    },
  },
  {
    name: "subtitle",
    style: {
      font_family: "Arial",
      font_size: 42,
      font_color: "#CCCCCC",
      text_align: "center",
    },
  },
  {
    name: "lower-third",
    style: {
      font_family: "Arial",
      font_size: 36,
      font_color: "#FFFFFF",
      background_color: "rgba(0, 0, 0, 0.7)",
      text_align: "left",
    },
  },
  {
    name: "caption",
    style: {
      font_family: "Arial",
      font_size: 32,
      font_color: "#FFFFFF",
      background_color: "rgba(0, 0, 0, 0.5)",
      text_align: "center",
    },
  },
];

function createTextOverlay(
  text: string,
  templateName: string,
  position: Position,
  duration?: { start: number; end: number }
): TextOverlay {
  const template = templates.find((t) => t.name === templateName);

  if (!template) {
    throw new Error(`Template "${templateName}" not found`);
  }

  return {
    text,
    x: position.x,
    y: position.y,
    ...template.style,
    duration,
  };
}

四个内建模板覆盖了绝大多数版式需求:

模板名 字号 颜色 背景 对齐 典型用途
title 72 居中 开场标题卡
subtitle 42 #CCCCCC 浅灰 居中 章节副标题
lower-third 36 黑 70% 左对齐 人名/头衔条
caption 32 黑 50% 居中 强调性说明文字

工厂函数在模板名缺失时抛出显式错误,便于在批量生成场景中快速定位配置笔误——这一点与技能 SKILL.md 的"生成前先校验输入"的最佳实践一致。

七、时间轴对齐:让文字跟着脚本走

文字叠加层最容易踩的坑是与口播节奏脱节。原文档的做法是在脚本中先标注时间区间,再为每个区间生成对应叠加层:

// 带时间标记的脚本
const script = `
Hello and welcome. [0:00 - 0:03]
Let me show you our features. [0:03 - 0:08]
First, we have analytics. [0:08 - 0:15]
Get started today! [0:15 - 0:20]
`;

// 与之匹配的文字叠加层
const overlays = [
  {
    text: "Welcome",
    duration: { start: 0, end: 3 },
    ...titleStyle,
  },
  {
    text: "Feature Overview",
    duration: { start: 3, end: 8 },
    ...subtitleStyle,
  },
  {
    text: "Analytics Dashboard",
    duration: { start: 8, end: 15 },
    ...lowerThirdStyle,
  },
  {
    text: "www.example.com",
    duration: { start: 15, end: 20 },
    ...ctaStyle,
  },
];

这里有两点实践细节值得注意:

  • 时间区间首尾相接(0→3→8→15→20),避免同一区域两个叠加层交叉重叠导致文字打架;
  • 口播时长可预估remotion-integration.md 给出了经验公式——按约 150 词/分钟的语速估算视频时长,wordCount / 150 * 60 * fps 可得大致帧数。因此标注脚本时间戳时,可以先按该速率粗排,待视频生成后再微调。

八、最佳实践与能力边界

原文档总结了六条最佳实践:

  1. 可读性 — 文字与背景之间保持足够对比度;
  2. 字号 — 保证在移动设备上依然可读;
  3. 时长 — 给观众留足阅读时间(经验值:至少 3 秒);
  4. 定位 — 不要遮挡数字人的脸部区域;
  5. 一致性 — 全片使用统一的字体与样式;
  6. 无障碍 — 考虑色盲友好的配色方案。

同时明确列出了能力边界(Limitations):

也就是说:把"确定性文字"交给叠加层、把"口播字幕"交给自动字幕、把"复杂动效文字"留给后期/程序化合成,是这套能力划分背后的设计逻辑。

九、仓库纵深:文字叠加层在 OpenMontage 合成链路中的落位

上述内容主要覆盖 HeyGen 侧的"生成时叠加"。从仓库源码结构看,OpenMontage 还有一条合成时叠加的路线,理解两者配合能更完整地把握该技能的用法。

1. 技能包内的交叉引用

avatar-video 技能把文字叠加层定位为"Video Customization"三大件之一(背景 / 文字叠加 / 字幕),见 SKILL.md 的 Reference Files 一节;Quick Reference 表中"Add text overlays → text-overlays.md"一行给出了直达索引。这说明在 Agent 执行视频任务时,文字需求会先路由到本文所讲的参考文档。

2. Remotion 合成路线:叠加层是"第三层"

对于需要复杂动效的文字(打字机效果、弹性入场、逐词高亮等),仓库的推荐做法是:HeyGen 只产出"干净的数字人视频",文字在 Remotion 中作为独立图层合成。remotion-integration.md 中的分层示例把这一思路具体化(约 L277-L307):

<AbsoluteFill>
  {/* Layer 1: 背景/内容 */}
  <AbsoluteFill style={{ backgroundColor: "#1a1a2e" }}>
    <YourMotionGraphics />
  </AbsoluteFill>

  {/* Layer 2: 透明背景数字人(OffthreadVideo 保证逐帧精确) */}
  <OffthreadVideo src={avatarWebmUrl} transparent style={{...}} />

  {/* Layer 3: 数字人之上的文字叠加层,用 Sequence 控制出现帧 */}
  <Sequence from={30}>
    <AnimatedTitle text="Welcome!" />
  </Sequence>
</AbsoluteFill>

对比两种路线,可以得出选型结论:

维度 生成时叠加(本文主体) 合成时叠加(Remotion)
实现位置 HeyGen API 配置 Remotion 组件图层
时间单位 秒(duration.start/end 帧(Sequence from
动效能力 受 API 档位限制 完整(GSAP/CSS/任意 React 动效)
适用场景 静态标题、人名条、CTA 弹性入场、逐词高亮、复杂排版

两个时间系统的换算关系很直接:帧号 = 秒 × fps,例如 from={30} 在 30fps 下即第 1 秒出现,与生成时路线 duration: { start: 1 } 等价。该文档同时强调必须使用 OffthreadVideo 而非 Video(浏览器解码器不逐帧精确,渲染会抖动),这与文字叠加层的帧对齐质量直接相关。

3. 仓库内的字幕叠加组件

从源码结构看,OpenMontage 的 Remotion 工程 remotion-composer/ 已内置文字叠加类组件,如 CaptionOverlayHeroTitleEndTag 等,并在 组件出口文件 中统一导出。可以推断:走合成路线时,"下三分之一条""片尾 CTA"等版式可以直接复用这些组件,而本文第二至七节的坐标、字号、时长规则依然适用——只是坐标从 HeyGen 的像素坐标系转换为 Remotion 的 CSS 定位(position: absolute + top/left),两者共享同一套"原点左上、Y 轴向下"的坐标系心智模型。

十、小结

OpenMontage 的 avatar-video 技能把"数字人视频上的文字"拆成了三层可控能力:数据层TextOverlay 接口的坐标、字体、时长三要素)、版式层(title / subtitle / lower-third / caption 四个模板 + 位置辅助函数)、时间层(与脚本时间戳逐区间对齐)。生成时叠加适合确定性文字,Remotion 合成路线(OffthreadVideo + Sequence + 仓库内置覆盖组件)承接复杂动效,二者按"动效复杂度"分工。掌握本文的数据结构、定位速查表、模板工厂与时间轴对齐方法,即可在 OpenMontage 的 avatar-video 工作流中独立完成标题卡、人名条、CTA 等全部常规文字叠加需求。

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

项目优选

收起
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