演示文稿转视频 是做什么的?
将演示文稿或幻灯片大纲转化为带有旁白、自动推进的动画视频。每张幻灯片重建为动态图形——元素逐步揭示、真实过渡、时序与旁白锁定——而不是某人点击 PowerPoint 的屏幕录制。
何时使用
- 需要变成自动播放视频的推介文稿、网络研讨会或课程模块。
- 需要变成带旁白的动画幻灯片的要点大纲。
- 幻灯片时序必须精确跟踪旁白的演示文稿(自动推进,无需点击)。
重建,而非录制
屏幕录制继承了演示文稿的静态外观、鼠标抖动和突兀的幻灯片切换。用代码(Remotion)重建带来:逐帧确定性揭示、实际缓动过渡、在任何分辨率下保持清晰的文本,以及由音频时长驱动的幻灯片持续时间。演示文稿变成脚本;视频是一个新产物。
叙事流:演示文稿是一个论点,不是N张幻灯片
在时序或动画之前,先修复故事。一个自动推进的演示文稿视频没有演示者来挽回丢失的思路——结构必须自己承载逻辑。先构建主干;幻灯片是其上的节拍。
- 一条主线(主干)。 用一句话陈述演示文稿的单一结论。每张幻灯片必须推进该结论;如果一张幻灯片没有做到,就删除它或将其移到附录。观看者应该能在观看一次后复述出主线。
- 每张幻灯片一个信息。 一张幻灯片只表达一个点——其标题就是该点,表述为一个主张(“流失率是我们真正的增长税”),而不是一个标签(“流失率”)。两个想法意味着两张幻灯片。
- 过渡承载逻辑,而不仅仅是动画。 幻灯片之间的切换应该回答“那么接下来呢?”——因此,但是,这意味着,这是证据。使动画与逻辑步骤匹配:安静的淡入用于“而且”,更大的部分推进用于“新一幕”。不标志着逻辑步骤的过渡只是装饰。
- 开场用钩子,结尾用行动号召。 第一张幻灯片在约5秒内赢得注意力——一个尖锐的问题、一个令人惊讶的统计数据、利害关系——而不是议程或徽标页面。最后一张幻灯片陈述你想要的单一行动(“启动试点”、“投资200万美元获得15%”),并作为结论帧保持静止。
张力→解决(推介主干)
推介是一场戏剧,而不是功能列表。将其排序,使张力上升,然后解决——每个幕次为下一个做铺垫。
| 幕次 | 节拍 | 作用 |
|---|---|---|
| 问题 | “这是出问题/有风险的地方” | 创造观看者感受到的张力 |
| 洞察 | “这是每个人都忽略的东西” | 非显而易见的转折;赢得解决方案 |
| 解决方案 | “这是我们的答案” | 解决问题构建的张力 |
| 证据 | “这是它有效的原因” | 牵引力、演示、数据 |
| 请求 | “这是我们想要的” | 一个具体的行动号召 |
在问题落地之前不要揭示解决方案——一个不成熟的解决方案感觉像是功能,而不是解脱。将你的幻灯片映射到这些幕次上;如果缺少一个幕次,那么论点就有漏洞。
节奏:让构建与旁白保持同步
主线在时间中展开,因此屏幕上的构建和旁白必须一起推进——旁白主导时钟(下一节),揭示根据它进行调度,以便观看者在听到台词的同时阅读它,绝不会提前。每张幻灯片一个信息使得这很自然:一张幻灯片携带一个点,恰好与旁白论证它的时间一样长,然后过渡标志着到下一个点的逻辑步骤。对一个点的长时间旁白意味着拆分幻灯片,而不是加快构建。
唯一规则:旁白主导时钟
每张幻灯片的持续时间恰好等于其旁白音频的时长,加上一点额外余量。 测量每个旁白剪辑的实际持续时间,转换为帧,并将其作为幻灯片的长度。绝不要凭感觉判断“这张幻灯片大约需要5秒”——它总是会漂移,导致音频被切断或提前结束。
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);
然后幻灯片内部的揭示根据该持续时间进行调度——要点在单词出现时出现,而不是在固定的网格上。
构建揭示:为揭示而动画,不为装饰
构建的目的是节奏:在旁白达到每个元素时显示它,以便观看者阅读正在被说出的台词——而不是提前的三行。逐个引入元素;保持标题、徽标和背景形状静态。
| 选项 | 推荐 | 原因 |
|---|---|---|
| 进入动画 | 淡入 + 12–24px 上升 | 优雅、平静;读作“到达” |
| 每个元素持续时间 | 0.25–0.5秒 | 足够快以流动,足够慢以被注意到 |
| 要点之间的间隔 | 0.15–0.4秒 | 顺序出现,而不是一堵文字墙 |
| 避免 | 飞入、旋转、弹跳、打字机效果 | 读作装饰;与旁白竞争 |
使用 useCurrentFrame() 驱动间隔,使其与渲染的音频保持锁定同步(有关完整组件,请参见 references/slide-components.md)。
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>
);
};
幻灯片间过渡
使用来自 @remotion/transitions 的 <TransitionSeries> 对幻灯片进行排序。每张幻灯片是一个带有从其旁白派生的 durationInFrames 的 Sequence;一个 Transition 位于它们之间。保持过渡安静(短淡入或平滑滑动)——内容才是主角,每次切换时花哨的擦除很快就会让人厌烦。
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。
标题和章节分隔符
标题卡和章节分隔符为视频提供了节奏,并让观看者在密集的幻灯片之间喘口气。将分隔符视为其自己的短“幻灯片”:一个大的章节编号/文字、章节标题、约1.5–2秒的停留,以及两侧更明显的过渡。保持分隔符的视觉语言(颜色、字体)一致,使其读作标点符号,而不是不同的视频。
保持文本清晰易读且符合品牌风格
幻灯片文字密集,因此可读性是关键。
- 类型比例,而非幻灯片比例。 在笔记本电脑上观看的演示文稿 ≠ 在信息流中观看的视频。在1080p情况下将正文提升到 ≥ 28–32px;标题56–80px。如果一张幻灯片需要16px的脚注才能放下,则它需要被拆分为两张幻灯片。
- 每张幻灯片一个想法。 如果一张幻灯片的旁白很长,就拆分它——永远不要通过缩小类型来适应。
- 对比度 + 安全边距。 保持 ≥ 4.5:1 的对比度;将所有内容保持在中心90%以内,以应对平台裁剪。
- 将品牌锁定在主题对象中。 颜色、字体、徽标和间距存在于一个
theme中,以便每张幻灯片保持一致,并且重新品牌化是一行更改。
export const theme = {
bg: "#0B0B12", fg: "#F5F5F7", accent: "#6C5CE7",
font: "Inter, system-ui, sans-serif",
titlePx: 72, bodyPx: 30, maxWidthPct: 90,
} as const;
工作流程
- 大纲 → 脚本。 一张幻灯片 = 一个想法 + 确切的旁白台词。这是事实来源。
- 为每张幻灯片生成/录制旁白。 每张幻灯片一个音频文件(TTS 或录制)。
- 测量音频 → 设置幻灯片持续时间。
getAudioDurationInSeconds→ 帧(上述规则)。 - 构建幻灯片组件,使用绑定到
useCurrentFrame()的逐步揭示。 - 排序 使用
<TransitionSeries>;添加标题和章节分隔符。 - 将每张幻灯片的音频挂载 在其
Sequence内部,以便旁白和视觉内容永远不会漂移。 - 可读性/品牌检查,然后渲染为 MP4。
输出检查清单
- 每张幻灯片的
durationInFrames源自其旁白音频,而非猜测。 - 每张幻灯片的音频都挂载在其自己的
Sequence内部(视觉内容和旁白锁定在一起)。 - 要点通过
useCurrentFrame()顺序揭示;标题/徽标保持静态。 - 揭示为淡入+上升,0.25–0.5秒,无装饰效果。
- 幻灯片间过渡安静;仅在章节分隔符上使用更明显的过渡。
- 在1080p下正文类型 ≥ 28px,对比度 ≥ 4.5:1,内容保持在中心90%以内。
- 每张幻灯片一个想法;长旁白应拆分幻灯片而不是缩小字体。
交付与验证(渲染静态帧 → MP4)
打包的辅助工具(
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,因此静态帧检查可以在你浪费一次完整编码之前捕捉到被裁剪的标题、不符合品牌的颜色或溢出的要点。
输出约定:
- 一个带有注册的演示文稿(
<Composition>+ zodschema+defaultProps)的 Remotion 项目,所有动画由帧驱动(无计时器 /Date.now()/Math.random());每张幻灯片的音频挂载在其自己的Sequence内部。 - 交付物 = 渲染的
out/*.mp4(加上项目,以便用户可以使用新的幻灯片/旁白重新渲染)。 - 幻灯片持续时间源自旁白——在
calculateMetadata中计算总durationInFrames和每个幻灯片的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. 检查每个 PNG — 保真度(幻灯片文本精确、数字/标签正确、品牌颜色/字体应用)
# 和 工件(文本溢出、正文类型太小、内容超出中心90%安全裁剪区、缺少字体、低对比度、要点在构建中途幻灯片本应稳定时被捕捉)。
# 3. 只有在静态帧检查通过后,再进行编码:
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。
在完成之前:
npx remotion still在标题、内容幻灯片和最后一帧上干净渲染——无错误,无缺失字体。- 幻灯片文本精确,在1080p下正文类型 ≥ 28px,对比度 ≥ 4.5:1,所有内容每帧都在中心90%内部。
- 仅由帧驱动——无
Date.now()/Math.random()/ 库计时器(确定性在 CI 中保持)。 - 实际提供的属性正确渲染(不仅是
defaultProps)——正确的幻灯片、挂载的旁白、源自音频的持续时间。 - 完整的 MP4 编码并播放(旁白 + 视觉内容锁定);(可选)为 README 渲染 GIF。
参考文件
references/slide-components.md— 完整的可运行 RemotionSlide组件、逐步揭示的BulletList、动画TitleCard和SectionDivider组件,带有共享主题和通过<Audio>挂载的每张幻灯片旁白。references/sequencing.md— 完整的演示文稿排序器:测量每个旁白剪辑并设置总时长和每张幻灯片时长的calculateMetadata,<TransitionSeries>组装,过渡帧预算核算,以及 JSON 演示文稿模式到视频数据流。