📍 无忆研习社 › 开源解码 › Hypit 深度实操指南:用 SVML 语义锚点把短视频做成可复用模板(原理拆解、安装部署、批量变体与国内合规要点)

Hypit 深度实操指南:用 SVML 语义锚点把短视频做成可复用模板(原理拆解、安装部署、批量变体与国内合规要点)

摘要:Hypit把视频从“第几秒”改成“哪个词”,用SVML语义锚定台词与画面,WhisperX词级对齐,HyperFrames渲染,配合编程Agent走通检查、规划、构建、导出全流程;支持批量变体复用、零模型出片,也提醒国内创作者注意版权、肖像声音授权与AI内容标识。从安装命令到SVML语法、数据流、避坑清单一次讲清,适合愿与命令行和Agent协作的人。
字号 100%
行距 2.05
当前可见 60% 的内容
本文由 莫潇羽@无忆研习社(www.wuyi.wiki)撰写,转载请注明出处。
版本提示:本文依据 2026 年 9 月中旬的 Hypit 官方文档整理,写稿当天 GitHub 上的最新发布版本为 v0.1.9。项目迭代很快,文中的 SVML 语法细节(如 span-authority 属性、@/id~ 这类边界吸附写法)和命令行用法可能随版本调整,动手前请先运行 hypit version --check 核对,一切以官方最新文档为准。

快速摘要

Hypit 是一个开源的 AI 视频制作系统,定位是给 Claude Code、Codex 这类“会用技能(Skill)的编程 Agent”提供一套写视频的语言和执行工具。它的核心是 SVML 标记语言:台词写在 Script 里,画面、字幕、特效不再绑定“第几秒”,而是绑定“哪个词、哪句话”。配音或口播录好之后,由 WhisperX 做词级对齐,把语义锚点换算成精确帧,最后交给 HyperFrames 渲染器输出 MP4。安装只需一行 npx skills add hypit-ai/hypit -g,需要 Node.js 22 及以上版本。生成模型是可选项,纯字幕加动态图形的视频可以不调用任何模型。对国内创作者来说,有三件事必须提前知道:语音对齐目前只支持英文和中文;境外模型服务的使用要遵守国内网络与内容管理规定;发布 AI 生成或合成的视频必须按《人工智能生成合成内容标识办法》做标识。

这篇文章不打算把 Hypit 吹成“一键出片神器”。它现在还处在 0.1.x 的早期版本,门槛也不低,更适合愿意和命令行、配置文件打交道的人。我会从“为什么改一句台词要返工半天”这个老问题讲起,一路拆到 SVML 的语法细节、从台词到成片的完整数据流、安装和出片的每一条命令、批量变体怎么复用已有素材、不用模型怎么出片,最后把国内平台发布必须补上的合规功课逐条讲清楚。

想看完整拆解,往下翻。

一、剪辑越做越累,问题其实出在“秒”上

一个几乎人人都经历过的返工场景

先说一个很普通的场景。你做了一条 45 秒左右的知识口播视频,结构是开场抛问题、中间讲三个要点、结尾给行动建议。视频发出去反馈不错,你打算照着同样的节奏再做一期,换个话题。

打开剪辑软件,你会发现能直接复用的东西少得可怜。工程文件可以另存一份,可里面的每一个元素都钉在时间轴上:第 3.2 秒弹出标题卡,第 7.8 秒切到产品特写,第 12 秒开始第二段字幕。新一期的口播只要比上一期多说半句,后面所有东西就会整体错位。字幕要重新对,贴纸要一个个挪,转场位置要重新卡点。

我自己折腾短视频这几年,最大的体会是:真正累人的往往不是“创意”,而是“对齐”。创意想好之后,大量时间耗在把画面、字幕、音效一帧一帧地挪回正确位置上。

时间轴剪辑的底层逻辑

主流的剪辑工具,无论是专业的非线性编辑软件,还是手机上的剪辑应用,底层逻辑都一样:以时间为坐标。所有素材都有“起点秒数”和“持续时长”两个属性,你拖动的每一个片段,本质上都是在修改这两个数字。

这种设计对“一次性作品”很友好,所见即所得,直观。可一旦你想把一条视频变成模板反复用,它的短板就暴露出来了:时间坐标记录的是“结果”,不是“意图”。软件只知道标题卡出现在第 3.2 秒,却不知道你之所以把它放在那里,是因为主播刚好说到了“三个误区”这几个字。

意图丢了,复用就只能靠人工重新理解一遍。下面这张图,是改动一句台词之后,时间轴工程里会发生的连锁反应:

flowchart TD
    A[开场第二句台词多了 1.5 秒] --> B[后续口播整体后移]
    B --> C[字幕块全部错位]
    B --> D[B-roll 切入点对不上]
    B --> E[音效和卡点失效]
    C --> F[逐条手动重新对齐]
    D --> F
    E --> F
    F --> G[重新导出检查]

换一种坐标系:绑定“词”而不是“秒”

如果把坐标系从“秒”换成“词”,情况就完全不同了。你在工程里记录的不再是“第 3.2 秒出标题卡”,而是“主播说到‘三个误区’时出标题卡”。至于“三个误区”这几个字最终落在第几秒,交给程序在配音生成之后自动算。

