Communitygithub.com

上船演示片

用一份脚本把网页应用拍成有旁白的产品演示:配音、字幕和清晰的界面截取,素材来自构建好的仓库或线上地址,并按各平台的画幅出片。

上船演示片 是什么?

把一个网页应用收成成品演示片。一份脚本驱动声音、字幕和高清界面,覆盖 Reels、Shorts 和横屏,仓库本地构建或线上页面都可以拍。

兼容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/himohitmehta/shipdemo/tree/HEAD

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

上船演示片 是做什么的?

scripts/demo 录制一个 Web 应用并将其语料库写入 ~/demo-reels-out/<workspace>/(DEMO_OUT_ROOT 可设置父目录,DEMO_OUT 可指定某次运行的目录):每个场景生成一个带旁白的 mp4 文件、一张海报、视网膜屏静态截图,以及 full-tour.mp4、manifest.json 和 index.html。所有内容均在本地完成。引擎从本技能运行,不会向被录制的应用中安装任何内容。

不可妥协的规则

以下每一条都会消耗一次运行或用户的耐心。

  1. 必须使用固定构建版本,绝不能使用开发服务器。 开发服务器的模块图属于编辑源代码的任何人。请将构建版本复制到私有位置,并通过读取打包文件验证其 API 地址。没有对应仓库的 URL 为 site 模式;localhost 的 URL 为开发服务器,绝不能录制。
  2. 在 build 模式下,需在进程内模拟所有请求并固定时钟。 语料库会被发布,真实账户会发布真实用户的地址。site 模式则主动放弃这两点:仅录制公开页面。
  3. 使用自己的端口和输出目录。 工作室拒绝接受非自己启动的服务器。切勿使用模式匹配的方式进行 pkill。
  4. 1080p60 视频,2 倍静态截图。 两者为独立设置。4K 视频会因像素/秒的吞吐量预算固定而产生抖动。
  5. 先执行手势动作,再推近镜头,然后对结果进行旁白解说。 每行只针对一个主题。切勿在主题出现前进行解说。如果应用有自身计时器(如撤销窗口、提示框),则手势操作应在计时器内进行,旁白在其后,否则影片会展示功能无法正常工作。
  6. 录制一个场景后,暂停并询问(步骤 8)。这曾在拍摄 26 个场景前发现了四个缺陷。
  7. 每次必须检查 PNG 静态截图。 一个场景虽然通过但在取景错误的情况下,仍属于失败,只有通过眼睛查看静态截图才能发现。
  8. 除非用户确认,否则一切均非最终版本。 任何关于措辞、取景、节奏、覆盖内容或声音的反馈都是需要重新录制的,而非讨价还价:修改后重新录制。用户无法看到你所见的,因此“太长”、“再放大一点”和“别缩放太多”都是完整的指令,重新拍摄一个场景成本很低。

工作流程

  1. 根据所给信息选择模式,无需询问。 公开主机上的 http(s) URL 为 site 模式,工作区为 ~/.shipdemo/<host>/。localhost 或私有地址上的 URL 为开发服务器:找到其背后的仓库,并将请求视为该仓库。没有 URL 则表示当前所在的仓库,因此向上查找 Web 应用(即存在 package.json 且包含构建脚本,以及 Vite、React Router、Next、Astro、SvelteKit 或 Remix 配置文件)。只有一个是 build 模式;如果有多个,则询问;如果没有,则要求提供 URL 或路径。工作区的 .origin 文件如果已命名此仓库,则复用,不再重新搭建。在一行内说明模式和工作区路径,然后继续。
  2. 运行 scripts/doctor.sh,在向用户提出任何其他要求前,先完成自身设置。 用户安装了一个技能,并非为了运行三个脚本。用一行说明缺少什么,一行说明建议安装的内容及大致大小,待用户同意后执行。scripts/install.sh 安装引擎和 Chromium(约 250MB)并在包管理器允许时同时安装 ffmpeg;scripts/install-voice.sh 安装语音包(约 350MB),如果用户不愿意,录制无声版本也是可以的。未经允许绝不安装任何东西,也绝不把 doctor 报告交给用户自行解读。脚本不会做两件事,你也不应该做:升级用户的 Node(因为哪个工具管理 Node 版本应由用户决定)和运行 sudo(无人值守的脚本遇到密码提示会直接挂起)。在这两种情况下,脚本会打印单条命令,你只需转达即可。
  3. 发现阶段,不写入任何内容。 site 模式:打开 URL 并读取页面用途、值得展示的三件事,以及哪些内容足够稳定可以指向。如果页面跳转到登录页面,则停止:登录后的应用应从其仓库录制,因此请要求提供仓库或公开 URL。build 模式:从 package.json 中逐字复制构建命令;根据框架配置的输出目录;.env* 中任何绝对 API 主机(放入 build.forbid 中);主题启动脚本读取的键;已有的 mock API 或 MSW handler;data-testid 的密集程度;无需凭据的路由。
  4. 运行 scripts/scaffold.mjs <appRoot> 或 scripts/scaffold.mjs --site <url>。不会向应用中写入任何内容。
  5. 填写工作区的 demo.config.ts。 如果仍有必填字段未知,说明发现未完成。config.md
  6. 仅 build 模式:编写 mock.ts 和 seed/。 如果应用有数据 fixture 文件,可复用,但绝不能使用导入了 @playwright/test 的文件:同一运行中出现两份副本会导致 Playwright 拒绝执行,并且整个语料库会因一个场景而失败。然后运行 DEMO_VOICE=0 scripts/demo --grep smoke。如果应用有 fixture API,也可复用(mocking.md)。查看静态截图:确认已登录、已植入数据、主题正确、非登录页面。查看捕获行。修复直到两者都正确,然后编写仅包含 smoke 运行证明的内容的 demo/ui.ts。
  7. 先编写脚本。 填写工作区的 profile.json(复制 template/profile.json;产品、受众、结束语、禁用词),然后根据 script.md 编写每一行:钩子、步骤、成果、结束语。钩子也要写入 hooks.json 以便生成变体版本。按照用户要求及范围进行录制。 一个命名的功能就是一个场景:编写、录制、交付。不要用“录制首页搜索”的请求给出十个场景的提案,也不要因为产品包含更多功能而悄悄扩大需求。只有当请求为整个产品时,才提出 6 至 10 个场景,每个场景一个标题和一行简介(按导览顺序),并询问先录制哪一个。
  8. 暂停。 录制那个场景并加入旁白。确认旁白字数与 say 调用一致,没有超时,语速正常。查看每一张静态截图。将 mp4 文件路径提供给用户,并就措辞风格、缩放程度、节奏和声音进行询问。在用户回答前,不要编写任何其他内容。
  9. 然后通过 --grep 每次批量录制三到四个场景;清单会合并。每批后查看静态截图。迭代场景时使用 DEMO_BUILD=0 scripts/demo 跳过重建(二十秒替代四分钟);在生成最终语料库的运行中撤除此设置。
  10. 使用 DEMO_CAPTIONS=1 DEMO_TRACE_FRAMES=1 进行完整运行,然后运行 scripts/check.mjs <out> 并打开 <out>/index.html。报告捕获表格、任何慢速剪辑以及检查中标记的所有问题。
  11. 变体版本。 询问用户需要哪些变体,除非他们已指定: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/ 的修改会立即影响机器上的所有项目:直接在那里编辑即可,无需传播。

相关技能