presentation-video

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Presentation Video

演示视频制作

Turn a deck or slide outline into a narrated, auto-advancing animated video. Each slide is rebuilt as motion graphics — staggered element reveals, real transitions, timing locked to the voiceover — not a screen-recording of someone clicking through PowerPoint.
将演示文稿或幻灯片大纲转换为带旁白、自动播放的动画视频。每张幻灯片都会被重构为动态图形——包含分步元素展示、真实过渡效果,且时间与旁白完全同步——而非录制点击PowerPoint的屏幕录像。

When to use

使用场景

  • A pitch deck, webinar, or course module that should become a self-playing video.
  • A bullet-point outline that needs to become narrated, animated slides.
  • A deck where slide timing must track a voiceover exactly (auto-advance, no clicking).
  • 需要转为自动播放视频的宣传演示文稿、网络研讨会或课程模块。
  • 需要制作成带旁白的动画幻灯片的要点大纲。
  • 幻灯片切换时间必须与旁白完全同步(自动切换,无需点击)的演示文稿。

Rebuild, don't record

重构而非录制

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. The deck becomes the script; the video is a new artifact.
屏幕录像会保留演示文稿的静态外观、鼠标抖动和生硬的幻灯片切换。通过代码(Remotion)重构可实现:逐帧精确的元素展示、平滑过渡效果、任意分辨率下都清晰的文本,以及由音频长度决定的幻灯片时长。演示文稿成为脚本,视频则是全新的产物。

Narrative flow: the deck is one argument, not N slides

叙事流程:演示文稿是一个完整论点,而非N张独立幻灯片

Before timing or motion, fix the story. A presentation video that advances itself has no presenter to recover a lost thread — the structure must carry the logic on its own. Build the spine first; slides are beats on it.
  • 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 viewer should be able to recount the spine after one watch.
  • One message per slide. A slide makes exactly one point — its title is that point, phrased as a claim ("Churn is our real growth tax"), not a label ("Churn"). Two ideas means two slides.
  • Transitions carry logic, not just motion. The cut between slides should answer "so what's next?" — therefore, but, which means, here's the proof. Match the motion to the logical move: a quiet fade for "and also", a bigger section push for "new act". A transition that doesn't mark a logical step is just decoration.
  • Open with a hook, close with a CTA. The first slide earns attention in ~5s — a sharp question, a surprising stat, the stakes — not an agenda or a logo hold. The last slide states the single action you want ("Start the pilot", "Invest $2M for 15%"), held still as the takeaway frame.
在设置时间或动画之前,先梳理故事线。自动播放的演示视频没有主持人来引导观众跟上思路——结构本身必须承载逻辑。先搭建核心框架;幻灯片只是框架上的节点。
  • 一条核心主线:用一句话概括演示文稿的核心结论。每张幻灯片都必须服务于这个结论;如果某张幻灯片无关,就删除它或移至附录。观众看完一遍后应该能复述这条主线。
  • 每张幻灯片一个核心信息:每张幻灯片只传达一个观点——标题就是这个观点,用断言的方式表述(如“客户流失是我们增长的真正阻碍”),而非简单标签(如“客户流失”)。两个观点就需要两张幻灯片。
  • 过渡效果承载逻辑,而非仅作装饰:幻灯片之间的切换要回答“接下来是什么?”——因此、但是、这意味着、以下是证据。让动画匹配逻辑跳转:用柔和淡入表示“此外”,用较大的板块推送表示“新章节”。不承载逻辑的过渡效果只是装饰。
  • 开场抓眼球,结尾明确行动号召(CTA):第一张幻灯片要在约5秒内吸引注意力——比如尖锐的问题、惊人的数据、核心利害关系——而非展示议程或长时间停留的Logo。最后一张幻灯片明确你希望观众采取的单一行动(如“启动试点项目”“投资200万美元换取15%股权”),并将该画面作为收尾帧固定展示。

Tension → resolution (the pitch spine)

张力→解决(宣传演示文稿的核心框架)