这样一来,台词改长了、改短了、换了一个主播重新录,只要那几个关键词还在,画面就会自动跟过去。这就是所谓的语义锚定。白话解释一下:锚定就是“拴住”,语义锚定就是把画面元素拴在一句话的意思上,而不是拴在一个时间点上。

我用一张表对比一下两种思路在常见改动下的工作量差异:

改动类型

时间轴思路要做的事

语义锚定思路要做的事

开场台词多加半句

后续字幕、贴纸、切镜全部手动后移

改台词文本,重新对齐后自动换算

换一位主播重录

所有卡点按新语速重新调整

替换口播素材,锚点重新测量

删掉中间一个要点

删除片段后填补空隙、修正后续位置

删掉对应段落,后面自动顺延

竖屏改横屏

所有元素位置和尺寸重新摆

切换画布和布局规则

同一结构换个产品

几乎等于重新剪一遍

替换产品相关文本和素材

这个思路本身并不新。字幕行业里的“强制对齐”技术早就存在,自动化剪辑工具里也有“按关键词触发”的零散功能。Hypit 做的事情,是把这个思路贯彻到整条视频的每一层:字幕、画面叠加、B-roll、配音、合成、渲染,全部围绕同一份台词来组织。

为什么偏偏是现在出现

语义锚定之所以现在才开始变得实用,我认为有两个外部条件成熟了。

第一个条件是词级语音对齐工具足够好用了。以 WhisperX 为代表的开源工具,能给出每个词在音频里的起止时间,而不只是整句的大概位置。没有这一步,“拴在词上”就只是一句空话。

第二个条件是编程 Agent 能读懂结构化文件了。一份包含几十个组件、上百行标记的视频描述文件,让人手写会很痛苦,但让 Agent 去写、去改、去检查,负担就小很多。人只需要用自然语言说“把开头换成更直接的提问”,剩下的交给 Agent 去改文件。

两个条件叠在一起,才让“用写文件的方式做视频”从极客玩具变成了普通创作者也能尝试的方案。

二、Hypit 的真实身份:一套给 Agent 用的视频编译工具

先把“它不是什么”说清楚

第一次听说 Hypit 的人,很容易把它想象成一个网页应用:上传视频,点个按钮,出来一堆新视频。实际并不是这样。

Hypit 没有那种傻瓜式的在线编辑界面作为主入口。它的主要使用方式,是在你本地的编程 Agent 里调用一个名为 hypit 的技能。你和 Agent 对话,Agent 读取 Hypit 提供的制作知识,调用 Hypit 的命令行工具,在你的项目文件夹里生成、修改一组文本文件,再把这些文件编译、渲染成视频。

所以,我更愿意把它理解成一套视频编译工具链。“编译”这个词借用自编程:程序员写的是人能读懂的源代码,编译器把它翻译成机器能执行的程序。Hypit 里,你(或者 Agent)写的是描述视频的源文件,Hypit 把它翻译成真正的 MP4。

拆开看,它由哪几块组成

根据官方文档的描述,Hypit 的结构可以分成下面几个角色。我按“谁负责什么”整理成表:

组成部分

负责的事情

白话理解

Hypit Skill

给 Agent 提供视频制作的知识和工作方法

Agent 的“岗前培训手册”

hypit 命令行包

提供检查、规划、构建、导出等可执行工具

真正干活的“工具箱”

SVML / SVS / SVRUN 文件

分别描述视频内容、视觉样式、构建意图

剧本、化妆手册、开工单

本地 Runtime

管理凭据、服务端点和后台执行进程

片场调度

WhisperX

把口播音频里每个词的时间测出来

场记,记下每句话说在哪一帧

HyperFrames 渲染器

把合成结果逐帧渲染并编码成视频

冲印车间

生成模型(可选)

生成图片、视频片段、配音

外请的摄影师和配音演员

这里有两个开源依赖值得多说一句。

HyperFrames 是 HeyGen 开源的视频渲染框架,采用 Apache 2.0 协议。它的做法是把视频的每一帧描述成网页,用无头浏览器逐帧截取,再用 FFmpeg 编码。“无头浏览器”就是没有界面、在后台运行的浏览器。这种做法的好处是确定性强,同样的输入每次渲染出来的结果一致,很适合自动化批量生产。它对环境的要求是 Node.js 22 及以上和 FFmpeg。

WhisperX 是一个开源语音识别项目,在 OpenAI 的 Whisper 模型基础上,用 wav2vec2 做强制对齐,得到词级时间戳,还能借助 pyannote 做说话人区分。“强制对齐”是指:已知文本内容,让程序去音频里找出每个字词的精确位置。Hypit 正是靠它把“台词”和“真实口播”对上号。

三个入口,对应三种起步方式

Hypit 官方给出了三种开始制作的方式,我按上手难度从低到高重新排一下:

flowchart LR
    subgraph 起步方式
    T[从现成模板开始] 
    D[用文字描述想要的视频]
    R[提供一条参考视频]
    end
    T --> S[生成可编辑的 SVML 项目]
    D --> S
    R --> S
    S --> C[检查与规划]
    C --> B[构建与渲染]
    B --> V[成片 + 可继续修改的源文件]

