pr-to-video

pr-to-video

热门

将 GitHub 拉取请求(PR URL,如 github.com/<owner>/<repo>/pull/<N>,或 <owner>/<repo>#<N> 引用,或已检出仓库中的 'this PR')转换为代码变更解说视频,时长最长约 3 分钟(最佳时长 30-90 秒)—— 变更日志、功能展示、修复或重构讲解,基于 diff/提交/文件渲染。输入是通过 gh CLI 读取的代码变更,不涉及网站捕获。此技能用于 GitHub PR。请勿用于产品发布/推广(使用 /product-launch-video)、真实网站导览(使用 /website-to-video)、无 PR 的主题讲解(使用 /faceless-explainer)、现有素材的字幕(使用 /embedded-captions)或短篇无旁白动态图形(使用 /motion-graphics)。若意图不明确,请先通过 /hyperframes 路由。

3.1万Star
3036Fork
更新于 2026/6/25
SKILL.md
只读
名称
pr-to-video
描述

将 GitHub 拉取请求(PR URL,如 github.com/<owner>/<repo>/pull/<N>,或 <owner>/<repo>#<N> 引用,或已检出仓库中的 'this PR')转换为代码变更解说视频,时长最长约 3 分钟(最佳时长 30-90 秒)—— 变更日志、功能展示、修复或重构讲解,基于 diff/提交/文件渲染。输入是通过 gh CLI 读取的代码变更,不涉及网站捕获。此技能用于 GitHub PR。请勿用于产品发布/推广(使用 /product-launch-video)、真实网站导览(使用 /website-to-video)、无 PR 的主题讲解(使用 /faceless-explainer)、现有素材的字幕(使用 /embedded-captions)或短篇无旁白动态图形(使用 /motion-graphics)。若意图不明确,请先通过 /hyperframes 路由。

media-use:在获取音频/图片前,先调用 /media-use 从 HeyGen 目录中确定 BGM/SFX/图片。先运行 --adopt 注册已有资源。参见 /media-use 技能。

PR 到 HyperFrames

使用此技能来摄取 GitHub 拉取请求,理解变更,规划代码变更解说视频,并在 HyperFrames 中逐帧构建。输入是代码变更(通过 gh 读取),而非网站——没有捕获步骤,也没有真实资源,除了贡献者的头像。

在步骤 0 之前确认路由。 你是编排者。运行每个步骤,验证其关卡,然后继续。此技能适用于 GitHub 拉取请求(代码变更)。将其他意图路由到别处:产品发布/推广 → /product-launch-video;通用网站导览 → /website-to-video;无 PR 的主题讲解 → /faceless-explainer;现有素材的字幕 → /embedded-captions;短篇无旁白动态图形 → /motion-graphics;整个仓库或多 PR 的发布讲解 → /general-video超出范围: 实时/渲染时数据——PR 事实仅在创作时读取一次并固化。如果用户只说“制作视频”或路由不确定,请先阅读 /hyperframes

你是编排者。在 videos/<project>/ 中工作。按顺序运行步骤,并在继续前通过每个关卡。用户关卡为步骤 0、步骤 3 和步骤 6。除步骤 5(你为每帧分派一个子代理)外,自行执行每个步骤。不要在此处放置设计或运动规则;这些位于帧工作子代理、hyperframes-creativehyperframes-animation 中。

工作流程:步骤 0 设置 → hyperframes.json;步骤 1 摄取 → capture/extracted/ + assets/<login>.png;步骤 2 设计系统 → frame.md;步骤 3 故事板/脚本 → STORYBOARD.mdSCRIPT.md;步骤 3.1 音频 → audio_meta.json;步骤 4 视觉设计 → 增强的 STORYBOARD.md;步骤 5 帧 → compositions/frames/NN-*.htmlindex.html;步骤 6 最终渲染 → renders/video.mp4


步骤 0:设置与简报

目标:锁定 PR 引用和核心视频简报,并在需要时创建 HyperFrames 项目。

获取 PR 引用(完整 URL、<owner>/<repo>#<N> 引用,或已检出仓库中的“this PR”),并在一条消息中确认简报——为每项提供推荐默认值,并预填 /hyperframes 已设置的任何内容:角度(变更日志 / 功能展示 / 修复讲解 / 重构讲解——默认:从 PR 推断)、受众(默认:开发者)、时长(默认:根据 PR 变更规模缩放——见下文)、宽高比(默认 16:9)、语言。风格始终为 claude。仅在用户回复后继续;“go”表示接受默认值。

根据 PR 的变更规模推荐时长,而非固定猜测。在确认简报前,先只读查看一次 PR——该调用也用于确定角度(步骤 1 仍执行完整的确定性获取):

gh pr view <PR_REF> --json title,additions,deletions,changedFiles

根据 additions + deletions(由 changedFiles 微调)选择层级,并将其作为默认值推荐(用户可覆盖;硬上限约 3 分钟):

PR 变更规模 推荐时长
微小(≲ 50 行变更) 约 20-40 秒
集中(约 50-200 行) 约 40-70 秒
较大(约 200-600 行) 约 70-110 秒
大型(≳ 600 行,或 25+ 文件) 约 110-180 秒

在提出时用一句话说明依据(例如“约 40 秒——小变更,+44/−13 跨 12 个文件”)。大型 PR 不意味着长视频——如果故事只有一个重点变更,保持紧凑并说明。

仅在 hyperframes.json 缺失时初始化。以 kebab-case 形式从 PR 命名 <project>,例如 acme-sdk-pr-1842;切勿使用工作区名称或时间戳。

npx hyperframes init "videos/<project>" --non-interactive --skip-skills --example=blank

在简报前显示登录状态——运行 npx hyperframes auth status逐字输出其结果(不要转述或重写)。 它报告语音/BGM 将使用 HeyGen 还是本地引擎,以及未登录时如何登录。如果未登录,停止并等待用户选择——登录,或说“go”/“offline”以使用本地引擎继续——然后再询问简报或其他任何内容。 将其视为真正的决策点,而非附带说明;不要将选择并入简报问题,也不要将密钥写入每个仓库的 .env。(在自主模式下,记录状态并离线继续。)参见 ../hyperframes-media → Preflight 获取规范指导。

关卡: hyperframes.json 存在;PR 引用已捕获;角度、时长、宽高比和语言已锁定;登录状态已显示(已登录,或继续离线)。


步骤 1:摄取 PR(无捕获)

目标:获取 PR 的事实并将其纳入项目作为信息来源。没有网站捕获fetch-pr.mjs 确定性运行 gh——通过分页的 gh api 完成文件列表,因此大型 PR 不会在约 100 个文件处截断,并仅写入 capture/pr.json + capture/diff.patch(无临时目录)。然后 ingest.mjs 将其离线折叠到合成捕获包中。

PR="<url | owner/repo#N | N>"

# 确定性获取 PR:运行 gh,通过分页的 gh api 完成文件列表
# (因此大型 PR 不会在约 100 个文件处截断),仅写入 capture/pr.json +
# capture/diff.patch — 无临时目录。gh auth / not-found / private 错误在此退出 1。
(cd "videos/<project>" && node <SKILL_DIR>/scripts/fetch-pr.mjs --pr "$PR" --out-dir ./capture)

# 离线转换 → capture/extracted/{tokens.json (colors:[] → claude 调色板),
# visible-text.txt (简报), people.json (贡献者, 过滤机器人, avatarFile=assets/<login>.png)}。
(cd "videos/<project>" && node <SKILL_DIR>/scripts/ingest.mjs \
  --pr-json ./capture/pr.json --diff ./capture/diff.patch --out-dir ./capture/extracted)

# 人员方面的唯一网络步骤——将每位贡献者的 GitHub 头像下载到
# assets/<login>.png,用于可选的致谢结尾。尽力而为;始终退出 0。
(cd "videos/<project>" && node <SKILL_DIR>/scripts/fetch-people-avatars.mjs \
  --people ./capture/extracted/people.json)

如果 fetch-pr.mjs 退出 1(gh auth / not found / private),报告其 stderr 并停止——不要编造 PR 内容。如果 ingest.mjs 退出 1,读取其 stderr(通常是格式错误的 pr.json),修复并重新运行(确定性)。fetch-people-avatars.mjs 始终退出 0;缺失头像仅意味着没有致谢结尾给作者。

关卡: capture/pr.jsoncapture/diff.patchcapture/extracted/tokens.jsoncapture/extracted/visible-text.txtcapture/extracted/people.json 存在;你能用一句清晰的话说明 PR 的变更。assets/<login>.png 是尽力而为——缺失不算失败。


步骤 2:设计系统

目标:采用 claude 帧预设;脚本将其转换为该视频的 frame.md + 字幕皮肤。

风格固定——claude(温暖编辑风格;为 diff 构建的海军蓝代码表面)。运行:

node <SKILL_DIR>/scripts/build-frame.mjs --preset claude --hyperframes .

脚本复制 claude 预设的 FRAME.mdframe.md,将其与 capture/extracted/tokens.json 中的任何品牌令牌混合(PR 没有 → colors:[]/fonts:[] 保留 claude 自己的调色板,完整设计),将预设的字幕皮肤复制到 .hyperframes/caption-skin.html,并自我验证(映射损坏时退出 1)。一旦退出 0 即继续——无需手动编辑。

关卡: build-frame.mjs 退出 0——frame.md 从 claude 预设存在,且 .hyperframes/caption-skin.html 作为字幕皮肤源存在。


步骤 3:故事板与脚本

目标:将 PR 转换为经批准的逐帧解释计划。

阅读 references/story-design.md../hyperframes-core/references/storyboard-format.md../hyperframes-core/references/script-format.md。使用它们编写 STORYBOARD.md,并在需要旁白时编写 SCRIPT.md

使用 story-design.md 获取 PR 原型(变更日志 / 功能展示 / 修复讲解 / 重构讲解)、PR 原生帧类型、钩子、说服、节拍、每帧字数预算以及可选的致谢结尾。顺序来自叙事设计,而非 diff 的文件顺序——解释变更,而非逐字朗读 diff。展示 2-4 个真实 diff 片段(来自 capture/diff.patch),每个为简短可读的片段;命名每个帧的 scene 所需的 code-* 块。帧不携带 asset_candidates,除了可选的 credits 结尾(2-6 个 assets/<login>.png 头像)。使用故事板和脚本参考中的确切必填字段。

草拟后,显示逐帧摘要。在同一条消息中询问用户(a)批准或请求更改,以及(b)是否希望实时预览故事板框架(npx hyperframes preview)——仅在回答“是”时打开。迭代直至批准;将预览选择带到步骤 6。

关卡: STORYBOARD.md 存在,每帧具有必需的叙事字段,需要旁白时 SCRIPT.md 存在,且用户批准了计划。


步骤 3.1:音频

目标:根据批准的脚本生成旁白、单词时间、音乐和音频元数据。

在步骤 3 批准后开始音频。在后台运行,然后继续步骤 4。

node <SKILL_DIR>/scripts/audio.mjs --script ./SCRIPT.md --storyboard ./STORYBOARD.md --hyperframes . --out ./audio_meta.json &

音频脚本处理旁白、单词时间、从 HeyGen 音乐库查找 BGM 以及时间元数据。BGM 情绪来自故事板的 music: 字段。这使用 HeyGen 音频 API 进行检索而非生成,并使用与 TTS 相同的 ~/.heygen 凭据。有关提供商详细信息,请阅读 ../hyperframes-media/references/tts.md

如果没有旁白且没有 SCRIPT.md,则跳过语音生成。如果故事板有音乐情绪,BGM 仍可能运行。

关卡: 音频作业已启动,或项目标记为静音。


步骤 4:帧视觉设计

目标:为每个故事板帧添加视觉方向、布局意图和运动选择。

原地编辑 STORYBOARD.md。不要创建另一个故事板。使用 frame.md 作为颜色、字体、布局感觉和风格的真相来源。

阅读 references/visual-design.mdreferences/composition.mdreferences/motion-language.mdreferences/code-vocabulary.md../hyperframes-animation/。使用 visual-design.md 获取必需的帧字段和必需的 ## Video direction 块,以及代码节拍如何将 code-* 块命名为其 focal。使用 code-vocabulary.md 为每个节拍选择正确的块(diff = code-diff,重构 = code-morph,新代码 = code-typing,……)。使用 composition.md 获取布局/层次/焦点,使用 motion-language.md + ../hyperframes-animation/ 获取有效的效果和蓝图 ID。不要发明效果名称或块/蓝图 ID。

对于每帧,添加必需的视觉和运动字段,包括 effectsfocal 和/或 roles。对于代码节拍,将 code-* 块命名为 focal,并让 effects 编排周围的 claude 代码表面(而非代码动画,该动画由块拥有)。添加一个视频范围的 ## Video direction 块。

不要更改故事、脚本、transition_inasset_candidates 或 PR 来源。不要在此步骤编写 HTML。没有资源暂存步骤——唯一的真实资源是致谢头像,已在 assets/ 中。

关卡: 每帧具有 effects 加上 focal 和/或 roles;代码帧命名 code-* 块;## Video direction 存在。


步骤 5:构建帧

目标:将每个故事板帧构建为 HTML 合成,并组装可播放的视频。

如果音频已启动,等待步骤 3.1 音频完成。然后同步时长并获取 SFX;如果静音则跳过两者。

node <SKILL_DIR>/scripts/audio.mjs sync-durations --audio-meta ./audio_meta.json --storyboard ./STORYBOARD.md

node <SKILL_DIR>/scripts/audio.mjs fetch-sfx --storyboard ./STORYBOARD.md --hyperframes .

时长同步是机械性的:真实语音时长优先;静音帧保留估计值;切勿手动编辑同步后的时长。

预安装注册表块,这些块在 STORYBOARD.md 中命名一次,在分派之前,以便并行工作线程不会在注册表上竞争:

for b in <each registry block named in the storyboard>; do npx hyperframes add "$b"; done

在分派前,阅读 sub-agents/frame-worker.md../hyperframes-core/references/subagent-dispatch.md。每帧分派一个子代理,尽可能并行;否则以波次运行工作线程。每个工作线程恰好获得一帧。每个工作线程的上下文必须包括 PROJECT_DIRframe_id、画布大小、字幕状态和启用字幕时的保留带、ANIM_DIR../hyperframes-animation/ 的绝对路径)以及 references/code-vocabulary.md 的绝对路径。每个工作线程读取 frame.md、其自己的 ## Frame N 块、每个引用的效果/蓝图 ID 的配方主体,以及——对于代码节拍——code-vocabulary.md 以获取命名块的输入。每个工作线程仅写入 compositions/frames/NN-*.html;工作线程从不编辑 STORYBOARD.md

当每个工作线程返回时,在 STORYBOARD.md 中将该帧标记为 animated

在音频时间存在后,在后台构建字幕并组装索引:

node <SKILL_DIR>/scripts/captions.mjs build --storyboard ./STORYBOARD.md --audio-meta ./audio_meta.json --hyperframes . --out ./caption_groups.json &

node <SKILL_DIR>/scripts/assemble-index.mjs --storyboard ./STORYBOARD.md --hyperframes .

captions.mjs 使用项目的 .hyperframes/caption-skin.html(claude 的,在步骤 2 中复制),从 frame.md 注入品牌令牌;captions: skipped (<reason>) 是有效的。assemble-index.mjsassets/ 中的致谢头像作为幂等后备暂存。

关卡: 每帧标记为 animatedindex.html 存在,且字幕已构建或明确跳过。


步骤 6:最终确定

目标:验证组装的视频,获取用户批准,并渲染最终的 MP4。

注入过渡,运行检查,暂停审查,然后渲染。

node <SKILL_DIR>/scripts/transitions.mjs inject --storyboard ./STORYBOARD.md --hyperframes .

node <SKILL_DIR>/scripts/transitions.mjs verify --storyboard ./STORYBOARD.md --index ./index.html

npx hyperframes lint

npx hyperframes validate

npx hyperframes inspect

npx hyperframes snapshot --at <frame-midpoints>

snapshot 将捕获的帧拼接成一个联系表(snapshots/contact-sheet.jpg)。快速浏览;如果没有明显损坏,继续——不要在此停留。

如果命令失败,显示 stderr 并停止——不要堆叠恢复命令。自行修复:对 compositions/frames/NN-*.html 进行最便宜的安全编辑,然后重新运行失败的检查。

已知误报——不要追究。 inspect 可能报告少量约 1-4px 的 text_box_overflow 错误,位于字幕高亮词(选择器 #caption-word-* / .caption-line)上。字幕药丸使用故意紧凑的 line-height(在 scripts/captions.mjs 中设置一次),并且没有 overflow:hidden,因此重显示字形的墨水会溢出几像素到药丸自己的内边距中——实际上没有内容被裁剪。将这些视为预期并继续。不要增大字幕 line-height(这会使药丸膨胀,更糟)。仅在 text_box_overflow 命名元素(#el-NN-*)而非字幕词时采取行动。

检查通过后,暂停等待用户审查。视频已组装、可查看,并可在 Studio 中编辑。仅在步骤 3 和步骤 6 之间管理一次预览:如果用户之前要求则打开,如果之前拒绝则提供,如果已在 Studio 中审查则不再询问。

预览:npx hyperframes preview

仅在用户批准后渲染:

npx hyperframes render --skill=pr-to-video --quality high --output renders/video.mp4

除非用户要求,否则不要在渲染后重新运行 lintvalidateinspectsnapshot

关卡: lintvalidateinspect 在渲染前通过;用户在审查暂停时批准;renders/video.mp4 存在。最终回复说明 MP4 路径和最终时长。


快速参考

格式: 默认横向 1920x1080;纵向 1080x1920;方形 1080x1080。在故事板前言中设置一次格式。

PR 差异与捕获资源工作流: 无步骤 1 捕获(gh CLI 将 PR 摄取到合成 capture/extracted/ 包中——tokens.json + visible-text.txt + people.json);唯一的真实资源是贡献者的 assets/<login>.png 头像(可选的致谢结尾);无 asset-descriptions.md,无资源暂存步骤。代码节拍由 code-* 注册表块在 claude 的海军蓝代码表面上渲染;风格始终为 claude

后台脚本: 工作流在 scripts/ 下提供这些脚本:fetch-pr(PR → capture/pr.json + diff.patch 通过 gh;大型 PR 安全,无临时文件),ingest(→ 合成捕获包;离线),以及 fetch-people-avatars(贡献者头像 → assets/);加上共享引擎——build-frame(采用预设并混合品牌到 frame.md + 字幕皮肤),audio(TTS、BGM、SFX、时长同步),captionstransitions(注入 + 验证),以及 assemble-index。其他一切都是 hyperframes CLI。代码块通过 npx hyperframes add <name> 安装。

阅读 时机
[references/story-design.md](references/story-design.md) 步骤 3:规划 PR 解释。
[../hyperframes-core/references/storyboard-format.md](../hyperframes-core/references/storyboard-format.md) 步骤 3:编写 STORYBOARD.md
[../hyperframes-core/references/script-format.md](../hyperframes-core/references/script-format.md) 步骤 3:编写 SCRIPT.md
[../hyperframes-media/references/tts.md](../hyperframes-media/references/tts.md) 步骤 3.1:选择或了解 TTS 提供商。
[references/visual-design.md](references/visual-design.md) 步骤 4:视觉上丰富故事板。
[references/code-vocabulary.md](references/code-vocabulary.md) 步骤 4 + 5:为代码节拍选择并填充 code-* 块。
[references/composition.md](references/composition.md) 步骤 4:判断构图。
[references/motion-language.md](references/motion-language.md) 步骤 4:判断运动语言。
[../hyperframes-animation/](../hyperframes-animation/) 步骤 4:引用效果和蓝图 ID。
[sub-agents/frame-worker.md](sub-agents/frame-worker.md) 步骤 5:分派每帧工作线程。
[../hyperframes-core/references/subagent-dispatch.md](../hyperframes-core/references/subagent-dispatch.md) 步骤 5:安全分派子代理。
[../hyperframes-creative/frame-presets/claude/FRAME.md](../hyperframes-creative/frame-presets/claude/FRAME.md) 步骤 2:claude 预设(固定风格)。