A pitch is a drama, not a feature list. Sequence it so tension rises, then resolves — each act sets up the next.
ActBeatJob
Problem"Here's what's broken / at stake"Create tension the viewer feels
Insight"Here's what everyone misses"The non-obvious turn; earn the solution
Solution"Here's our answer"Resolve the tension the problem built
Proof"Here's why it works"Traction, demo, numbers
Ask"Here's what we want"One concrete CTA
Don't reveal the solution before the problem has landed — an unearned solution feels like a feature, not a relief. Map your slides onto these acts; if an act is missing the argument has a hole.
宣传演示是一场叙事,而非功能列表。按张力上升再解决的顺序编排——每个章节为下一个章节铺垫。
章节节点作用
问题“这是当前存在的问题/利害关系”让观众感受到张力
洞察“这是所有人都忽略的点”非显而易见的转折;为解决方案做铺垫
解决方案“这是我们的答案”解决问题带来的张力
证据“这是它有效的原因”用户反馈、演示、数据
请求“这是我们的诉求”一个具体的行动号召
不要在问题尚未明确时就展示解决方案——未经铺垫的解决方案只是一个功能,而非缓解张力的答案。将你的幻灯片对应到这些章节;如果缺少某个章节,论点就存在漏洞。

Pacing: keep the build in sync with the voice

节奏:让动画与旁白同步

The throughline plays out in time, so on-screen build and VO must advance together — narration owns the clock (next section), and reveals are scheduled against it so the viewer reads the line as it's spoken, never ahead. One message per slide makes this natural: a slide carries one point for exactly as long as the voice argues it, then the transition marks the logical step to the next. Long narration on one point means split the slide, not race the build.
主线随着时间推进,因此屏幕上的动画和旁白必须同步——旁白主导时间节奏(下一节详述),元素展示的时间安排要让观众在旁白讲述时刚好读到对应内容,而非提前阅读。每张幻灯片一个核心信息让这种同步变得自然:一张幻灯片承载的观点时长恰好是旁白论述它的时间,然后过渡效果标记逻辑跳转至下一个观点。如果某个观点的旁白过长,就拆分幻灯片,而非加快动画速度。

The one rule: narration owns the clock

核心规则:旁白主导时间节奏

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. Never eyeball "this slide feels like ~5s" — it always drifts and the audio gets cut off or runs dry.
ts
import { getAudioDurationInSeconds } from "@remotion/media-utils";
// In a Remotion calculateMetadata() / build step, per slide:
const sec = await getAudioDurationInSeconds(slide.audioUrl);
const HANDLE = 0.4; // breathing room after the voice ends
slide.durationInFrames = Math.ceil((sec + HANDLE) * fps);
Then the reveals inside the slide are scheduled against that duration — bullets land on the words, not on a fixed grid.
**每张幻灯片的时长恰好等于其旁白音频的时长,再加上一小段缓冲时间。**测量每个旁白片段的实际时长,转换为帧数,并将其设为幻灯片的时长。绝不要凭感觉估算“这张幻灯片大概5秒”——这样总会出现偏差,导致音频被截断或提前结束。
ts
import { getAudioDurationInSeconds } from "@remotion/media-utils";
// 在Remotion的calculateMetadata() / 构建步骤中,针对每张幻灯片:
const sec = await getAudioDurationInSeconds(slide.audioUrl);
const HANDLE = 0.4; // 旁白结束后的缓冲时间
slide.durationInFrames = Math.ceil((sec + HANDLE) * fps);
然后,幻灯片内部的元素展示时间将基于这个时长来安排——项目符号在旁白讲到对应内容时出现,而非按固定网格展示。

Build reveals: animate to reveal, never to decorate

元素展示:动画用于引导阅读,而非装饰

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. Stagger elements in; keep titles, logos, and background shapes static.
ChoiceRecommendationWhy
Enter motionfade + 12–24px risePolished, calm; reads as "arriving"
Per-element duration0.25–0.5sFast enough to flow, slow enough to register
Stagger between bullets0.15–0.4sSequential, not a wall of text
Avoidfly-in, spin, bounce, typewriterReads as decoration; competes with the voice
Drive the stagger off
useCurrentFrame()
so it stays in lockstep with the rendered audio (see
references/slide-components.md
for the full component).
tsx
import { useCurrentFrame, interpolate, spring, useVideoConfig } from "remotion";

