Home / All Skills / Content & Media Creation / pr-to-video
Content & Media Creation · heygen-com/hyperframes

pr-to-video

Turn a GitHub pull request (a PR URL, owner/repo#N, or 'this PR' in a checked-out repo) into a code-change explainer video — changelog, feature reveal, fix, or refactor walkthrough built from the diff, commits, and files: the input is a code change, not a website. Not a product promo (/product-launch-video) or a no-PR topic explainer (/faceless-explainer). Unclear → /hyperframes.

L4 High-Privilege · Graded auth & full auditV1 Commit-PinnedExecute CommandNetwork AccessWrite FileDual-pass Audit
Author heygen-comGitHub heygen-com/hyperframes ↗Stars 44283License Apache-2.0(仓库根 LICENSE 为 Apache License Version 2.0;池内值亦为 Apache-2.0)Commit d2f0bc7f34
Control levels describe skill capabilities and suggested control measures; they do not represent quality or safety certifications, nor do they dictate usability. Usage decisions rest entirely with users and administrators. Different agent hosts apply varying constraints; do not assume hosts provide automatic protection. Third-party skill copyrights belong to their original authors. Use at your own risk.

1How It Works & Mechanism

Orchestrator pattern: PR-to-video workflow is broken down into 7 sequential steps (Step 0 setup → 1 ingest → 2 design system → 3 storyboard/script → 3.1 audio → 4 visual design → 5 frames → 6 finalize), all executed sequentially by the orchestrator itself except Step 5 which dispatches frame workers, with explicit gates at every step.

skills/pr-to-video/SKILL.md
User-gated steps are Step 0, Step 3, and Step 6.
What happens here: Hardcodes 'who does what and when to pause'—strictly forbids mid-process reviews outside three specific user gates; parallelism in Step 5 occurs only across frame-level work orders.

Input is strictly defined as a 'code change', not a website: reads PR via gh, contains no capture step, and utilizes no real-world media assets other than contributor avatars.

skills/pr-to-video/SKILL.md
The input is a **code change** (read via `gh`), not a website — there is **no capture step and no real assets** beyond the contributors' avatars.
What happens here: Clearly differentiates from web-crawling workflows (such as product-launch-video); 'no external media' dictates that subsequent visuals must be invented via code, charts, and mechanism animations.

Step 1 is deterministic ingestion: fetch-pr.mjs runs gh to fetch core PR objects and uses paginated gh api calls to complete the files list (gh pr view caps at ~100 files), writing only capture/pr.json and capture/diff.patch without temporary directories; for MERGED PRs, it attempts to resolve a real shipped_version.

skills/pr-to-video/scripts/fetch-pr.mjs
// gh pr view --json files caps at ~100 files; the REST endpoint paginates with no
What happens here: Replaces 'agent-driven step-by-step scraping' with a deterministic script (preventing videos/ directory pollution and unreproducible behavior) and ensures closing cards do not guess version numbers; gh errors (unauthenticated/missing/private) exit with code 1 emitting native gh stderr, prompting the orchestrator to halt immediately rather than hallucinate content.

Projects are placed in a resolved external directory, never creating videos/ inside the caller's repository: resolves PR reference → parsed by project-dir.mjs (overridable via PR_TO_VIDEO_PROJECT_DIR) → preflight CLI capability checks → runs init only if hyperframes.json is missing.

skills/pr-to-video/SKILL.md
Never create `videos/` in the caller repository:
What happens here: Enforces 'do not pollute caller repo' as an executable constraint; preflight runs first to prevent discovering too late that installed CLIs lack required commands (e.g., check).

Style is fixed to code-editorial without user prompting: build-frame.mjs copies the preset FRAME.md and blends in brand tokens (PR lacks branding → colors:[]/fonts:[]), then duplicates the caption skin and self-validates.

skills/pr-to-video/SKILL.md
The style is fixed — **code-editorial** (warm editorial; a navy code surface built for diffs).
What happens here: Eliminates the 'style selection' gate that slows down the workflow (Step 2 requires zero user interaction), as PR explanations require a dark code-centric canvas capable of rendering diffs.

Narrative discipline in Step 3: sequence stems from narrative design rather than the diff's file order, quantified via 'word budget' (TTS ≈2.2 words/sec, soft target ≤19 words/≤9s per frame, hard cap >26 words/>12s, full video sweet spot ~30–90s).

skills/pr-to-video/references/story-design.md
Scene order comes from narrative design, not from the diff's file order or the commit list.
What happens here: Marks the most common failure (reciting diffs file-by-file) as a red line, providing four PR archetypes (changelog / feature-reveal / fix-explainer / refactor-walkthrough) along with a 'value before evidence' sequence. Explicitly notes: 'The largest quality bug in PR videos is scripts that talk too long.'

Code beats are delegated to registry code-* primitives (code-diff / code-morph / code-typing / code-highlight, etc.), requiring inspection of the live catalog before writing manually; non-code 'mechanism beats' require invented animations/flowcharts/data charts.

skills/pr-to-video/references/code-vocabulary.md
**Reach for one of these first** for any code beat; fall back to hand-authored composition only when none fits.
What happens here: Replaces 'manually hand-coding diff animations' with 'installing official primitives + inserting actual hunks'; primitives are self-contained sub-compositions (inlined engine + paused GSAP timelines), deterministic and seekable, strictly forbidding Math.random and Date.now.

Step 5 uses bounded parallelism: frame packets are generated by frame-packets.mjs (hard failure for code frames missing ### Source excerpt, with strict byte limits), dispatching to a maximum of 3 workers where each worker reads only its assigned packet and frame.md; frame failures trigger at most one retry per frame with concrete findings attached.

skills/pr-to-video/SKILL.md
Dispatch **at most three workers total**, balanced across the packet paths
What happens here: Maximizes context efficiency via 'packetization + role file composition (_role.md = frame-worker-core.md + frame-worker.md from this skill)'; caps retries at one to prevent budget burnout from re-running entire batches.

Validation phase is restrained: lint + check + snapshot contact sheet, with documentation pre-identifying a known false positive (caption highlight text_box_overflow 1–4px) that must not be pursued; rendering strictly requires user approval.

skills/pr-to-video/SKILL.md
**Known false-positive — do not chase it.**
What happens here: Codifies 'which warnings to address vs. ignore' into the pipeline (handling only overflows tied to frame elements), enforcing mandatory gates before rendering: lint/check pass + contact sheet inspected + explicit user approval.

2Core Capabilities

01PR ingestion: gh fetches core PR objects + paginated file list completion + full diff extraction, producing capture/pr.json and capture/diff.patch (untruncated for large PRs, no temp directories, resolves real shipped_version when MERGED)
02Offline capture package synthesis: ingest.mjs parses pr.json + diff.patch to generate tokens.json (color → code-editorial palette), visible-text.txt (source briefing), and people.json (contributors, bots filtered)
03Fixed code-editorial design system: build-frame.mjs copies code-editorial preset and blends brand tokens, generating frame.md + .hyperframes/caption-skin.html with self-validation
04Storyboarding and scripting: four PR archetypes (changelog / feature-reveal / fix-explainer / refactor-walkthrough), PR-native frame types (hook/problem/change/diff/before_after/mechanism/impact/evidence/credits/cta), and word-count-quantified frame budgets
05Audio pipeline: narration (HeyGen or local Kokoro), word-level timing, BGM search, SFX retrieval, and actual speech duration backwritten to STORYBOARD; supports explicit silence tokens
06Frame-level parallel construction: frame-packets.mjs produces bounded work orders (hard failure on missing Source excerpts in code frames, strict byte caps), with up to 3 workers each reading only their assigned packet and frame.md
07Transitions and assembly: transitions.mjs injects and validates inter-frame transitions (crossfade / blur-crossfade / push-slide / zoom-through / squeeze), assemble-index.mjs builds playable index.html and stages contributor avatars as an idempotent fallback
08Captions and delivery proof: captions.mjs builds caption sub-compositions using project caption skin, snapshot generates contact sheets for visual inspection prior to final MP4 rendering
09Contributor credits frame (sole real media asset): downloads avatars against GitHub host whitelist, validates paths to prevent escaping project dir, always exits with code 0 on failure; narration speaks full names instead of @handles

3External Dependencies

KindDependency / Endpoint
cliGitHub CLI(gh):pr view / pr diff / api 分页 / users/<login> 取显示名——摄取 PR 的唯一通道
apiGitHub 用户 API(解析 null 显示名,供 credits 帧旁白念姓名)
network贡献者头像下载(白名单仅 GitHub 头像主机;github.com/<login>.png 302 到 avatars.githubusercontent.com)
cli官方 hyperframes CLI:init / add / catalog / lint / check / snapshot / preview / render(--skill=pr-to-video)
apiHeyGen 音频后端(BGM 检索;TTS 由同一个共享音频引擎承担,signed in 时走 HeyGen、离线走本地引擎)
package兄弟 skill 依赖(被指名调用):/media-use(BGM/SFX/图像/logo 来源与音频引擎)、/hyperframes、/hyperframes-core、/hyperframes-animation(rules/blueprints)、/hyperframes-creative(帧 preset)
networkCDN 资源(产物期):组装的 index.html/captions.html 引用 GSAP,带 SRI 与 crossorigin
package共享音频引擎路径可用环境变量覆盖(HF_MEDIA_ENGINE),默认指向 /media-use 的 audio.mjs

4Recommended Governance & Evidence

Suggested Controls for Safe Operation
For Agent Runtime
Graded/per-use authorization, sandbox recommended
For Administrators
Approval workflow, rollback support, full audit
Evidence & Triggers (File Paths & Excerpts)
  • scripts/: Execute local script or command: node <SKILL_DIR>/scripts/project-dir.mjs --pr "$PR" (resolves project directory; configurable via PR_TO_VIDEO_P
  • 网络端点: Declare external network access: GitHub: all PR reads go through gh (github.com + api.github.com), gh handles auth and retries; large PR file lists use paginated API calls
  • 本地工作目录: File I/O and artifact output: Within PROJECT_DIR (never in caller repo): capture/{pr.json,diff.patch,extracted/{tokens.json,
Audit Notes: Both conditions triggering the Orange tier are met and verifiable within the skill's own directory: ① Credentials surface: fetch-pr.mjs first runs `gh auth status` and reads PRs using the user's GitHub identity (SKILL.md explicitly supports private repos), and the audio step shares `~/.heygen` credentials with TTS; ② Transmission of user assets to external backends: the audio step sends scripts and requirements to HeyGen's audio backend (search/synthesis, consuming account credits; falls back to local engine offline), and avatars are fetched as external assets from GitHub. Precedents like product-launch-video and media-use (reading ~/.heygen) are similarly classified as Orange. No Red tier behavior found (no TLS downgrade, no sandbox tampering, no detection evasion, no arbitrary code execution; subprocess calls use fixed binaries and scripts); exceeds Yellow tier (Yellow covers fixed public endpoint queries, whereas this involves authenticated writable backends and private repository access). Trigger conditions: requires gh and HeyGen authentication to touch credentials and external backends; without gh authentication, the workflow halts immediately at Step 1.

5Second-Pass Verification

  • [ok] gh 凭证是否真被使用(橙档证据之一) — fetch-pr.mjs 顶部注释写明「gh runs HERE so auth / not-found / private-repo errors surface with gh's own stderr and exit 1」,实现里第一步就是 `if (!ghTry(["auth", "status"]).ok) { die("gh is not authenticated — run: gh auth login"); }`,随后 pr view / api 分页 / pr diff 三处都用同一 execFileSync 包装。调用点真实存在。
  • [ok] HeyGen 凭证与 TTS/BGM 实现到底在谁身上(避免把别家行为算进档位) — 本 skill 的 scripts/audio.mjs 头注释自述「The TTS / BGM / SFX implementation no longer lives here: it is the shared engine at ../../media-use/audio/scripts/audio.mjs」,实现只做 SCRIPT/STORYBOARD → audio_request.json 的映射与回写;凭证读取发生在被指名的姊妹 skill 内。按范式「他人 skill 被指名调用只写进 reason、不作档位依据」,橙档依据只用本目录自身可取证的两条:SKILL.md 明写音频共用 ~/.heygen 凭证,以及 fetch-pr.mjs 的 gh 凭证依赖。
  • [ok] 头像下载的防护是否真实(是否只是口号) — fetch-people-avatars.mjs 里有 AVATAR_HOSTS 白名单 + isAllowedAvatarUrl(拒绝非 GitHub 主机)与 isUnderProject(写入路径必须在项目目录内,防 ../../ 逃逸),并以 softExit 保证任何失败都 exit 0;注释解释了 github.com/<login>.png 302 到 avatars.githubusercontent.com 属同主控重定向。防护与注释一致,非表面文章。
  • [discrepancy] 「无 asset-staging 步骤」的声明与随包代码是否一致 — SKILL.md Step 4 明写 `There is **no asset-staging step** — the only real assets are the credits avatars, already in `assets/`。`,但 scripts/lib/assets.mjs 的头注释仍写着「Shared by stage-assets.mjs (Step 4 close, BEFORE the frame workers run) and assemble-index.mjs (Step 5, idempotent backstop)」,而 **pr-to-video 目录内并不存在 stage-assets.mjs**(该脚本只存在于同仓 product-launch-video 与 music-to-video),assemble-index.mjs 第 521 行也仍在注释里引用它。结论:这是复用姊妹 skill 时残留的过期注释(audio.mjs 自述该适配层在复用者之间「intentionally identical」,可解释来源);实际行为与 SKILL.md 一致(只有 assemble-index 作为幂等兜底暂存头像),但读者若去找 Step 4 的 stage-assets 会找不到——对 pin commit 有效的真实出入。
  • [ok] 是否漏掉未声明的网络调用 — 全目录 URL 命中仅 5 处:两处 gsap CDN(assemble-index.mjs 与 captions.mjs,产物期)、一处 ingest.mjs 的 `https://github.com/${login}.png?size=200` 头像 URL、两处测试文件里的 PR fixture URL;fetch( 仅出现在 fetch-people-avatars.mjs(带白名单);无其它隐藏端点。
  • [ok] 「Step 1 无 capture、只读 gh」与脚本能力是否相符 — fetch-pr.mjs 只写 capture/pr.json 与 capture/diff.patch(头注释明确 no scratch dir),ingest.mjs 是纯离线变换,两者都不抓网页;Quick Reference 亦写明「no Step 1 capture」。与 description「the input is a code change, not a website」一致,无夸大。

6Verdict & Scenarios

  • Deterministic script ingestion instead of step-by-step agent scraping: paginated gh api calls complete file lists for large PRs, produces exactly two artifacts, and exits cleanly with native gh errors upon failure
  • Actionable narrative discipline: four archetypes + PR-native frame types + word count budgets (≤19 words/≤9s soft target, >26 words hard cap), strictly prohibiting diff-reading recitals
  • Bounded parallelism with context efficiency: frame packets hard-fail on missing code excerpts, enforce strict byte caps, limit concurrency to at most 3 workers, with each worker reading solely its assigned packet
  • Restrained repair discipline: single-frame failures trigger re-dispatch only for that specific frame, capped at one attempt with concrete findings attached, avoiding full-batch re-runs
  • Rigorous edge-case handling: ignores documented false positives, incorporates SSRF and path traversal protections on avatar downloads without blocking pipeline, and falls back to URLs when version numbers cannot be resolved
  • Best for: Designed for teams seeking to turn a GitHub PR into a publishable code-change explainer video (changelog, feature reveal, bug fix explanation, or refactor walkthrough): takes only a PR URL or owner/repo#N as input and yields an MP4 (ranging from 8-second shorts to 1–3 minute overviews) featuring code-editorial styling, authentic diff snippets, mechanism animations, and contributor credits frames; also ideal as a standardized production line for 'scripted PR retrospectives' with strict per-frame word count and timing constraints.
    Not for: Not suitable for: ① Scenarios without a PR (topic explainers without PRs should use /faceless-explainer; product promos should use /product-launch-video); ② Workflows requiring existing footage/assets (screenshots, screen recordings, brand films) — this pipeline uses only contributor avatars, generating all other visuals via code, diagrams, or animations; ③ Environments where gh is not authenticated and cannot log in (Step 1 halts immediately); ④ Projects requiring custom visual branding/styling (style is fixed to code-editorial without selection); ⑤ Users unwilling to send script text through HeyGen who also reject offline TTS quality.
    Install Agent-Ready
    ① Verified Mirror 2026-09-28
    Option A · Direct DownloadDownload pr-to-video.tar.gz
    sha256: 8f260d47a576b3e2…
    Option B · Copy Guide for Agent
    install.json
    Agents automatically download and verify mirrors from this JSON guide.
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit d2f0bc7f34.