presentation-video
This skill should be used when the user asks to "make an animated presentation", "turn a pitch deck into a video", "convert slides/a deck to video", "make a presentation video", "build a deck video", "narrate a slide deck as a video", or "auto-advance slides synced to a voiceover". Covers rebuilding slides as motion graphics with staggered build reveals, slide-to-slide transitions, and timing locked to per-slide narration.
1How It Works & Mechanism
The core premise is rebuilding rather than screen recording: screen recording inherits static visuals, mouse jitter, and hard cuts, whereas rebuilding achieves frame determinism, ease-able transitions, crispness at any resolution, and audio-driven durations.
A screen-recording inherits the deck's static look, mouse jitter, and abrupt slide cuts. Rebuilding in code (Remotion) buys: per-frame-deterministic reveals, transitions that actually ease, text that stays crisp at any resolution, and slide durations driven by audio length.
Narrative-first: define a one-sentence spine first, convey only one idea per slide, and make slide titles assertions rather than labels.
- **One throughline (the spine).** State the deck's single takeaway in one sentence. Every slide must advance that sentence; if a slide doesn't, cut it or move it to an appendix.
The single iron rule: narration controls the clock—each slide's duration = measured audio length for that slide + a small handle; guessing visually is prohibited.
**Each slide lasts exactly as long as its narration audio, plus a small handle.** Measure every voiceover clip's real duration, convert to frames, and make that the slide's length.
Each slide's audio is mounted within its own component: audio and visuals are positioned by the same Sequence, making drift physically impossible.
Because the audio lives inside the same component that draws the visuals, and both are placed by the sequencer at the same start frame, voice and picture physically cannot drift.
Account for transition frame budgets: transitions in TransitionSeries overlap rather than add time, consuming frames from neighboring slides.
A `<TransitionSeries.Transition>` does **not** add time — it overlaps its neighbors, consuming frames from the end of the outgoing slide and the start of the incoming one.
In-slide build reveals must sync with narration: elements appear the moment they are spoken, preventing readers from reading three lines ahead.
The point of a build is pacing: show each element when the narration reaches it, so the viewer reads the line being spoken — not three lines ahead.
Readability is a hard line: body text ≥28–32px @1080p, titles 56–80px, contrast ≥4.5:1, content kept within the center 90%.
- **Type scale, not deck scale.** A deck viewed on a laptop ≠ a video viewed in a feed. Bump body to ≥ 28–32px at 1080p; titles 56–80px.
Verification loop: read compositions first to get total duration, then sample from each slide's "hold section" rather than during transitions.
- Use `npx remotion compositions` to read the deck's `durationInFrames`/`fps` and pick the end frame; sample a still **inside each slide's hold**, not on a transition, to judge the built state.
Transitions must carry logic (therefore / however / so): quiet fades for "and", large pushes only for section dividers.
- **Transitions carry logic, not just motion.** The cut between slides should answer "so what's next?" — therefore, but, which means, here's the proof.
2Core Capabilities
3External Dependencies
| Kind | Dependency / Endpoint |
|---|---|
| package | remotion(AbsoluteFill/Sequence/Audio/spring/interpolate) |
| package | @remotion/media-utils(getAudioDurationInSeconds 量测旁白) |
| package | @remotion/transitions(TransitionSeries / linearTiming / fade / slide) |
| package | @remotion/google-fonts(reference 建议的字体加载方式;选择它会在渲染期访问 Google Fonts) |
| cli | npm / npx(安装并运行 Remotion 工程、读 compositions、渲染) |
| network | iart.ai(reference 尾部推广链接,具 utm 参数;仅读者点击才请求) |
4Recommended Governance & Evidence
- scripts/: Local script or command execution: No built-in scripts inside the skill directory; SKILL.md/reference instructs agent to execute `npm i remotion @remotion/tra
- 网络端点: Declared external network access: No operational API calls during runtime; narration audio consists of local files measured locally by Remotion.
- 本地工作目录: File I/O and artifact output: Writes `out/f-title.png`/`out/f-mid.png`/`out/f-end.png`, `out/deck.mp4`, `o` inside the user project.
5Second-Pass Verification
- [ok] 音频量测与 HANDLE 数值是否两处一致 — SKILL.md 代码块 `const HANDLE = 0.4; // breathing room after the voice ends` 与 sequencing.md 的 `const HANDLE = 0.4; // seconds of breathing room after each voice line` 同值。
- [ok] theme 数值是否与 reference 一致 — SKILL.md 示例 theme(bg #0B0B12 / fg #F5F5F7 / accent #6C5CE7 / titlePx 72 / bodyPx 30 / maxWidthPct 90)与 slide-components.md 的 theme.ts 逐项相同。
- [ok] 转场帧预算的声明与实现 — SKILL.md「A transition borrows frames from both neighbors, so add its length back into the slide budget」与 sequencing.md 的记账规则(slide.durationInFrames += TRANSITION)同口径。
- [discrepancy] @remotion/google-fonts 的声明层级 — @remotion/google-fonts 只出现在 sequencing.md 的 pitfalls(作为可选建议),SKILL.md 既未列入依赖面、也未提示渲染期可能访问 Google Fonts;照抄该建议会产生未声明的出网行为。
- [ok] SKILL.md 内联组件与 reference 组件是否冲突 — SKILL.md 的 Bullet 用 spring(...durationInFrames: 12) + interpolate(p,[0,1],[18,0]),reference 用 useEnter() 封装同一动效;属精简版与封装版的关系,非矛盾。
- [unlocatable] 旁白生成方式是否被声明 — SKILL.md workflow 第 2 步写「Generate/record narration per slide.(One audio file per slide (TTS or recorded).)」但未指名任何 TTS 服务或端点——属用户自备素材;「无 TTS 端点」这一结论无法在源码内定位到明确声明,故记 unlocatable(非档位依据)。
6Verdict & Scenarios
c9a450ffb476b92f…