const Bullet: React.FC<{ index: number; children: React.ReactNode }> = ({ index, children }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const STAGGER = 8;                         // frames between bullets (~0.27s @ 30fps)
  const enter = frame - index * STAGGER;     // each bullet starts later
  const p = spring({ frame: enter, fps, config: { damping: 200 }, durationInFrames: 12 });
  return (
    <li style={{ opacity: p, transform: `translateY(${interpolate(p, [0, 1], [18, 0])}px)` }}>
      {children}
    </li>
  );
};
元素展示的目的是控制节奏:在旁白讲到对应内容时展示每个元素,让观众在旁白讲述时刚好读到对应内容——而非提前看到三行内容。逐个展示元素;标题、Logo和背景图形保持静态。
选项建议原因
入场动画淡入 + 向上移动12–24px精致、沉稳;传达“出现”的含义
单元素动画时长0.25–0.5秒足够流畅,又能让观众注意到
项目符号之间的间隔0.15–0.4秒按顺序展示,而非一次性出现整段文本
避免使用飞入、旋转、弹跳、打字机效果会被视为装饰;分散观众对旁白的注意力
基于
useCurrentFrame()
来控制元素展示的间隔,使其与渲染的音频保持同步(完整组件请参考
references/slide-components.md
)。
tsx
import { useCurrentFrame, interpolate, spring, useVideoConfig } from "remotion";

const Bullet: React.FC<{ index: number; children: React.ReactNode }> = ({ index, children }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const STAGGER = 8;                         // 项目符号之间的帧数间隔(30fps下约0.27秒)
  const enter = frame - index * STAGGER;     // 每个项目符号延迟出现
  const p = spring({ frame: enter, fps, config: { damping: 200 }, durationInFrames: 12 });
  return (
    <li style={{ opacity: p, transform: `translateY(${interpolate(p, [0, 1], [18, 0])}px)` }}>
      {children}
    </li>
  );
};

Slide-to-slide transitions

幻灯片间过渡效果

Sequence slides with
<TransitionSeries>
from
@remotion/transitions
. Each slide is a
Sequence
with its narration-derived
durationInFrames
; a
Transition
sits between them. Keep transitions quiet (short fade or gentle slide) — the content is the star, and a busy wipe on every cut gets tiring fast.
tsx
import { TransitionSeries, linearTiming } from "@remotion/transitions";
import { fade } from "@remotion/transitions/fade";

<TransitionSeries>
  {slides.map((s, i) => (
    <React.Fragment key={s.id}>
      <TransitionSeries.Sequence durationInFrames={s.durationInFrames}>
        <Slide {...s} />
      </TransitionSeries.Sequence>
      {i < slides.length - 1 && (
        <TransitionSeries.Transition
          timing={linearTiming({ durationInFrames: 15 })}
          presentation={fade()}
        />
      )}
    </React.Fragment>
  ))}
</TransitionSeries>
Reserve a bigger transition (a slide/push) for section dividers only — it signals "new topic" and earns the extra motion. A transition borrows frames from both neighbors, so add its length back into the slide budget if a slide's narration must play in full. See
references/sequencing.md
.
使用
@remotion/transitions
中的
<TransitionSeries>
来编排幻灯片。每张幻灯片是一个
Sequence
,时长由旁白决定;幻灯片之间添加
Transition
。过渡效果要保持简洁(短时间淡入或柔和滑动)——内容才是核心,过于花哨的切换效果很快会让观众感到疲劳。
tsx
import { TransitionSeries, linearTiming } from "@remotion/transitions";
import { fade } from "@remotion/transitions/fade";

<TransitionSeries>
  {slides.map((s, i) => (
    <React.Fragment key={s.id}>
      <TransitionSeries.Sequence durationInFrames={s.durationInFrames}>
        <Slide {...s} />
      </TransitionSeries.Sequence>
      {i < slides.length - 1 && (
        <TransitionSeries.Transition
          timing={linearTiming({ durationInFrames: 15 })}
          presentation={fade()}
        />
      )}
    </React.Fragment>
  ))}
</TransitionSeries>
仅在章节分隔页使用更明显的过渡效果(如滑动/推送)——它标志着“新主题”,值得额外的动画效果。过渡效果会占用前后两张幻灯片的帧数,因此如果某张幻灯片的旁白必须完整播放,要将过渡效果的时长加回到幻灯片的时长预算中。请参考
references/sequencing.md

Title & section dividers

标题与章节分隔页

