OpenMontage avatar-video 实战:为 HeyGen 数字人视频编写脚本——语速估算、Break 停顿标签与多场景结构
本文基于 OpenMontage 仓库中 avatar-video 技能的核心参考文档 scripts.md,系统讲解如何为 HeyGen AI 数字人(Avatar)视频编写自然、可控、渲染稳定的口播脚本。读完本文,你可以掌握 150 词/分钟的时长估算方法、SSML 风格 <break> 停顿标签的完整语法规则与时长选择标准,并能直接套用产品演示、教程、公告三类脚本模板,完成单场景与多场景数字人视频的文案工程。
1. 脚本在 avatar-video 工作流中的位置
OpenMontage 的 avatar-video 技能围绕 HeyGen 的 /v2/video/generate API 构建,SKILL.md 中定义的默认工作流为五步:
- 列出头像 —
GET /v2/avatars,选择 avatar 并记录avatar_id与default_voice_id; - 列出语音(如需要) —
GET /v2/voices,选择与头像性别、语言匹配的 voice; - 编写脚本 — 组织场景结构,每个场景承载一个概念(本文主题);
- 生成视频 — 按场景提交头像、语音、脚本与背景;
- 轮询状态 —
GET /v2/videos/{video_id}直到状态为completed。
也就是说,脚本写作处于"素材选型之后、云端生成之前"的关键环节:它直接决定视频时长、节奏与可理解性,而一次云端生成通常需要 5–15 分钟,脚本错误在生成后才能暴露,返工成本很高。因此在 OpenMontage 的生产流水线中,这一步由专职角色负责——avatar-spokesperson 管线的 Script Director 明确要求"为口语而写,而非为幻灯片而写"(短句子、直接动词、每拍一个观点、显式转场),并规定"读起来像宣传册的文案必须重写"。这与 scripts.md 的核心原则完全一致:AI 数字人的脚本与真人出镜脚本的需求不同,需要在文本层面就为 TTS 合成做优化。
2. 语速与时长:150 词/分钟估算模型
2.1 基准语速表
脚本时长的规划基线是:正常语速(speed = 1.0x)约为 150 词/分钟。原文档以此作为粗略估计基准,给出如下对应表:
| 脚本词数 | 大致时长 |
|---|---|
| 75 词 | 30 秒 |
| 150 词 | 1 分钟 |
| 300 词 | 2 分钟 |
| 450 词 | 3 分钟 |
| 750 词 | 5 分钟 |
2.2 时长与帧数估算函数
scripts.md 提供了两个 TypeScript 工具函数:由脚本估算视频秒数,以及换算为 Remotion 帧数(默认 30 fps):
// Estimate video duration from script
function estimateDuration(script: string, speed: number = 1.0): number {
const words = script.split(/\s+/).filter(w => w.length > 0).length;
const wordsPerMinute = 150 * speed;
return words / wordsPerMinute * 60; // seconds
}
// Estimate frames for Remotion
function estimateFrames(script: string, fps: number = 30, speed: number = 1.0): number {
const durationSeconds = estimateDuration(script, speed);
return Math.ceil(durationSeconds * fps);
}
两个实现细节值得注意:
- 分词用
\s+空白切分并过滤空串,因此<break time="1s"/>这类标签会被计为一个"词",实际估时长时应以纯口播文本为准,或将标签先行剔除; - speed 参数直接线性缩放词速(
150 * speed),这与 HeyGen 的speed字段语义一致——video-generation.md 的 voice 字段表确认speed取值范围为 0.5–2.0,默认 1.0。
这一 150 词/分钟的估算基线在仓库中是贯穿一致的:remotion-integration.md 在讲解"并行开发工作流"时同样给出 wordCount / 150 * 60 * fps 的近似帧数公式,用于在 HeyGen 视频生成完成(10–15 分钟以上)之前,先把 Remotion 组合的 durationInFrames 定下来。
3. 句式结构与标点控制
3.1 短句优先
AI 语音对短句的处理更自然。原文档给出的量化标准:
| 准则 | 示例 |
|---|---|
| 好:每句 10–20 词 | "Our platform helps teams collaborate. It syncs in real-time across all devices." |
| 避免:30 词以上的连句 | "Our platform helps teams collaborate more effectively by providing real-time synchronization across all devices while also offering offline support and automatic conflict resolution." |
3.2 标点即韵律
标点符号直接参与 TTS 的韵律生成,scripts.md 将其归纳为:
| 标点 | 效果 |
|---|---|
句号 . |
完整停句,自然停顿 |
逗号 , |
短暂停顿 |
问号 ? |
语调上扬 |
感叹号 ! |
强调(应少用) |
省略号 ... |
语气拖尾,轻微停顿 |
这意味着写作时可以"用标点导演"语音:在需要换气的地方落逗号,在需要悬念处用省略号,把真正需要强调的结论句以句号收尾。
4. 使用 <break> 标签精确控制停顿
4.1 标签语法
HeyGen 支持 SSML 风格的 <break> 标签实现精确停顿:
<break time="Xs"/>
其中 X 为秒数(如 0.5s、1s、1.5s、2s)。四条硬性格式规则:
| 规则 | 正确写法 | 错误写法 |
|---|---|---|
| 标签前留空格 | word <break time="1s"/> |
word<break time="1s"/> |
| 标签后留空格 | <break time="1s"/> word |
<break time="1s"/>word |
| 秒数带 "s" 后缀 | <break time="1.5s"/> |
<break time="1500ms"/> |
| 自闭合标签 | <break time="1s"/> |
<break time="1s"></break> |
这些规则在 voices.md 中同样被列为 break 标签的强制要求("Must have space before/after tag"),两处文档互为印证。一个容易被忽视的前置条件:GET /v2/voices 返回的每个 voice 对象都带有 support_pause 布尔字段(见 voices.md 的响应格式),在写依赖 <break> 的脚本前,应确认所选 voice 支持停顿,否则标签可能不生效。
4.2 停顿时长选择标准
| 场景 | 建议停顿 | 示例 |
|---|---|---|
| 问候语之后 | 0.5–1s | Hello! <break time="0.5s"/> Welcome to... |
| 章节之间 | 1–1.5s | ...that's feature one. <break time="1.5s"/> Now let's look at... |
| 关键点之前 | 0.5s | The most important thing is <break time="0.5s"/> consistency. |
| 戏剧效果 | 1.5–2s | And the winner is... <break time="2s"/> you! |
| 提问之后 | 1s | Sound good? <break time="1s"/> Let's get started. |
| 列举条目之间 | 0.5s | First, speed. <break time="0.5s"/> Second, reliability. |
按时长的"听感"分级:
| 时长 | 听感 | 适用 |
|---|---|---|
| 0.3–0.5s | 短促换气 | 分句之间、轻量强调 |
| 0.5–1s | 自然停顿 | 句子断开、转场 |
| 1–1.5s | 刻意停顿 | 章节切换、为关键点铺垫 |
| 1.5–2s | 戏剧化 | 揭晓、重要宣布 |
| 2s 以上 | 长停顿 | 慎用,容易显得不自然 |
4.3 完整脚本示例
原文档给出三段可直接复用的脚本片段,分别覆盖转场、悬念与列举节奏:
// Section transitions
const script = `
Welcome to our product overview. <break time="1s"/>
Today I'll cover three key features. <break time="0.5s"/>
First, let's look at the dashboard. <break time="1.5s"/>
As you can see, it's designed for simplicity. <break time="0.5s"/>
Every action is just one click away.
`;
// Building suspense
const announcement = `
We've been working on something special. <break time="1s"/>
After months of development... <break time="1.5s"/>
I'm excited to announce <break time="0.5s"/> our new AI assistant.
`;
// List with rhythm
const features = `
Our platform offers three core benefits. <break time="0.5s"/>
Speed. <break time="0.5s"/>
Reliability. <break time="0.5s"/>
And simplicity. <break time="1s"/>
Let me show you each one.
`;
注意模板字符串中的空行:它们只影响源码可读性,口播文本由分词规则处理;真正决定停顿的是标签本身。
4.4 连续 break 的合并规则
多个相邻的 <break> 会被合并为一次总时长停顿,而不是叠加两次处理:
// These two breaks:
"Hello <break time=\"1s\"/> <break time=\"0.5s\"/> world"
// Are treated as a single 1.5s pause
这一行为在 voices.md 的 "Consecutive Breaks" 小节有相同描述("Multiple consecutive break tags are automatically combined"),可作为稳定行为理解。
5. 脚本结构模板
原文档按视频时长给出三类带占位符的完整模板,均内置 break 标签,可直接替换 [...] 占位后使用。
5.1 产品演示(60 秒,约 150 词)
const productDemo = `
Hi, I'm [Name], and I'm excited to show you [Product]. <break time="1s"/>
[Product] helps you [main benefit] in just [timeframe]. <break time="0.5s"/>
Here's how it works. <break time="1s"/>
First, [step 1]. <break time="0.5s"/>
Then, [step 2]. <break time="0.5s"/>
And finally, [step 3]. <break time="1s"/>
What used to take [old time] now takes [new time]. <break time="0.5s"/>
Ready to get started? <break time="0.5s"/>
Visit [website] today.
`;
结构是"自我介绍 → 核心利益 → 三步用法 → 前后对比 → CTA",与 Script Director 推荐的 hook / value / proof / CTA 分段逻辑一致。
5.2 教程引言(90 秒,约 225 词)
const tutorial = `
Welcome to this tutorial on [topic]. <break time="0.5s"/>
I'm [Name], and I'll guide you through everything you need to know. <break time="1s"/>
By the end of this video, you'll be able to [outcome 1], [outcome 2], and [outcome 3]. <break time="1s"/>
Let's start with the basics. <break time="1.5s"/>
[Section 1 content - 2-3 sentences] <break time="1s"/>
Now that you understand [concept], let's move on to [next topic]. <break time="1.5s"/>
[Section 2 content - 2-3 sentences] <break time="1s"/>
And finally, let's cover [last topic]. <break time="1.5s"/>
[Section 3 content - 2-3 sentences] <break time="1s"/>
That's everything you need to get started. <break time="0.5s"/>
If you have questions, leave a comment below. <break time="0.5s"/>
Thanks for watching!
`;
注意章节间统一使用 1.5s 的"刻意停顿"(对应 4.2 表中"章节切换"档),而段落内部用 0.5–1s。
5.3 公告(30 秒,约 75 词)
const announcement = `
Big news! <break time="0.5s"/>
We're thrilled to announce [announcement]. <break time="1s"/>
This means [benefit 1] and [benefit 2] for all our users. <break time="0.5s"/>
Starting [date], you'll be able to [new capability]. <break time="1s"/>
Head to [location] to learn more. <break time="0.5s"/>
We can't wait to hear what you think!
`;
6. 面向 AI 语音的写作规范
6.1 应该做
- 口语化写作 —— 大声朗读一遍检验流畅度;
- 使用缩略形式 —— "We're" 而非 "We are","It's" 而非 "It is";
- 拆分长句 —— 在自然停顿点断开;
- 拼写展开缩写 —— "API" 可能被读成 "a pee eye";
- 用停顿制造强调 —— 引导听者注意力;
- 明确收尾每个章节 —— 不要在思路中途淡出。
6.2 应避免
- 无上下文的行话 —— 技术术语需要解释;
- 冗长的插入语 —— 拆成独立句子;
- 发音歧义词 —— 如 "read"(现在时 / 过去时);
- 过量感叹号 —— 全文通常一个就够;
- 连珠炮长句 —— 拆成可消化的小块;
- 信息密度过高 —— 用停顿把事实拉开间距。
6.3 发音提示技巧
对可能被误读的词,采用"音素展开"或括号注音的方式写入脚本:
// Technical terms
const script1 = "Our API (A-P-I) handles authentication...";
// Ambiguous words
const script2 = "I read (red) the documentation yesterday...";
// Brand names
const script3 = "Welcome to HeyGen (hey-jen)...";
这与仓库中 voice-performance-director 技能的做法一致——voice-performance-director.md 在供应商脚本中也直接内嵌了 <break time="0.6s"/> 这类停顿标记,说明"文本即表演指令"是该仓库统一的脚本工程思路。
7. 多场景脚本
当脚本跨场景切分(用于不同背景或不同 avatar)时,每个场景对应 video_inputs 数组中的一个对象,脚本写在各场景自己的 input_text 中:
const multiSceneVideo = {
video_inputs: [
{
// Scene 1: Introduction
character: { type: "avatar", avatar_id: "josh_lite3_20230714", avatar_style: "normal" },
voice: {
type: "text",
input_text: "Welcome to our quarterly update. <break time=\"1s\"/> I'm Josh, and I'll walk you through the highlights.",
voice_id: "voice_id_here",
},
background: { type: "color", value: "#1a1a2e" },
},
{
// Scene 2: Main content (different background)
character: { type: "avatar", avatar_id: "josh_lite3_20230714", avatar_style: "normal" },
voice: {
type: "text",
input_text: "Let's start with revenue. <break time=\"0.5s\"/> We grew 25 percent quarter over quarter. <break time=\"1s\"/> Here's what drove that growth.",
voice_id: "voice_id_here",
},
background: { type: "image", url: "https://..." },
},
// ... more scenes
],
};
请求结构中 video_inputs 为 1–50 个场景的数组,input_text 在 voice.type 为 "text" 时必填——这些字段约束与 video-generation.md 的 "Request Fields" 表一致。
场景转场的四条写作建议:
- 每个场景以完整的意思结尾,不要在场景边界切断句子;
- 新场景以简短上下文开场,让听者快速定位;
- 全片保持语气一致;
- 场景开头使用停顿,给画面(新背景)留出被"看见"的时间。
最后一条在多场景模板中可以直接看到:Scene 2 的 input_text 在主题句后紧跟 0.5s 停顿,正是为了给背景切换留出听觉空间。
8. 生成前的脚本测试
在提交完整视频生成任务前,原文档给出四步检查清单:
- 大声朗读 —— 计时并检查拗口表达;
- 数词 —— 用第 2 节的 150 词/分钟模型验证预期时长;
- 检查 break 标签 —— 确认前后空格与语法(4.1 节四条规则);
- 短片段预览 —— 对发音没把握时,先生成一段约 10 秒的测试视频。
对应的测试代码取脚本前两句,用 720p 低分辨率生成(更快、更省资源):
// Test a small portion first
const testScript = script.split('.').slice(0, 2).join('.') + '.';
const testVideoId = await generateVideo({
video_inputs: [{
character: { type: "avatar", avatar_id: avatarId, avatar_style: "normal" },
voice: { type: "text", input_text: testScript, voice_id: voiceId },
}],
dimension: { width: 1280, height: 720 }, // Lower res for test
});
补充两点仓库内的配套实践:video-generation.md 指出请求顶层支持 test: true 测试模式(输出带水印、不消耗 credit),可叠加使用;而 remotion-integration.md 建议开发时用 avatar 的 preview_video_url 短视频占位,与正式生成任务并行推进。
9. 语速调节:speed 参数
语速在 voice 配置中通过 speed 字段调节:
voice: {
type: "text",
input_text: script,
voice_id: "voice_id",
speed: 1.1, // Slightly faster (range: 0.5 - 2.0)
}
| 语速 | 效果 | 适用场景 |
|---|---|---|
| 0.8–0.9 | 更慢、更从容 | 复杂主题、年长受众 |
| 1.0 | 正常 | 通用 |
| 1.1–1.2 | 稍快 | 有活力的内容、年轻受众 |
| 1.3 以上 | 快 | 慎用,可能牺牲清晰度 |
从源码结构看,speed 的有效范围 0.5–2.0(默认 1.0) 由 video-generation.md 的 voice 字段表定义;同一字段表还定义了 pitch(-20 到 20,默认 0),但 scripts.md 只覆盖 speed——更完整的语音配置(语言过滤、性别匹配、support_pause / emotion_support 特性筛选、自定义音频替代 TTS 等)应参照 voices.md。
10. 小结与延伸阅读
scripts.md 给出的是一套"文本层导演术":以 150 词/分钟规划时长,用短句和标点控制基础韵律,用 <break> 标签叠加精确停顿,用占位符模板快速产出 30–90 秒的成片脚本,再用小片段预览和 speed 微调兜底。把它放回 avatar-video 技能 的整体工作流中,脚本写作是连接"选头像、选语音"与"生成、轮询"之间的核心创作环节,也是多场景视频能否自然衔接的决定因素。
相关文档索引:
- SKILL.md — avatar-video 技能总览与五步工作流
- voices.md — 语音列表、speed/pitch、break 规则、自定义音频
- video-generation.md —
/v2/video/generate请求字段与脚本长度限制 - remotion-integration.md — 由脚本帧数估算驱动 Remotion 组合时长
- Script Director — 生产流水线中的脚本质量门槛
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00