上船演示片 是做什么的?
scripts/demo 录制一个 Web 应用并将其语料库写入 ~/demo-reels-out/<workspace>/(DEMO_OUT_ROOT 可设置父目录,DEMO_OUT 可指定某次运行的目录):每个场景生成一个带旁白的 mp4 文件、一张海报、视网膜屏静态截图,以及 full-tour.mp4、manifest.json 和 index.html。所有内容均在本地完成。引擎从本技能运行,不会向被录制的应用中安装任何内容。
不可妥协的规则
以下每一条都会消耗一次运行或用户的耐心。
- 必须使用固定构建版本,绝不能使用开发服务器。 开发服务器的模块图属于编辑源代码的任何人。请将构建版本复制到私有位置,并通过读取打包文件验证其 API 地址。没有对应仓库的 URL 为
site模式;localhost 的 URL 为开发服务器,绝不能录制。 - 在
build模式下,需在进程内模拟所有请求并固定时钟。 语料库会被发布,真实账户会发布真实用户的地址。site模式则主动放弃这两点:仅录制公开页面。 - 使用自己的端口和输出目录。 工作室拒绝接受非自己启动的服务器。切勿使用模式匹配的方式进行
pkill。 - 1080p60 视频,2 倍静态截图。 两者为独立设置。4K 视频会因像素/秒的吞吐量预算固定而产生抖动。
- 先执行手势动作,再推近镜头,然后对结果进行旁白解说。 每行只针对一个主题。切勿在主题出现前进行解说。如果应用有自身计时器(如撤销窗口、提示框),则手势操作应在计时器内进行,旁白在其后,否则影片会展示功能无法正常工作。
- 录制一个场景后,暂停并询问(步骤 8)。这曾在拍摄 26 个场景前发现了四个缺陷。
- 每次必须检查 PNG 静态截图。 一个场景虽然通过但在取景错误的情况下,仍属于失败,只有通过眼睛查看静态截图才能发现。
- 除非用户确认,否则一切均非最终版本。 任何关于措辞、取景、节奏、覆盖内容或声音的反馈都是需要重新录制的,而非讨价还价:修改后重新录制。用户无法看到你所见的,因此“太长”、“再放大一点”和“别缩放太多”都是完整的指令,重新拍摄一个场景成本很低。
工作流程
- 根据所给信息选择模式,无需询问。 公开主机上的 http(s) URL 为
site模式,工作区为~/.shipdemo/<host>/。localhost 或私有地址上的 URL 为开发服务器:找到其背后的仓库,并将请求视为该仓库。没有 URL 则表示当前所在的仓库,因此向上查找 Web 应用(即存在package.json且包含构建脚本,以及 Vite、React Router、Next、Astro、SvelteKit 或 Remix 配置文件)。只有一个是build模式;如果有多个,则询问;如果没有,则要求提供 URL 或路径。工作区的.origin文件如果已命名此仓库,则复用,不再重新搭建。在一行内说明模式和工作区路径,然后继续。 - 运行
scripts/doctor.sh,在向用户提出任何其他要求前,先完成自身设置。 用户安装了一个技能,并非为了运行三个脚本。用一行说明缺少什么,一行说明建议安装的内容及大致大小,待用户同意后执行。scripts/install.sh安装引擎和 Chromium(约 250MB)并在包管理器允许时同时安装 ffmpeg;scripts/install-voice.sh安装语音包(约 350MB),如果用户不愿意,录制无声版本也是可以的。未经允许绝不安装任何东西,也绝不把 doctor 报告交给用户自行解读。脚本不会做两件事,你也不应该做:升级用户的 Node(因为哪个工具管理 Node 版本应由用户决定)和运行sudo(无人值守的脚本遇到密码提示会直接挂起)。在这两种情况下,脚本会打印单条命令,你只需转达即可。 - 发现阶段,不写入任何内容。
site模式:打开 URL 并读取页面用途、值得展示的三件事,以及哪些内容足够稳定可以指向。如果页面跳转到登录页面,则停止:登录后的应用应从其仓库录制,因此请要求提供仓库或公开 URL。build模式:从package.json中逐字复制构建命令;根据框架配置的输出目录;.env*中任何绝对 API 主机(放入build.forbid中);主题启动脚本读取的键;已有的 mock API 或 MSW handler;data-testid的密集程度;无需凭据的路由。 - 运行
scripts/scaffold.mjs <appRoot>或scripts/scaffold.mjs --site <url>。不会向应用中写入任何内容。 - 填写工作区的
demo.config.ts。 如果仍有必填字段未知,说明发现未完成。config.md - 仅
build模式:编写mock.ts和seed/。 如果应用有数据 fixture 文件,可复用,但绝不能使用导入了@playwright/test的文件:同一运行中出现两份副本会导致 Playwright 拒绝执行,并且整个语料库会因一个场景而失败。然后运行DEMO_VOICE=0 scripts/demo --grep smoke。如果应用有 fixture API,也可复用(mocking.md)。查看静态截图:确认已登录、已植入数据、主题正确、非登录页面。查看捕获行。修复直到两者都正确,然后编写仅包含 smoke 运行证明的内容的demo/ui.ts。 - 先编写脚本。 填写工作区的
profile.json(复制template/profile.json;产品、受众、结束语、禁用词),然后根据 script.md 编写每一行:钩子、步骤、成果、结束语。钩子也要写入hooks.json以便生成变体版本。按照用户要求及范围进行录制。 一个命名的功能就是一个场景:编写、录制、交付。不要用“录制首页搜索”的请求给出十个场景的提案,也不要因为产品包含更多功能而悄悄扩大需求。只有当请求为整个产品时,才提出 6 至 10 个场景,每个场景一个标题和一行简介(按导览顺序),并询问先录制哪一个。 - 暂停。 录制那个场景并加入旁白。确认旁白字数与
say调用一致,没有超时,语速正常。查看每一张静态截图。将 mp4 文件路径提供给用户,并就措辞风格、缩放程度、节奏和声音进行询问。在用户回答前,不要编写任何其他内容。 - 然后通过
--grep每次批量录制三到四个场景;清单会合并。每批后查看静态截图。迭代场景时使用DEMO_BUILD=0 scripts/demo跳过重建(二十秒替代四分钟);在生成最终语料库的运行中撤除此设置。 - 使用
DEMO_CAPTIONS=1 DEMO_TRACE_FRAMES=1进行完整运行,然后运行scripts/check.mjs <out>并打开<out>/index.html。报告捕获表格、任何慢速剪辑以及检查中标记的所有问题。 - 变体版本。 询问用户需要哪些变体,除非他们已指定:
reel、wide-phone、wide-laptop、wide-laptop-zoom、web或all(scripts/variants.mjs --list描述了每种变体)。然后运行scripts/variants.mjs <out> --only <list>。手机预设采用竖屏录制,笔记本预设采用横屏录制,因此如果用户需要两者,则需录制两种尺寸。在交付前,每种变体查看一张海报。
一个场景
scene('tasks', { title: '您的待办事项,紧邻日历', blurb: '...' },
async ({ actor, page, shot }) => {
await actor.click(page.getByRole('radio', { name: '今天' }));
await actor.settle();
await actor.spotlight(
row('向 Sam 发送反馈'),
'而这个来自昨天,我从未处理过,所以被标记了。',
{ scale: 1.8, stay: true }
);
await shot('overdue');
await actor.unfocus();
});
spotlight 接受旁白标记,然后将摄像机和光标移动到该行开头位置。缩放比例根据主体而定:面板约 1.4,行约 1.7,单个控件约 2。涉及整个屏幕的行只需使用 say,无需缩放。unfocus 是一个提示而非具体移动:仅当需要广角时才拉远镜头,因此连续关于同一区域的操作会平滑过渡而非跳跃。scenes.md · narration.md
绝对禁止
云 TTS(因为录制的可能是私有数据)。Playwright 的 recordVideo(无法控制码率、大小或开始时间;录制器会替代它)。默认使用 4K。音乐、开场卡片或过渡效果。基于路由遍历生成的场景:场景应是有目的的编排。重试:重试的场景等同于不同的影片。
字幕、检查与变体
对于计划发布的任何内容(DEMO_CAPTIONS=1),都需要添加字幕:.srt、.vtt、.lines.json 以及一个 .captioned.mp4 文件。这些字幕直接从脚本中生成,因此与语音逐字匹配。内嵌字幕位于底部,并抬高以避开播放器控件(可通过 DEMO_CAPTION_MARGIN 覆盖;绝不能放在顶部)。
scripts/check.mjs 运行三项检查:语音(转录每一行并与脚本比较)、屏幕(每半秒检测配置文件中 neverOnScreen 中的词汇,然后检测所有红色内容)以及帧(检测慢速间隙)。如果某个工具缺失,则跳过并提供安装命令(scripts/install-checks.sh)。对于属于正常的红色内容(如逾期徽章),也会列出:只需读取列表,不将其计入。
scripts/variants.mjs 读取 variants/presets.json。新的变体只需在其中添加新条目:画布、应用位置、钩子和字幕位置,以及 zoom(如果需要推近高亮内容)。无需重新录制;原始文件不被修改。
其他
使用 DEMO_VOICE_VARIANTS=am_michael,bf_emma 可以为同一段录音混合更多语音(生成 <scene>.<voice>.mp4),以便在不重新录制的情况下试听不同语音。
在更改任何捕获参数前,请先参阅 capture.md。runs.md 提供了关于构建、隔离和清单的指南。当运行失败或截图显示异常时,请参阅 troubleshooting.md。引擎从本技能运行,因此对 engine/ 的修改会立即影响机器上的所有项目:直接在那里编辑即可,无需传播。