从模板开始:官方仓库里准备了播客、街头采访、双人对话、视频通话等常见格式的示例工程。新手我最推荐这个入口,因为模板本身就是一份“能跑通的标准答案”,照着改比从零写安全得多。

用文字描述:直接告诉 Agent 你想要什么样的视频,比如时长、风格、开头怎么抓人、结尾引导什么动作,Agent 会自己规划结构、写台词、决定画面方案,再落成 SVML 文件。

提供参考视频:给 Agent 一个本地视频文件或受支持平台的链接,再说明要替换什么,比如换主播、换产品、换语言、换画幅。Agent 会分析参考视频的镜头节奏、字幕落点、图形出现的时机,然后按你的目标改写。官方把这个入口放在最显眼的位置,但我要提前泼一盆冷水:参考视频的版权问题在国内非常敏感,第八章会专门讲。

不管从哪个入口进来,最终得到的都不是一个“只能看不能改”的成片,而是一整套普通文本文件。你随时可以打开来改,改完重新构建。这一点,是它和大多数在线 AI 视频工具最本质的区别。

模型从哪里来:自带密钥还是托管服务

Hypit 本身不绑定任何一家模型厂商。官方文档里提到两种接入方式。

一种是 HypiHub,也就是 Hypit 官方的托管服务,一个账号里集成了托管版 WhisperX,以及图片、视频、语音相关的模型。另一种是 BYOK,全称 Bring Your Own Key,意思是“自带密钥”:你用自己在各家模型平台申请的 API 密钥,通过 Hypit 的 Provider 机制接进来。Provider 可以理解成“适配器”,负责把 Hypit 的统一调用翻译成某家模型平台的接口格式。项目还允许你自己编写 Provider,本地能力和托管能力也可以混着用。

如果选用托管服务,建议先确认其服务端所在地区及数据处理条款。服务端位于境外时,上传含有人脸、人声等个人信息的素材,就涉及个人信息出境的合规判断,这一点在第八章“境外服务”一节会展开讲。

官方示例工程里出现的模型,包括用于生成视频片段的 Seedance、用于生成图片的 GPT Image 系列,以及用于对齐的 WhisperX。需要提醒的是,这些模型大多是境外服务,境外模型使用需遵守国内网络与内容管理相关规定。国内创作者如果想走合规路线,可以关注国内平台正式开放的同类模型接口,比如火山引擎在 2026 年 4 月正式开放的 Seedance 2.0 系列 API,再评估是否需要为它编写或适配 Provider。

还有一点我很认可:官方的 Agent 工作流程里明确要求,在发起任何付费调用之前,Agent 要先向你说明所用账号、计划做哪些工作、可查到的费率或预估成本,以及还不确定的部分,得到你的同意才开跑。账号、范围、预算任何一项变了,都要重新确认。这种“先报价后开工”的设计,对怕被 API 账单吓到的人非常友好。

它现在处在什么阶段

从 GitHub 的 Release 记录看,写稿时 Hypit 仍处在 0.1.x 区间,更新非常频繁。v0.1.8 发布于 2026 年 9 月 14 日,第二天就发布了 v0.1.9。最近几个版本主要在打磨命令行报错提示、长时间准备过程的进度展示、托管服务与自带密钥的连接说明,以及把正式发布流程和 npm 发包打通。

这里有个容易忽略的点:官方说明中,Hypit 的可执行程序和 Hypit Skill 是两份独立的安装,升级时要分别处理。以全局安装为例:

# 升级可执行程序(版本号以官方最新 Release 为准)
npm install --global @hypit/hypit@0.1.9
hypit version --check

# 升级全局安装的 Skill
npx skills update hypit -g

hypit version --check 只报告本机正在运行的版本和仓库里的最新版本,不会自动安装更新,也不会改动你的项目。官方还说明,升级之后已有的视频项目和生成好的素材不需要重新制作。

早期版本意味着两件事。好的一面是,功能在快速补齐,社区反馈能很快被响应。不好的一面是,语法和命令随时可能调整,今天能跑的写法,下个版本也许就要改。所以我的建议是:动手之前先用 hypit version --check 看一眼本地版本和最新版本的差距,遇到文档和实际行为对不上,优先以官方最新文档和 Release 说明为准。

说到这里,Hypit 的“身份”基本清楚了。接下来进入最核心的部分:SVML 到底长什么样,台词和画面是怎么拴在一起的。莫潇羽@无忆研习社 会尽量用中文例子来讲,毕竟官方示例几乎全是英文。

三、读懂 SVML:先写好台词,其他一切跟着台词走

SVML 是什么:先认识“标记语言”

没有编程背景的朋友,看到一堆尖括号可能会发怵。其实“标记语言”的思路非常朴素,我们平时就在用。

写作文时,给书名加上书名号《》,读者就知道这是一本书;编辑改稿时,在某句话下面画波浪线,排版的人就知道这里要加粗。标记语言就是用约定好的符号,给内容贴上“这是什么、该怎么处理”的标签。符号本身不是内容,而是关于内容的说明。

