VHS 录制终端幻灯片演示:用 Tape 脚本编排 slides 翻页动画

原创2026-09-30 22:41:261,628 阅读
文章标签:开发工具

VHS 录制终端幻灯片演示:用 Tape 脚本编排 slides 翻页动画

VHS 的 examples/slides 示例展示了一个非常典型且巧妙的用法:把终端幻灯片演示工具 slides 的整场演出录制成 GIF。这篇指南以该示例为骨架,逐行拆解其 Tape 脚本中的全局设置、Hide/Show 帧控制、带速度的 Type@1s 输入与 Ctrl+E 组合键编排,并深入 parser/parser.go、command.go、evaluator.go 源码,帮助你掌握"用低帧率 + 定时按键制造幻灯片翻页节奏"这类演示录制技巧,从而为自己的 CLI 工具或演示应用编写同类 Tape 文件。

VHS 录制的 slides 终端幻灯片演示

一、示例概览:一份 30 行的完整演示脚本

examples/slides/README.md 的核心是一份可直接运行的 Tape 文件,它与同目录下的 slides.tape 内容一致:

Output examples/slides/slides.gif
Set FontSize 32
Set Padding 0
Set Framerate 1
Set Width 1600
Set Height 1200

Hide
Type "slides"
Enter
Show

Sleep 1s

Type@1s "n"

Sleep 1s

Ctrl+E

Sleep 1s

Type@1s "nnn"

Sleep 1s

整个脚本只用了 6 类命令(Output、Set、Hide/Show、Type、Enter、Ctrl、Sleep),却完整模拟了一次幻灯片演示:启动应用 → 隐藏启动过程 → 逐页翻页 → 收尾。这也是 VHS 面向"演示与集成测试"定位的缩影(主 README 开篇即写道 "Write terminal GIFs as code for integration testing and demoing your CLI tools")。

二、逐段拆解:全局设置如何决定画面形态

1. 输出与画布尺寸

Output examples/slides/slides.gif
Set FontSize 32
Set Padding 0
Set Framerate 1
Set Width 1600
Set Height 1200
  • Output 指定渲染产物路径。解析器 parser.go 会读取文件扩展名来决定输出类型:.gif 走 GIF 通道,.mp4/.webm 走视频通道,.png 或带尾斜杠的目录则输出 PNG 帧序列,.txt/.ascii 则用于生成 golden file 做集成测试(见 command.go 的 ExecuteOutput)。
  • Set FontSize 32:字号越大,终端里每个字符占的像素越多。执行时通过浏览器内核执行 term.options.fontSize = 32 并调用 term.fit 重新适配画布(见 command.go 的 ExecuteSetFontSize)。
  • Set Padding 0:把终端外框的内边距设为 0 像素,让幻灯片内容尽可能铺满画面(对比 examples/settings 中 Set Padding 20 的留白效果)。需要提醒的是,evaluator.go 会校验画布尺寸必须能容纳 padding、margin 与 window bar,否则直接报错 Dimensions must be at least ...。
  • Set Framerate 1:每秒只捕获 1 帧(对应 command.go 的 ExecuteSetFramerate,写入 Video.Framerate)。这是整个脚本"幻灯片感"的关键:每秒钟画面只刷新一次,配合下方的 Sleep 1s,每一次动作之间恰好只有一帧,GIF 看起来就像一页一页切换的幻灯片,而不是流畅滚动的视频。
  • Set Width 1600 / Set Height 1200:16:9 的画布比例,适合宽屏演示场景;高分辨率也保证了幻灯片里较大字号(32px)的文字清晰锐利。

注意:Set 指令(除 TypingSpeed 外)必须写在文件顶部、任何非设置命令之前。若放在后面会被忽略并输出警告(见 evaluator.go)。本示例严格遵循了这一约束。

2. 隐藏启动过程:Hide / Type / Enter / Show

Hide
Type "slides"
Enter
Show

这是 VHS 最常用的"舞台准备"四件套:

  • Hide 暂停帧捕获(内部调用 PauseRecording,见 command.go 的 ExecuteHide);
  • Type "slides" 在隐藏状态下输入启动命令,Enter 回车执行;
  • Show 恢复录制(ResumeRecording,见 command.go)。

效果:观众看不到"你敲命令启动应用"的过程,画面直接从已经打开的 slides 界面开始。主 README 的 Hide 小节 也给出同样套路:隐藏阶段可用来做构建、清理等任何不想入镜的准备工作。更妙的是 evaluator.go 专门优化了这条路径——如果设置命令之后的第一个命令是 Hide,VHS 会在正式录制帧之前先执行完 Hide 到 Show 之间的所有命令,确保这中间的按键操作连一帧都不会被记录。

