关于 psychopomp
psychopomp 是用于制作软件变更解说短片的技能,要求先核实变更事实,再编写旁白并构建场景。它将动画视觉节拍与旁白短语对齐,并涵盖审阅和渲染流程。
主要功能
- 01依据差异和测试核实变更
- 02编写分片旁白脚本
- 03用可复用组件组合动画场景
- 04将视觉节拍对齐到转录短语
- 05审阅并渲染完整短片
适用场景
- 01用动画场景解释拉取请求
- 02制作带旁白的代码前后对比讲解
- 03用定时标注和计数器展示行为变化
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ kitlangton/ psychopomp --skill psychopomp安装后在 Claude Code 中输入/psychopomp确认已加载。
附带文件STORY.md
详细介绍
Psychopomp 讲解短片
讲解短片由多个独立编写的 Scene Plan 在同一时间轴上拼接而成:GPU Stage 上的行为故事(光球、卡片、光束、数据包、摄像机、泛光)、固定 Callout、滚动数字、以动画阶梯差异呈现的更改、终端风格字幕,以及可选的配音。添加配音后,每个视觉节拍都会等待转录稿中的对应短语,因此重新配音会自动调整影片的时间安排。
可参考的示例位于 scenes/pr-walkthrough:src/flagship.rs(以 Stage 影片形式呈现 #50825,并缩放至其代码)、src/stop_stage.rs(结合 Stage、Callout、滚动数字,并缩放至带注释的代码差异,呈现 #50042),以及 src/lib.rs(包含时序图的五个 PR 短片)。沿用它们的结构;不要从空白 crate 开始。组件负载、通道和命令见 SCENE_PLANS.md(“制作配音讲解短片”),术语见 CONTEXT.md;开始编写前请先阅读两者。工程规则见 AGENTS.md。
步骤
-
确认事实。 对于每项更改,阅读实际差异和 PR 描述 (
gh pr diff、gh pr view),并分别用一句话描述出错的行为、 修复后的行为和具体更改。完成标准:你要配音的每项说法都能追溯到 代码、测试或复现结果;标出任何无法验证的内容,并将其排除在脚本之外。 -
编写脚本,保存为
scenes/<name>/narration/script.json,每个部分对应一个片段: 开场,然后每项更改依次为<slug>-before、<slug>-after、<slug>-code,最后是结尾。 编写时遵循 STORY.md。完成标准:每个片段的配音时长约为 30 秒以内, 且每个计划中的视觉节拍都有独特的锚点短语。 -
配音(可选)。 先在不使用凭据的情况下起草(
--draft使用 macOSsay),或者使用 ElevenLabs(engine: "elevenlabs",默认模型为eleven_v4) 或 Fish Audio(engine: "fish")合成最终配音:{ "engine": "elevenlabs", "model": "eleven_v4", "voice": "<elevenlabs-voice-id>", "settings": { "stability": 0.5, "similarity": 0.7 }, "clips": [ { "id": "change-before", "text": "[warm, conversational voice] ..." } ] }# Draft (no API key required) bun scripts/narrate.ts scenes/<name>/narration/script.json --draft # ElevenLabs (requires ELEVENLABS_API_KEY and script.voice) ELEVENLABS_API_KEY=... bun scripts/narrate.ts scenes/<name>/narration/script.json # Fish Audio (requires FISH_AUDIO_API_KEY) FISH_AUDIO_API_KEY=... bun scripts/narrate.ts scenes/<name>/narration/script.jsonscripts/narrate.ts会规范化响度、使用 Whisper 转录词语时间,并写入<id>.mp3、<id>.words.json和narration.json。切换声音或引擎时,请根据新的词语时间重新构建 Scene Plan。或者在 Scene Program 中声明配音,使用
psychopomp-media(SCENE_PLANS.md, “声明配音和声音”):media.say(id, &voice, text)、media.dialogue、media.sfx和audio.derive(Effect::pitch(..)),然后media.finish()?。每行只生成一次,并记录在media.lock.json中;之后除非声明发生变化,否则运行时不会调用任何内容,而 ElevenLabs 的词语时间会根据其字符对齐结果和脚本拼写生成。先用PSYCHOPOMP_MEDIA=plan cargo run -p <crate>检查费用(不会发起 API 调用), 用PSYCHOPOMP_MEDIA=draft计时,并用PSYCHOPOMP_MEDIA=prune清理。使用cargo run -p psychopomp-media -- adopt scenes/<name>/narration迁移 narrate.ts 场景 (不会重新生成)。完成标准:普通运行时每个资源都显示=。 -
编写场景程序,放在
scenes/<name>中(工作区会自动识别;在verify.json中添加几个关键时间点)。 使用psychopomp::score(SCENE_PLANS.md,「使用 Score DSL 编写」),确保PlanBuilder是唯一的mut绑定,且每个角色(Stage、Camera、Caption、Callout、RollingNumber、Checklist、Meter、Bars、Subtitles、Confetti、Terminal、Chat、ChangedFiles、LowerThird、Lens)都是不可变值,其方法会返回可组合的Beat(.then、.also、.with、.on_end、.after、.early、stagger、each、at!(scene, time => ...))。使用Narration::reading安排片段,使用StageElement::card|orb|beam|packet|label|ring和相对的psychopomp::layout::Placement包络,在StagePost::RESTRAINED上构建元素; 使用Caption::header|chip|footer添加画面说明,并使用sfx::*.beat(id, gain_db)播放音效(或在psychopomp-media中使用audio.beat(gain_db))。加载explainer-motion技能并将其应用到每个节拍:卡片使用settle_in,光束使用connect, 消息使用send,回复等待.reply(),冲击使用hit,主角使用orb_in, 修复过程使用rewind;使用Callout将注释固定到舞台元素或编辑器代码范围, 使用RollingNumber显示实时计数器和计时器;通过stage.camera()(establish、frame、follow、release、orbit、whip、dolly_zoom)控制镜头移动。优先使用可视化和文字叠加, 而不是用 Stage 标签和圆环手动构建:用Checklist展示运行并解决的检查项, 用Meter(MeterPlan::countdown)显示超时圆环,用Bars展示前后数值, 用Confetti呈现成功节拍,用Subtitles(SubtitlesPlan::from_spoken)烧录按词计时的字幕。 变更由Diff组成,包含keep、add(step)和remove(step)行,每个 step 都对应一个短语。 当cargo run -p <crate>写入视频片段,且cargo run --release -- plan validate <reel>报告有效时,即为完成。缺少短语会连同其片段一起触发 panic: 将锚点改为转录中实际包含的词语。 -
渲染前先检查。 使用
plan inspect <reel>获取片段跨度,然后为每个片段的开始、切换、结束和代码节拍生成联系表:bun scripts/sheet.ts <reel> t1,t2,... --theme neutral --shutter --out output/sheet.jpg调整外观时,设置
PSYCHOPOMP_SHADER_DIR=crates/psychopomp-render/src/render并编辑stage.wgsl/stage_post.wgsl:每一帧和联系表都会应用着色器编辑,无需重新构建 Rust。 然后为一个行为片段渲染含音频的视频(plan render <reel> out.mp4 --cue <scene-id>), 或渲染 2–3 秒的时间窗口(--range a..b),并检查从运动过程中提取的帧。所有片段都检查过,且没有文字重叠、裁切或对应错误的芯片时,即为完成。 -
渲染并验证整个视频片段;仅在联系表和短时间窗口检查通过后执行一次。使用较长的超时时间在前台运行,且在任务仍在运行时绝不要结束这一轮:
cargo run --release -- plan render <reel> output/<name>.mp4 --theme neutral当
ffprobe显示分辨率为 1920x1080、帧率为 60 fps、音频为 AAC,时长与plan inspect相符,响度接近 -16 LUFS 且峰值低于 -1 dBFS 时,即为完成。 -
交付 MP4 路径。使用符合规范的提交消息,将场景、旁白素材以及 Psychopomp 中的任何引擎变更一并提交。
改进 Psychopomp
当某个 reel 需要引擎无法实现的功能时,应将其添加到 Psychopomp,而不是在某个场景中另辟蹊径:在 crates/psychopomp 中规划类型并进行验证,在 plan_runtime 中进行严格通道预检,在 render 中处理像素,添加不依赖 GPU 的测试和一个 #[ignore] GPU 测试,并及时更新文档 AGENTS.md。更改前运行 cargo run --release -- verify baseline,更改后运行 verify compare --expect <scenes you changed>,以证明其他所有展示项目和影片均未受影响。
从小型、可复用的组件着手构建。插值、缓动、曲线、形状接口和连接器应放在 psychopomp::math 中(按 pmndrs math 的结构组织:核心包括 lerp/
remap/smoothstep,以及 easing、curve、shapes、random;向量使用 glam)。应扩展这些组件,而不是在渲染器或场景中内联数学运算,并将渲染器拆分为每个元素对应一个小型辅助函数,如 render/stage.rs 所示。确保 cargo fmt --check、cargo clippy --workspace --all-targets --all-features -- -D warnings 和 cargo test --workspace 均通过。