SVML 的全称是 Semantic Video Markup Language,官方文档里直接用“语义视频标记语言”来解释这个缩写。它的标签用尖括号包起来,写法和 XML 一脉相承。一个标签通常由下面几部分组成:

组成部分

例子

白话理解

开始与结束标签

<hook> 和 </hook>

一对“括号”,中间夹着的就是这部分内容

自闭合标签

<pause/>

不夹内容的标签,自己就是一个完整标记

属性

frame-rate="30"

给标签补充的参数,名字等于值

引用

{story.segment.hook}

花括号里写路径,指向别处定义好的东西

导入

<import from="@hypit/script@1"/>

声明“这份文件要用到哪个功能包”

如果你接触过网页制作,会觉得这套写法有点眼熟。网页的结构用 HTML 这种标记语言来写,外观用 CSS 样式表单独描述,SVML 借鉴了类似的分工:内容写在 .svml 里,外观写在 .svs 里。两者真正的区别在于要描述的对象不同。网页主要描述“某一刻页面上的东西怎么摆”,SVML 要描述的是“随着台词一句句展开,画面、字幕、声音之间的先后和对应关系”。也正因为这层区别,SVML 里最核心的组件不是画面,而是台词。

对新手来说,记住一点就够了:你不需要从零手写 SVML。日常工作里,文件主要由 Agent 生成和修改,你要做的是能看懂它大概在描述什么,发现不对时知道该让 Agent 改哪里。下面几节的语法讲解,也按“能看懂”的标准来读就行。

三类文件各管一摊

Hypit 项目里最常打交道的是三种文件,扩展名不同,职责也分得很开:

文件类型

扩展名

装的是什么

类比

Author Source

.svml

视频内容:台词、素材、生成指令、轨道、合成

剧本加分镜

Stylesheet

.svs

视觉规则:颜色、字号、位置、进出场动效

网页的样式表

Run Source

.svrun

这一次要产出什么、复用哪些旧结果

开工单

这种“内容、样式、执行”三分离的设计,好处在批量做变体时会非常明显:换产品只动 .svml 里的文本,换视觉风格只动 .svs,复用上一次生成好的镜头只动 .svrun,三者互不干扰。

SVML 文件内部由很多“组件”串起来,每个组件通过 import 引入一个功能包。整条视频里地位最特殊的,是 <script> 这个组件。

Script 的铁律:只写“说什么”

官方文档对 Script 的定位非常克制:它只装旁白或角色说出口的每一个字,不写时间码、不引用素材、不写样式、不写生成参数。管线里所有其他环节都读取 Script,而 Script 不读取任何其他东西。

我第一次读到这条规则时,觉得有点“洁癖”。后来想明白了,这正是整套系统能复用的前提。台词是一条视频最稳定的“语义骨架”,只要骨架干净,其他东西往上挂、往下拆都不会乱。

一个最小的 Script 长这样:

<import from="@hypit/script@1"/>

<script id="story">
  <opening>
    <HOST> 大家好,今天聊聊视频模板怎么复用。
  </opening>
</script>

import 那一行激活了 Script 功能,id="story" 给这份台词起了个名字,方便其他组件引用。

段落:视频的“章节”

Script 里面由一个个段落(Segment)组成,段落就是按顺序排列的一块块口播内容。它有几个规定需要记住:

  • 标签名本身就是段落的 id,在同一份 Script 里不能重名。
  • 段落不能嵌套,每个段落都必须是 <script> 的直接下级。
  • 可以写成自闭合的空段落,比如 <pause/>,但空段落只代表“有这么个结构”,并不自动等于停顿,也不带默认时长。
  • 命名遵循 XML 规则,可以用字母、数字、连字符和下划线。

我自己的习惯是按“功能”给段落命名,而不是按顺序编号。比如 hook、pain、demo、close,而不是 part1、part2。原因很简单:后面做变体时经常要调换顺序、插入新段落,用功能命名,引用关系一眼就能看懂。

其他组件引用段落时,写法类似 {story.segment.hook};如果要取这个段落的某种文本形式,就写 {story.segment.hook.speech} 这样的路径。

角色提示:谁在说话

多人对话的视频,需要标明每句话是谁说的,这就是角色提示(Role Cue):

<interview>
  <HOST> 你平时做一条视频要多久?
  <GUEST> 口播半小时,剪辑两个多小时。
</interview>

角色提示有几个容易踩的点。它没有闭合标签,一个角色的发言会一直延续到下一个角色提示或段落结束。一个段落里要么全部句子都标角色,要么全都不标,混着写会报错。角色标签长度限制在 1 到 32 个字符。

另外要特别注意,角色提示只是“标注谁在说”,它不会自动选择音色,也不会创建人物。音色和形象是在生成、配音环节另外指定的。

同一段带角色的台词,会被投影出三种文本形式,用在不同地方:

投影类型

内容

典型用途

dialogue

带角色前缀,如“HOST: 你平时……”

喂给视频生成模型,让它知道谁说哪句

speech

去掉角色前缀的纯朗读文本

送去配音和对齐

caption

去掉角色前缀的显示文本

生成字幕

双文本:屏幕上写的和嘴里说的不一样