A title card and section dividers give the video rhythm and let the viewer breathe between dense slides. Treat a divider as its own short "slide": a large section number/word, the section title, a hold of ~1.5–2s, and a more pronounced transition on either side. Keep the divider's visual language (color, type) consistent so it reads as punctuation, not a different video.
标题页和章节分隔页为视频赋予节奏,让观众在密集的幻灯片之间有喘息的空间。将分隔页视为独立的短“幻灯片”:大字号的章节编号/名称、章节标题,停留约1.5–2秒,两侧使用更明显的过渡效果。保持分隔页的视觉语言(颜色、字体)一致,使其看起来像是视频的标点,而非另一个视频。

Keep text legible & on-brand

保持文本清晰可读且符合品牌风格

Slides are text-dense, so legibility is the whole game.
  • 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. If a slide needs a 16px footnote to fit, it needs to be split into two slides.
  • One idea per slide. If narration for a slide runs long, split it — never shrink type to fit.
  • Contrast + safe margins. Hold a ≥ 4.5:1 contrast ratio; keep all content within the center 90% so it survives platform cropping.
  • Lock the brand in a theme object. Colors, fonts, logo, and spacing live in one
    theme
    so every slide is consistent and a rebrand is a one-line change.
ts
export const theme = {
  bg: "#0B0B12", fg: "#F5F5F7", accent: "#6C5CE7",
  font: "Inter, system-ui, sans-serif",
  titlePx: 72, bodyPx: 30, maxWidthPct: 90,
} as const;
幻灯片文本密集,因此可读性至关重要。
  • 按视频比例调整字体大小,而非演示文稿比例:在笔记本电脑上查看的演示文稿≠在信息流中查看的视频。在1080p分辨率下,正文字体至少设为28–32px;标题字体设为56–80px。如果某张幻灯片需要16px的脚注才能容纳内容,就将其拆分为两张幻灯片。
  • 每张幻灯片一个核心信息:如果某张幻灯片的旁白过长,就拆分它——绝不要缩小字体来容纳内容。
  • 对比度 + 安全边距:保持≥4.5:1的对比度;所有内容都放在中心90%的区域内,避免被平台裁剪。
  • 将品牌规范锁定在主题对象中:颜色、字体、Logo和间距都存放在一个
    theme
    对象中,确保每张幻灯片风格一致,品牌更新只需修改一行代码。
ts
export const theme = {
  bg: "#0B0B12", fg: "#F5F5F7", accent: "#6C5CE7",
  font: "Inter, system-ui, sans-serif",
  titlePx: 72, bodyPx: 30, maxWidthPct: 90,
} as const;

Workflow

工作流程

  1. Outline → script. One slide = one idea + the exact narration line(s). This is the source of truth.
  2. Generate/record narration per slide. One audio file per slide (TTS or recorded).
  3. Measure audio → set slide durations.
    getAudioDurationInSeconds
    → frames (the rule above).
  4. Build slide components with staggered reveals tied to
    useCurrentFrame()
    .
  5. Sequence with
    <TransitionSeries>
    ; add title + section dividers.
  6. Mount each slide's audio inside its
    Sequence
    so voice and visuals can never drift.
  7. Legibility/brand pass, then render to MP4.
  1. 大纲→脚本:一张幻灯片=一个核心信息+对应的旁白文本。这是后续工作的基准。
  2. 为每张幻灯片生成/录制旁白:每张幻灯片对应一个音频文件(文本转语音或人工录制)。
  3. 测量音频时长→设置幻灯片时长:使用
    getAudioDurationInSeconds
    转换为帧数(遵循上述核心规则)。
  4. 构建幻灯片组件:基于
    useCurrentFrame()
    实现分步元素展示。
  5. 编排幻灯片:使用
    <TransitionSeries>
    ;添加标题页和章节分隔页。
  6. 将每张幻灯片的音频挂载到其
    Sequence
    :确保视觉与旁白永远同步。
  7. 可读性/品牌规范检查,然后渲染为MP4格式。

Output checklist

