用我们真实做过的「深夜下班开车回家」高速短片,从 Skill 知识到 CLI、Runtime,再到两版成片,走一遍完整链路。
Skill 是“导演手册”,CLI 是“制片调度”,Runtime 是“片场”。
check 校验 Source 图;plan 列出请求与费用归属runtime use/up/down 管理本地 Workerbuild 提交持久 Build;status/inspect/builds 观察get 把命名 Output 导出为文件从参考分析到成片,每一步都在你的电脑 <project-dir>\highway 完成。
在你电脑上用下载工具抓取参考片(部分网络环境被视频站拦截),抽帧做拼图,只用于分析,不嵌入、不复用。归纳出风格:扁平 2D / 低多边形卡通、低饱和配色、黄昏到夜晚的高速、驾驶位第一人称(圆润仪表台+方向盘)、车道虚线冲向消失点、成排橙色路灯、绿色起伏山丘剪影、粉紫天空、后视镜特写、对向远光、表情不爽的圆脸司机、底部居中白色小字幕。
6 个硬切镜头 / 22s / 1280×720 / 30fps;角色、文案、配乐全部原创(不使用任何歌词与原画面)。
Skill 指导 Agent:把"随时间变化的对象与关系"写成组件。我们写了项目组件 @example/highway-scene(TS 包,htmlVisual + canvas 按帧绘制),在 SVML 里用 <hw:Scene>/<hw:Shot> 编排。
校验 Source:+ Source is valid · Outputs 13(Grok 版 52)。
预览每一步由谁执行、是否收费——本地步骤全部显示 local, no Provider charge。
拉起本地 Worker(无头 Chrome + FFmpeg)。改了组件代码后必须 runtime down → up。
提交持久化 Build:660 帧光栅化约 45–60s,status --watch 跟进。
get <build-id> --output final.video --to raw.mp4 导出(目标存在会拒绝覆盖)。
box 上 ffmpeg 合成原创引擎低鸣并 mux:-c:v copy -c:a aac,得到最终 mp4。
<time:Clock id="clock" frame-rate="30"/>
<time:Timeline id="drive" clock={clock} end="22s">
<time:Instant id="s1" at="0s"/>
<time:Instant id="s2" at="4.5s"/> … <time:Instant id="s6" at="19s"/>
</time:Timeline>
<spatial:Canvas id="canvas" width="1280" height="720"/>
<hw:Scene id="road" timeline={drive.timeline} within={canvas.bounds} during={drive.window}>
<hw:Shot id="a" kind="road" text="加完班,已经快零点了" at={drive.s1}/>
<hw:Shot id="b" kind="mirror" text="后面那辆车,跟了我一路" at={drive.s2}/>
…
</hw:Scene>
<film:Film id="main" canvas={canvas.canvas} timeline={drive.timeline} appearance={style.film.main}>
<film:Track source={road.visual}/>
</film:Film>
<html:Video id="final" composition={main.composition} timeline={drive.timeline}/><asset:Video id="src-road" src="./grok/road.mp4"/>
<mediaop:Normalize id="m-road" source={src-road} clock={clock}
video="primary-moving" audio="none" span-authority="video"/>
<time:Window id="w1" from="0s" for="4.5s"/>
<spatial:Frame id="full-frame" within={canvas.bounds} left="0%" top="0%" right="100%" bottom="100%"/>
<visual:Track id="picture" timeline={drive.timeline}>
<visual:Clip id="c-road" media={m-road.media} during={drive.w1}
frame={full-frame} z="10" fit="cover"/> …×6
</visual:Track>
<hw:Scene id="subs" …> <!-- kind="sub-*":透明背景,只画字幕,present z=100 -->
<film:Film …>
<film:Track source={picture.visual}/>
<film:Track source={subs.visual}/>
</film:Film><?svml using="@hypit/markup/run@1"?> <svrun version="1"> <author source="./highway-grok.svml"/> <target output="final.video"/> </svrun>
{
"format": "hypit.runtime-local@1",
"dataRoot": ".hypit/runtimes/local",
"endpoints": {
"media.local": { "use": "@hypit/media-local", "config": { "defaultConcurrency": 2 } },
"html.local": { "use": "@hypit/provider-html-local", "config": { "workers": 2, "defaultConcurrency": 1 } }
}
}$ hypit plan highway-grok.svrun + Build plan is valid Requests 15 · Local requests 15 · Preflight ready @hypit/html-program#rasterize-visual html.local · local, no Provider charge @hypit/media-operations#normalize-media ×6 media.local · local, no Provider charge @hypit/media-operations#mux-program-media media.local · local, no Provider charge
POST /v1/videos/generations (API 网关, Bearer ●●●●)
{ "model":"grok-imagine-video", "prompt":"Flat 2D low-poly cartoon … + 镜头描述",
"duration":5, "aspect_ratio":"16:9", "resolution":"720p" }
→ { "request_id":"…" }
GET /v1/videos/{id} → status:"done", usage.cost_in_usd_ticks: 3.5e9 (≈$0.35)
GET /v1/videos/{id}/content → mp4 (1280×720, 24fps, ~5.04s)同一份时间线与字幕,只替换画面来源。
Canvas 按帧绘制:车道虚线滚动、路灯透视、镜头轻微摇晃、远光眩光、原创圆脸司机眨眼。
6 段 grok-imagine-video(5s/720p),统一风格前缀提示词;Hypit 负责归一化到 30fps、剪辑、叠字幕。
| A 纯代码 | B Grok 片段 | |
|---|---|---|
| 成本 | ¥0(全本地) | 6 次 × ≈$0.35 ≈ $2.1(按 tick=1e-10 USD 估算) |
| 耗时 | 渲染约 45s | 每段生成 45–55s + 渲染约 70s |
| 可控性 | 逐像素可改、可复现 | 需重新生成,结果有随机性 |
| 质感 | 扁平几何、偏简单 | 光影/角色表演更丰富 |
| Hypit 节点 | hw:Scene → film:Track | asset:Video → mediaop:Normalize → visual:Clip ×6 + 字幕层 |
22s 时间线上的 6 个窗口;字幕组件透明背景、present z=100,压在 z=10 的视频 Clip 之上。
都已解决,记录下来下次少走弯路。
Hypit 要求 Node ≥ 22.15,系统是 22.14 → 另放便携版 <tools>\node22,每个终端先 prepend PATH。
项目 package.json 必须声明,否则 check 找不到项目。
示例里的 workspace: 引用脱离 monorepo 无法安装,改成 npm 发布版本。
Worker 常驻并缓存组件模块,改代码后不重启就会渲染旧版本(我们的仪表盘时钟改了却没生效)。
组件编译时 tsc 会去类型检查 @hypit 依赖源码并报错不出产物;用 --noCheck 只做转译。
Export destination … already exists:先删旧文件再 get。
plan/build 需要自描述的 Run Source(.svrun),并先 hypit runtime use hypit.runtime.json。
字幕组件 present 默认 z=0,被 z=10 的视频 Clip 盖住 → 字幕层提到 z=100,并把背景改为透明。
字幕用 CSS 系统字体(Microsoft YaHei),换机器可能变;正式可用 asset:Font 打包。