做中文科普视频时,这个功能我觉得是最实用的。很多时候,字幕上想显示的和实际念出来的并不一致。英文缩写就是典型例子,屏幕上写“API”,嘴里要念“A P I”。

SVML 用双文本(Dual Text)解决,格式是 <显示内容|朗读内容>,竖线左边进字幕,右边进配音:

<explain>
  <HOST> 我们用的是 <API|A P I> 接口,价格按 <1K|一千> 次调用计算。
</explain>

字幕会显示“我们用的是 API 接口,价格按 1K 次调用计算”,配音念的是“A P I”和“一千”。左边允许留空,比如 < |嗯> 表示“嗯”要念出来,但字幕里不显示,很适合保留口语语气又不让字幕显得啰嗦。

当显示和朗读完全一样时,可以省略竖线右边,写成 <组件化|>。这个写法看似多此一举,其实有用:它把几个字打包成一个完整的字幕单元,字幕样式可以整组高亮,而配音里每个字仍然单独计时。官方文档还特别提到,中文、日文的汉字会按“单字”切分成词元,避免一整句中文被当成一个超长单词处理。

还有一个符号 ||,叫字幕分句标记,用来人为指定字幕在哪里换条。它只能出现在完整的对齐单元之间,不能插进双文本内部。

选区和时刻:给画面留好“挂钩”

前面说的都是“台词本身”。真正让画面能拴在台词上的,是两种零宽度的标记:选区(Selection)和时刻(Moment)。零宽度的意思是,它们不会出现在字幕和配音里,只是在文本中间插了一个看不见的钉子。

选区表示“一段范围”,成对出现:

<script id="story">
  <pain>
    <HOST> @problem 改一句台词,后面的字幕全要重新对。 @/problem
  </pain>
  <answer>
    <HOST> @fix 把画面拴在词上,这个问题就没了。 @/fix
  </answer>
</script>

时刻表示“一个时间点”,写法是名字后面加感叹号:

<reveal>
  <HOST> 一共有 @cards! 三个关键步骤。
</reveal>

@cards! 的意思是“在下一个词开始的那一刻”,后续你可以让一张卡片恰好在主播说出“三个”时弹出。

边界吸附方向的规则整理如下:

标记写法

含义

@id

选区开始,吸附到下一个词的开头(默认)

~@id

选区开始,吸附到上一个词的结尾

@/id

选区结束,吸附到上一个词的结尾(默认)

@/id~

选区结束,吸附到下一个词的开头

@id!

时刻,吸附到下一个词的开头

~@id!

时刻,吸附到上一个词的结尾

有两点比 XML 标签更灵活。不同名字的选区可以交叉,不要求像标签那样严格嵌套,比如 @a 一 @b 二 @/a 三 @/b 是合法的。选区和时刻共用一套命名空间,同一个名字不能既当选区又当时刻。

引用方式分别是 {story.selection.problem} 和 {story.moment.cards}。

锚点是怎么数出来的

Script 编译之后,会形成一串有序的“语义锚点”,所有选区和时刻最终都落在这些锚点上。官方文档给了一个很清楚的计数规则,我换成纯文本写出来:

锚点总数 = 2 × 词元数 + 2 × 段落数 + 2

其中:
每个词元有“开始”和“结束”两个锚点
每个段落有“开始”和“结束”两个锚点
最后的 2 是整条节目的起点和终点

举个例子,一份 Script 有 3 个段落、一共 40 个词元(中文按单字计),锚点总数就是 2 × 40 + 2 × 3 + 2 = 88 个。

这个规则的意义在于:Script 里自始至终没有一个秒数,也没有一个帧号。锚点只是“位置身份”,真正的时间要等到配音生成、对齐完成之后才算出来。这就是第一章说的“意图”被完整保留下来的技术实现。

注释、转义和词属性

最后补几个写台词时会用到的细节。

注释用 <!-- 这里是注释 -->,不会进入任何文本投影,适合给自己或 Agent 留备忘。台词里如果真的需要显示 @、< 或反斜杠,要分别写成 \@、\<、\\,否则会被当成语法符号。

单个词后面还能挂一个平铺的属性块,比如 重要{emphasis,keyword},字幕组件可以据此给这个词单独上色或加粗。属性不带任何时间含义,也不能嵌套。

写到这里,SVML 里“说什么”这一层就讲完了。下一章接着看,这份台词是怎么一步步变成带画面、带字幕、带声音的成片的。

四、从台词到成片:一条视频在 Hypit 里走过的完整路径

先看全景

上一章的 Script 只是起点。一条带口播的视频,在 Hypit 里大致要经过六个环节。我把官方文档里的数据流重新画了一遍,方便对照:

flowchart TD
    S[Script 台词] --> G[生成或导入口播素材]
    G --> N[Normalize 统一帧率与时长]
    N --> A[SemanticTake 词级对齐]
    S --> A
    A --> TL[Timeline 拼接成完整时间线]
    TL --> P[Performance 口播画面轨]
    TL --> SD[Sound 声音轨]
    TL --> CP[Caption 字幕轨]
    TL --> MT[Media Track 叠加素材与 B-roll]
    TL --> TX[Text 文字标题轨]
    P --> F[Film 合成]
    SD --> F
    CP --> F
    MT --> F
    TX --> F
    F --> R[Render 渲染为 MP4]