3. 节奏控制:Sleep 定拍

Sleep 1s

Sleep 让 VHS 保持录制但停止交互,时长参数既支持带单位的 1s、100ms,也支持裸数字(默认按秒解释),例如 Sleep 0.5 即 500ms(见 parser.go 的 parseTime 与 command.go 的 ExecuteSleep)。本脚本中每个 Sleep 1s 都夹在动作之间,配合 Framerate 1,每一拍恰好产出一帧。

4. 带速度的输入:Type@1s

Type@1s "n"

Type@<time> 是 Type 命令的速度变体:@1s 表示每个字符之间间隔 1 秒输入。解析层在 parser.go 的 parseSpeed 中识别 @ 后的时间,执行层在 command.go 的 ExecuteType 中逐字符输入并在字符间 Sleep 对应时长。

本示例用它输入 n 和 nnn。结合"每秒 1 字符 + 每秒 1 帧 + 前后 Sleep 1s"的编排可以推断:在 slides 这类演示应用里,n 常被映射为前进/播放下一步,Type@1s "n" 恰好让每次按键的节奏与帧率对齐,从而在 GIF 中呈现出"每帧翻一页"的确定性节奏;而 Type@1s "nnn" 连发三键,则是在演示结束阶段连续翻动多页。相比 Type "n" 的瞬间输入,这种慢速输入能更清晰地传达"用户正在一下一下操作"的体感。

5. 组合键:Ctrl+E

Ctrl+E

Ctrl 命令用于按住 Control 再按下后续键,语法为 Ctrl<a href="https://link.gitcode.com/i/d2ebf00e27829b4ef9e41add5b4a6723" target="_blank">+Alt][+Shift]+<char>,也支持组合修饰键如 Ctrl+Alt+Shift+P(见 [parser.go 的 parseCtrl)。执行时由 command.go 的 ExecuteCtrl 构造键盘动作:先按住 ControlLeft,逐个按下参数中的键,最后一个键用 Type 完成敲击再统一释放。此处 Ctrl+E 即"按住 Ctrl 敲 E",在 slides 演示场景中承担一次独立的翻页/跳转操作(具体语义由 slides 应用自身定义)。

三、参数速查:本例涉及的命令与设置

结合主 README 的 命令参考 与源码,本示例用到的语法归纳如下:

命令 / 设置 语法 取值与说明(仓库依据)
Output Output <path> 按扩展名决定格式:.gif / .mp4 / .webm / .png、帧序列目录、.ascii 测试输出(command.go)
Set FontSize Set FontSize <number> 像素字号,通过 xterm 的 term.options.fontSize 应用(command.go)
Set Padding Set Padding <number> 终端外框内边距(像素),command.go
Set Framerate Set Framerate <number> 每秒捕获帧数;设为 1 即每秒 1 帧,适合幻灯片式演示(command.go)
Set Width / Set Height Set Width/Height <number> 输出画布宽高(像素),command.go
Hide / Show Hide / Show 暂停/恢复帧捕获,隐藏启动等前置操作(command.go)
Type / Type@<time> Type "str" / Type@500ms "str" 逐字符模拟输入,@ 覆盖全局 TypingSpeed(command.go)
Enter Enter 回车键(键类命令支持 Key<a href="https://link.gitcode.com/i/f76e7b64c4f2b0d34170fa10d4e1d31d" target="_blank">@<time>] [count],[command.go)
Ctrl Ctrl+<char> 按住 Ctrl 的组合键,支持追加 +Alt/+Shift(command.go)
Sleep Sleep <time> 保持录制并等待,支持 1s、100ms、裸数字(秒)(command.go)

四、如何运行与验证

安装 VHS(需 ttyd 与 ffmpeg 在 $PATH 中,详见 README.md)后,进入仓库根目录直接执行:

vhs examples/slides/slides.tape

即可在 examples/slides 目录生成 slides.gif。你可以像这个示例一样,把任意终端演示工具(slides、glow、gum 等,参见 examples 下其他 demo)的操作流程脚本化,并总结出三条可复用的编排原则:

  1. 先设置、后动作:所有 Set 和 Output 放在文件顶部,保证帧捕获从干净状态开始;
  2. 用 Hide/Show 包裹启动与清理:让录制的"正片"从应用界面出现那一刻开始;
  3. 让 Framerate、Sleep 与 Type@<time> 三者节奏对齐:例如"1 帧/秒 + 1 秒一拍 + 每拍一个按键",就能稳定地制造出逐帧翻页的演示效果。

五、相关源码与参考文件

登录后查看全文
vhs