输出检查清单

  • Every slide's
    durationInFrames
    is derived from its narration audio, not guessed.
  • Each slide's audio is mounted inside its own
    Sequence
    (visuals + voice locked together).
  • Bullets reveal sequentially via
    useCurrentFrame()
    ; titles/logos static.
  • Reveals are fade+rise, 0.25–0.5s, no decorative effects.
  • Slide-to-slide transitions are quiet; bigger transitions only on section dividers.
  • Body type ≥ 28px @ 1080p, ≥ 4.5:1 contrast, content within center 90%.
  • One idea per slide; long narration splits the slide instead of shrinking type.
  • 每张幻灯片的
    durationInFrames
    由旁白音频时长决定,而非估算。
  • 每张幻灯片的音频挂载到其自身的
    Sequence
    中(视觉与旁白绑定)。
  • 项目符号通过
    useCurrentFrame()
    按顺序展示;标题/Logo保持静态。
  • 元素展示使用淡入+向上移动效果,时长0.25–0.5秒,无装饰性动画。
  • 幻灯片间过渡效果简洁;仅在章节分隔页使用更明显的过渡效果。
  • 1080p分辨率下正文字体≥28px,对比度≥4.5:1,内容位于中心90%区域内。
  • 每张幻灯片一个核心信息;旁白过长时拆分幻灯片,而非缩小字体。

Deliver & verify (rendered stills → MP4)

交付与验证(渲染静帧→MP4)