这张图里最关键的节点是 Timeline。在它之前,一切都是“语义”,没有确定的时间;在它之后,所有轨道都从同一份时间线里读取帧位置。下面按顺序拆开讲。

统一素材:Normalize

口播素材可能来自模型生成,也可能是你自己拍的。不同来源的视频,帧率、时长、音轨情况五花八门,直接拼在一起一定出问题。所以第一步要做“标准化”。

<program:Clock id="clock" frame-rate="30"/>

<pipeline:Normalize id="hook-media" source={hook-video.video}
  video="primary-moving" audio="default"
  span-authority="video" clock={clock}/>

Clock 是整条视频共用的时钟,只声明一次,这里设为每秒 30 帧。每一段口播素材都经过 Normalize,被换算到同一个帧的坐标系里。span-authority="video" 表示以画面时长为准。

官方文档专门强调,标准化这一步不包含任何台词含义,也不做语音识别,它只负责把“素材事实”确定下来,给后面的对齐打地基。这种“一步只干一件事”的设计,排查问题时特别省心。

词级对齐:SemanticTake

素材标准化之后,就轮到 WhisperX 登场了。SemanticTake 这个组件拿着一段标准化后的素材,和 Script 里对应的某一个段落做对齐:

<whisperx:SemanticTake id="hook-semantic"
  narrative={story}
  segment={story.segment.hook}
  media={hook-media.media}
  language="zh"/>

它的输出里包含:标准化后的素材本身、段落身份、每个词在这段素材里的本地帧窗口,以及这个段落的全部锚点。

这里有一个对中文创作者非常关键的限制:language 参数在每次对齐时都必须填写,官方文档写明目前只接受 en 和 zh 两个值,Hypit 也不会根据文本或音频自动判断语言。换句话说,中英文口播可以做,粤语、日语、韩语等其他语言的口播,暂时没法走这条对齐路线。想做多语种版本的朋友,这一点要提前心里有数。

官方建议按“段落大小”一段段对齐,一个段落对应一段素材。我理解这样做有两个好处:单段出错只需要重做这一段,不会牵连整条;另外,段落边界本身就是天然的“换镜头点”,和拍摄、生成的习惯正好吻合。

拼接时间线:Timeline

对齐好的各段素材,由 Timeline 按节目顺序拼起来:

<time:Timeline id="speech" clock={clock}>
  <time:Take source={hook-semantic.take}/>
  <time:Take source={pain-semantic.take} at="previous.end+1s"/>
  <time:Take source={demo-semantic.take} at="previous.end-10f"/>
</time:Timeline>

不写 at 时,每段默认紧跟在上一段后面。previous.end+1s 表示上一段结束后留 1 秒空隙,previous.end-10f 表示和上一段重叠 10 帧,适合做声音交叉过渡。时间线的结尾也可以用 end="content.end+2s" 多留 2 秒尾巴,或者用 end="30s" 定死总长。

有一条规则容易被忽略:时间线上没有素材覆盖的区域,系统不会自动填充占位画面。如果你留了空隙又没安排其他画面,那一段就是空的。

每一段素材在全局里的帧位置,等于它的放置起点加上它自己内部的本地帧号。这个换算完全是确定的,也就是说,同样的输入每次算出来的帧位置都一样。

各路轨道各自读取时间线

时间线建好之后,字幕、叠加素材、文字标题、声音、口播画面这些“轨道”就可以各干各的了。它们都接收同一个 timeline={speech.timeline},再用 during 属性说明自己在什么时候出现:

during 的写法

含义

{story.segment.demo}

整个 demo 段落期间

{story.selection.problem}

problem 选区覆盖的范围

{story.moment.cards}

cards 时刻那个时间点

"program"

整条节目全程

比如让一张示意卡片在 problem 选区期间出现:

<media-track:Track id="cards" timeline={speech.timeline} canvas={vertical}>
  <media-track:Item image={pain-card.image}
    during={story.selection.problem}
    frame={card-frame}
    appearance={recipes.media.card}
    motion={recipes.motion.card}/>
</media-track:Track>

字幕轨则直接读取 Script 自动产出的字幕文档:

<caption-fine:Track id="captions"
  document={story.caption}
  timeline={speech.timeline}>
  <caption-fine:Use style={primary-caption}/>
</caption-fine:Track>

注意看,这些代码里一个秒数都没有出现。卡片什么时候出、字幕每个字什么时候亮,全部由选区、时刻和对齐结果推导出来。台词一改,重新构建,位置自动更新。这就是语义锚定落到代码层面的样子。

样式表:把“长什么样”单独拎出来

轨道组件里的 appearance={recipes.media.card} 这类引用,指向的是 .svs 样式表。它的写法和网页 CSS 很像:

<?svml using="@hypit/svs@1"?>
<sheet version="1">
  film.vertical { background: #0B0B10; }
  media.card {
    stack-order: 40; fit: cover;
    clip: rounded; radius: 24;
  }
  motion.card {
    enter: slide; enter-frames: 5; enter-direction: up;
    exit: fade; exit-frames: 4;
  }
  caption.base {
    stack-order: 70; x: 0.06; y: 0.74; width: 0.88;
    size: 60; align: center;
    fill: #FFFFFF; background: #0B0B10CC;
    padding: 14 22; radius: 16;
  }
</sheet>

stack-order 决定图层上下关系,数值小的在下面,数值大的盖在上面。官方文档给出的典型分层是这样的:

stack-order

通常放什么

10 左右

口播画面

40 左右

叠加素材、B-roll

70 左右

字幕

90 左右

文字标题

我的习惯是给每一层之间留足间隔,后面临时插一个“贴纸层”或“水印层”时,不用把所有数字都改一遍。

合成与渲染:Film 和 Render

所有轨道最终交给 Film 合成:

<film:Film id="main" canvas={vertical}
  timeline={speech.timeline} appearance={recipes.film.vertical}>
  <film:Track source={performance.visual}/>
  <film:Track source={voice.audio}/>
  <film:Track source={cards.visual}/>
  <film:Track source={captions.track}/>
</film:Film>

<render:Video id="final"
  composition={main.composition} timeline={speech.timeline}/>

Film 负责校验所有轨道,产出一份“合成描述”。render:Video 再调用 HyperFrames 渲染器,大致经过五步:把合成描述编译成逐帧的网页文档,用 Chrome 或 Chromium 逐帧渲染,把帧序列编码成视频,混合音轨,最后把画面和声音封装成 MP4。

这里有个细节,Film 里轨道的书写顺序不影响图层上下,上下关系只看样式表里的 stack-order。所以调整代码顺序不会意外把字幕压到画面底下,这点比很多剪辑软件“轨道位置即图层位置”的逻辑更不容易出错。

原理部分到此告一段落。莫潇羽@无忆研习社 建议新手不必一次记住所有组件名,理解“台词定锚点、对齐算时间、轨道读时间线、合成再渲染”这条主线就够了,具体语法遇到时再查文档。下一章开始动手。

五、动手:从装好环境到导出第一条成片

动手前的环境清单

先把需要准备的东西列清楚,免得装到一半卡住:

项目

要求

说明

Node.js

22 及以上

版本过低会直接装不上,建议用 22 的较新小版本

编程 Agent

支持 Skill 的即可

官方点名的是 Claude Code 和 Codex

FFmpeg

需要

渲染时负责视频编码与音频混合

Chrome 或 Chromium

需要

渲染器靠它逐帧绘制画面

语音对齐能力

本地 WhisperX 或托管服务二选一

本地运行对显卡有一定要求

生成模型

可选

纯代码渲染的视频不需要

“Skill”这个词第一次出现,解释一下:它是一种给 Agent 使用的能力包,里面装着某一类任务的专业知识、操作规范和配套脚本。装上之后,Agent 遇到相关任务就会按照包里的方法去做,相当于给 Agent 请了个专项教练。

检查 Node.js 版本只需要一行命令:

node -v
# 输出 v22 开头或更高即可

版本不够的话,用 nvm 这类版本管理工具升级最省事。国内网络下载 npm 包偶尔会慢,可以把 npm 源切换到国内镜像:

npm config set registry https://registry.npmmirror.com

需要提醒一句,Hypit 的 Skill 和部分服务托管在境外代码平台上,访问受网络环境影响。遇到下载失败就稍后重试,不要去折腾任何突破网络管理的做法,合规永远排在效率前面。

安装 Skill

在终端执行官方给出的安装命令:

npx skills add hypit-ai/hypit -g

-g 表示全局安装,之后你打开任何项目文件夹,Agent 都能调用这个技能。

官方文档说得很清楚:Skill 负责提供制作知识,hypit 这个 npm 包负责提供可执行工具。你不需要把 Hypit 的代码仓库克隆到本地。第一次使用时,Agent 会自己检查可执行工具是否就绪,缺什么会告诉你并协助准备。

建一个干净的项目文件夹

我强烈建议每条视频或每个系列单独建一个文件夹。官方文档推荐过一种目录布局,我在它基础上加了几行中文注释:

my-video/
  package.json            项目边界标记
  authors/
    main.svml             视频内容主文件
  recipes/
    visual.svs            视觉样式
  runs/
    final.svrun           成片构建意图
  assets/                 自己提供的素材(需确认有使用授权)
  output/                 导出给人看的成片
  hypit.runtime.json      运行环境配置
  .hypit/                 自动生成的运行数据与构建结果

官方特别说明,这只是给人看的推荐布局,Hypit 并不强制这些文件夹名,它只认你在源文件和命令里写明的路径。小项目把几个文件平铺在根目录也完全没问题。

有一点必须遵守:.hypit/ 目录、各种凭据、生成出来的媒体文件和日志,都不要提交到代码仓库。如果你用 Git 管理项目,记得把它们写进忽略清单。

和 Agent 说出你的第一个需求

在项目文件夹里打开 Agent,用 /hypit 调用技能。新手我建议从“文字描述”入口开始,不涉及任何参考视频,版权上最干净。比如:

/hypit 帮我做一条 25 秒左右的竖屏知识短视频,主题是“为什么
视频模板复用这么难”。开头用一个反问句抓注意力,中间用两张
示意卡片解释原因,结尾引导观众收藏。先不要调用任何付费模型,
用字幕和动态图形完成。

最后一句“先不要调用任何付费模型”很重要。第一次上手的目标是跑通流程、熟悉文件结构,而不是追求画面效果。等流程通了,再逐步加入配音和生成素材。

Agent 接到需求后,会先解释它对需求的理解和打算怎么做,然后在项目里生成 SVML、SVS、SVRUN 文件。这个过程中它会持续汇报进展,你随时可以打断它、调整方向。

配置运行环境

如果你想自己动手执行命令,或者想看懂 Agent 在做什么,下面这几条是运行环境相关的核心命令:

# 生成一份入门级运行配置并选中它(不会覆盖已有文件)
hypit runtime init

# 或者选中一份已有的运行配置
hypit runtime use hypit.runtime.json

# 查看当前凭据状态
hypit auth status

# 为某个服务端点登录凭据
hypit auth login hypihub.default

runtime init 只负责写一份起步配置并选中,不安装任何东西,不联系任何服务,也不启动后台进程。凭据通过 auth login 安全录入,绝对不要把 API 密钥直接写进 .svml、.svrun 或配置源文件里。

检查、规划、看报价,再开跑

这是我认为整个流程里最值得养成习惯的部分:先确认,再花钱。

# 体检运行环境(只读,不发起付费请求)
hypit doctor

# 编译检查视频源文件,校验导入、类型和组件连接
hypit check authors/main.svml

# 查看本次构建计划:会发起哪些外部请求、带什么参数
hypit plan runs/final.svrun

# 读取本次构建涉及服务的费率信息
hypit pricing runs/final.svrun

几条命令的分工我整理成表:

命令

做什么

会不会花钱

doctor

检查运行环境、端点配置、凭据是否齐全

不会

check

编译视频源文件,找语法和连接错误

不会

plan

列出本次构建的全部操作和外部请求

不会

pricing

按所选服务读取费率,分组展示请求数量

不会

build

真正提交构建任务

可能会

pricing 读到的是费率信息,不是保证的总价。有些输入的时长在生成之前是未知的,报告里会把不确定的部分如实保留。AI 视频相关服务的价格变动非常快,任何时候都请以服务商官方定价页面的实时数据为准。

提交构建并导出成片

确认无误后,提交构建:

hypit build runs/final.svrun --title 第一版 --follow

加了 --follow,终端会持续显示进度。这里有个设计要理解:真正干活的是后台 Worker 进程,终端只是“观察者”。你中途关掉终端,构建并不会停,之后可以重新接上观察:

hypit status <构建编号> --watch

构建完成后,查看结果并导出:

hypit inspect <构建编号>
hypit get <构建编号> --output final.video --to output/final.mp4

构建成功时,终端会直接打印出每个文件目标对应的导出命令,照着复制就行。注意 --to 指向的目标文件不能已经存在,这是为了防止误覆盖。

用 Studio 做可视化微调

成片导出后,Agent 可以帮你打开 Hypit Studio。它提供一个可视化时间线界面,你能在上面查看各轨道的排布,并直接编辑部分支持的属性。

我的建议是把 Studio 当成“检查器”而不是“主编辑器”。字幕位置不舒服、卡片出现得太早,在 Studio 里看清楚问题,再回到对话里让 Agent 改源文件,这样修改会沉淀在文本里,下次做变体时依然有效。

六、复用与批量:变体为什么能越做越省

Hypit 没有“隐式缓存”

很多人第一次看到“批量变体”几个字,会以为系统会自动记住上次生成过的东西,下次跳过。Hypit 恰恰相反,官方文档明确写着:没有隐式缓存。

每次执行 build 都会拿到一个全新的构建编号和独立的结果目录,哪怕源文件一个字没改。原因在于生成模型本身是“不确定”的,同样

🔒
该内容仅对更高等级社区用户开放
请谨慎解锁时效性强且发布日期较早的文章
单篇解锁后若未显示全文请刷新页面
您当前:游客 · 可见 60% 内容 · 升级至 注册用户 可见 70%
👀
游客
可见 60%
✓ 当前
注册用户
注册用户
可见 70%
社区精英
社区精英
可见 100%
社区守护
社区守护
可见 100%
仅解锁本文,永久有效。如需PDF珍藏版,请联系站长获取。 当前单篇价格 ¥9.9
✏️ 发表评论

请先登录后发表评论

前往登录
📊 站点统计
今日发布0 篇
文章总数1107 篇
昨日发布1 篇
本月发布31 篇
建站时间456 天
🔍 搜索
站长微语

联系站长

QQ:2805463528
AIGC 技术社区
致力于解码 AI前沿技术 与经验分享
纯粹的技术应用社区

💡 欢迎您的建议与反馈,让社区变得更好

快速通道
联系站长
站长QQ二维码
AI交流群
AI交流群
仍在路上

那些寒夜里追赶过的方向

那些冷眼下没放弃的理想

一篇一篇写到现在

仍在路上

"不羁放纵爱自由"

—— 致敬 Beyond
持续创作中 莫潇羽 · 无忆研习社
▲