Packaged helper (
scripts/
): tile your stills with
scripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.png
, then assert the encode with
scripts/probe-mp4.sh out.mp4 [WxH] [fps]
. See
scripts/README.md
.
Remotion is frame-deterministic — every bullet build, transition, and slide position is a pure function of
useCurrentFrame()
, so you can render any exact frame headlessly with no seek harness. The deliverable is a narrated MP4, so still-inspection catches a clipped title, an off-brand color, or a bullet that overflows before you waste a full encode.
Output contract:
  • A Remotion project with the deck registered (
    <Composition>
    + zod
    schema
    +
    defaultProps
    ), all motion frame-driven (no timers /
    Date.now()
    /
    Math.random()
    ); per-slide audio mounted inside its own
    Sequence
    .
  • Deliverable = the rendered
    out/*.mp4
    (plus the project, so the user can re-render with new slides/narration).
  • Slide durations are narration-derived — compute total + per-slide
    durationInFrames
    in
    calculateMetadata
    (it measures each audio clip), never by hand.
Verify loop — render stills → inspect → encode. Render single frames first (cheap, no video encode), then encode only once each slide builds and reads right.
bash
undefined
打包工具
scripts/
):使用
scripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.png
将静帧拼接为一张预览图,然后使用
scripts/probe-mp4.sh out.mp4 [WxH] [fps]
验证编码。请参考
scripts/README.md
Remotion是逐帧确定的——每个项目符号的展示、过渡效果和幻灯片位置都是
useCurrentFrame()
的纯函数,因此你可以无需额外工具就无头渲染任何精确帧。交付物是带旁白的MP4,因此在进行完整编码前,通过静帧检查可以发现标题被裁剪、品牌颜色错误或项目符号溢出等问题。
输出约定:
  • 一个Remotion项目,包含已注册的演示文稿(
    <Composition>
    + zod
    schema
    +
    defaultProps
    ),所有动画均由帧驱动(无计时器/
    Date.now()
    /
    Math.random()
    );每张幻灯片的音频挂载到其自身的
    Sequence
    中。
  • 交付物=渲染后的
    out/*.mp4
    (附带项目文件,方便用户重新渲染新的幻灯片/旁白)。
  • 幻灯片时长由旁白决定——在
    calculateMetadata
    中计算总时长和单张幻灯片的
    durationInFrames
    (测量每个音频片段),绝不手动设置。
验证流程——渲染静帧→检查→编码。先渲染单帧(成本低,无需视频编码),仅在每张幻灯片的动画和内容都正确后再进行编码。
bash
undefined

1. Frame-exact stills — with the SHIPPED props. Land one inside each slide's settled state:

1. 精确帧静帧——使用最终交付的props。在每张幻灯片的稳定状态下各渲染一张:

npx remotion still Deck out/f-title.png --frame=20 --props='{"slides":[...]}' # title card settled npx remotion still Deck out/f-mid.png --frame=240 --props='{"slides":[...]}' # a content slide, bullets built npx remotion still Deck out/f-end.png --frame=899 --props='{"slides":[...]}' # last frame = durationInFrames - 1
npx remotion still Deck out/f-title.png --frame=20 --props='{"slides":[...]}' # 标题页稳定状态 npx remotion still Deck out/f-mid.png --frame=240 --props='{"slides":[...]}' # 内容页,项目符号已全部展示 npx remotion still Deck out/f-end.png --frame=899 --props='{"slides":[...]}' # 最后一帧 = durationInFrames - 1

2. Inspect each PNG — FIDELITY (slide text exact, numbers/labels correct, brand colors/fonts applied)

2. 检查每张PNG——保真度(幻灯片文本准确,数字/标签正确,品牌颜色/字体已应用)

AND artifacts (text overflow, body type too small, content outside center 90% safe-crop, missing

以及是否存在问题(文本溢出,正文字体过小,内容超出中心90%安全裁剪区域,字体缺失,

font, low contrast, a bullet caught mid-build where the slide should be settled).

对比度低,项目符号在幻灯片应稳定的状态下仍处于动画中)。

3. Only after the stills check out, encode:

3. 仅在静帧检查通过后,进行编码:

npx remotion render Deck out/deck.mp4 --props='{"slides":[...]}'

- 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.
- **Data-driven / batch**: verify ONE representative deck (real slides + narration) via stills *before* rendering every variant — catch a type-scale or overflow bug once, not per deck.
- **README demo GIF for free**: `npx remotion render Deck out/demo.gif --codec=gif`.

**Before you finish:**
1. `npx remotion still` renders cleanly at title, a content slide, and the last frame — no errors, no missing fonts.
2. Slide text is exact, body type ≥ 28px @ 1080p, ≥ 4.5:1 contrast, all content inside the center 90% at each frame.
3. Frame-driven only — no `Date.now()` / `Math.random()` / library timers (determinism holds in CI).
4. The **shipped** props render correctly (not just `defaultProps`) — right slides, narration mounted, durations from audio.
5. Full MP4 encoded and plays (voice + visuals locked); (optional) GIF rendered for the README.
npx remotion render Deck out/deck.mp4 --props='{"slides":[...]}'

- 使用`npx remotion compositions`查看演示文稿的`durationInFrames`/`fps`并选择最后一帧;在每张幻灯片的稳定状态下采样静帧,而非过渡状态,以判断最终效果。
- **数据驱动/批量处理**:在渲染所有变体前,先通过静帧验证一个有代表性的演示文稿(真实幻灯片+旁白)——一次性发现字体比例或溢出问题,而非每个演示文稿都重复排查。
- **免费生成README演示GIF**:`npx remotion render Deck out/demo.gif --codec=gif`。

**完成前的最后检查:**
1. `npx remotion still`能成功渲染标题页、内容页和最后一帧的静帧——无错误,无字体缺失。
2. 幻灯片文本准确,1080p分辨率下正文字体≥28px,对比度≥4.5:1,每一帧的内容都位于中心90%区域内。
3. 仅由帧驱动——无`Date.now()`/`Math.random()`/库计时器(在CI环境中仍能保持确定性)。
4. 最终交付的props能正确渲染(不仅是`defaultProps`)——幻灯片正确,旁白已挂载,时长由音频决定。
5. 完整MP4已编码并能正常播放(旁白+视觉同步);(可选)已为README渲染GIF。

Reference files

参考文件

  • references/slide-components.md
    — complete runnable Remotion
    Slide
    , staggered
    BulletList
    , animated
    TitleCard
    , and
    SectionDivider
    components with a shared theme and per-slide narration mounted via
    <Audio>
    .
  • references/sequencing.md
    — the full deck sequencer:
    calculateMetadata
    that measures every narration clip and sets total + per-slide durations,
    <TransitionSeries>
    assembly, transition frame-budget accounting, and a JSON deck-schema → video data flow.
  • references/slide-components.md
    ——完整可运行的Remotion
    Slide
    、分步展示的
    BulletList
    、动画
    TitleCard
    SectionDivider
    组件,包含共享主题和通过
    <Audio>
    挂载的单张幻灯片旁白。
  • references/sequencing.md
    ——完整的演示文稿编排器:
    calculateMetadata
    用于测量所有旁白片段并设置总时长和单张幻灯片时长,
    <TransitionSeries>
    组装,过渡效果帧数预算计算,以及JSON演示文稿 schema→视频数据流。