关于 remotion-performance-optimizer
该技能分析 Remotion 视频合成的性能瓶颈,并生成包含具体修复建议与基准测试方法的优化报告,面向开发 Remotion 视频的人员。分析范围包括计算、重渲染、素材、组件结构和帧耗时。
主要功能
- 01识别渲染路径中的高开销计算
- 02发现不必要的组件重渲染
- 03提出素材尺寸与格式优化建议
- 04定位可缓存计算与重复弹簧计算
- 05分析帧耗时并提供基准测试方法
适用场景
- 01排查特定场景渲染缓慢的原因
- 02减少复杂合成的逐帧计算与重渲染
- 03优化图像素材以缩短加载和渲染时间
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ncklrs/ startup-os-skills --skill remotion-performance-optimizer安装后在 Claude Code 中输入/remotion-performance-optimizer确认已加载。
附带文件rules/_sections.md
详细介绍
Remotion 性能优化器
针对 Remotion 视频合成提供全面的性能分析和优化建议。识别瓶颈并提供可执行的修复方案,以缩短渲染时间。
此工具的功能
执行深入的性能分析:
- 计算分析 — 识别渲染路径中开销较大的操作
- 重新渲染检测 — 找出不必要的组件重新渲染
- 素材优化 — 建议改进素材大小和格式
- 记忆化机会 — 识别可缓存的计算
- 架构审查 — 建议结构性改进
- 渲染分析 — 分析帧渲染时间
输入/输出格式
输入格式:Remotion 合成代码
接受已实现的 Remotion 合成文件:
要分析的文件:
src/remotion/compositions/VideoName/
├── index.tsx # Main composition
├── constants.ts # Color, timing, spring configs
├── types.ts # TypeScript types
└── scenes/
├── Scene1.tsx
├── Scene2.tsx
└── Scene3.tsx
所需上下文:
- 目标渲染时间要求(例如:每帧 < 100ms)
- 合成复杂度(简单、中等、复杂)
- 任何具体的性能问题
请求示例:
Analyze performance of VideoName composition.
Target: < 100ms/frame average render time.
Scene 2 is rendering slowly (200ms/frame).
输出格式:OPTIMIZATION_REPORT.md
生成包含可执行修复方案的详细性能分析:
# Performance Optimization Report: [Video Title]
**Date:** 2026-01-23
**Analyzer:** remotion-performance-optimizer
**Composition:** `src/remotion/compositions/VideoName/`
---
## Executive Summary
**Current Performance:** ⚠️ NEEDS OPTIMIZATION
| Metric | Current | Target | Status |
|--------|---------|--------|--------|
| **Average Render Time** | 145ms/frame | < 100ms | 🔴 45% over target |
| **Slowest Scene** | Scene 2: 285ms | < 150ms | 🔴 90% over target |
| **Total Render Time (estimated)** | 36 minutes | < 20 minutes | 🔴 80% over target |
| **Memory Usage** | Normal | Normal | 🟢 Good |
**Potential Improvement:** 60-70% faster render times after implementing recommendations
**Priority Actions:**
1. Replace Math.random() with seeded random in Scene 2 (55% improvement)
2. Optimize large product image (20% faster asset loading)
3. Extract repeated spring calculations (15% improvement)
---
## Performance Breakdown by Scene
| Scene | Avg Render Time | Status | Primary Bottleneck |
|-------|----------------|--------|-------------------|
| Scene 1 | 75ms | 🟢 Good | None |
| Scene 2 | 285ms | 🔴 Critical | Non-deterministic particle system |
| Scene 3 | 95ms | 🟡 Acceptable | Large asset loading |
| Scene 4 | 80ms | 🟢 Good | None |
**Overall:** 145ms average (Target: < 100ms)
---
## Issues Found
### CRITICAL (Major Performance Impact)
#### 1. Non-Deterministic Particle System in Scene 2
**Impact:** 🔴 200ms per frame slowdown
**Location:** `src/remotion/compositions/VideoName/scenes/Scene2.tsx:48-65`
**Severity:** Critical - 70% of render time in Scene 2
**Problem:**
```typescript
// ❌ PROBLEM: Math.random() called 70 times per frame
{Array.from({ length: 70 }, (_, i) => {
const x = Math.random() * width; // Recalculated every frame!
const y = Math.random() * height; // Non-deterministic
const speed = Math.random() * 2;
return <Particle key={i} x={x} y={y} speed={speed} />;
})}
速度慢的原因:
- Math.random() 具有非确定性(每帧结果都不同)
- 每帧 70 个粒子 × 3 次随机调用 = 210 次随机调用
- 由于数值会变化,Remotion 无法缓存
- 浏览器必须在每一帧重新计算位置
解决方案:
// ✅ OPTIMIZED: Seeded random, deterministic
const seededRandom = (seed: number): number => {
const x = Math.sin(seed) * 10000;
return x - Math.floor(x);
};
const particles = useMemo(
() => Array.from({ length: 70 }, (_, i) => ({
x: seededRandom(i * 123.456) * width,
y: seededRandom(i * 789.012) * height,
speed: seededRandom(i * 456.789) * 2,
})),
[width, height]
);
{particles.map((p, i) => (
<Particle key={i} x={p.x} y={p.y} speed={p.speed} />
))}
预期改进:
- 场景 2:285ms → 125ms(快 55%)
- 整体:145ms → 105ms(快 28%)
- 总渲染时间:36min → 22min(快 40%)
**实施时间:**15 分钟
高(显著的性能影响)
2. 未优化的大型产品图片
**影响:**🟡 素材加载延迟 50ms
位置:public/images/product.png
**严重程度:**高——影响加载和内存
问题:
Current Asset:
- Format: PNG (unnecessary transparency)
- Resolution: 4000x3000 (2x larger than needed)
- File Size: 8.2MB
- Load Time: ~50ms
速度慢的原因:
- 8.2MB 文件需要时间加载和解码
- 对于 1920x1080 的显示尺寸,4000x3000 过大
- 不需要 PNG 格式(未使用透明度)
解决方案:
# Resize and convert to JPEG
magick public/images/product.png \
-resize 1920x1440 \
-quality 90 \
public/images/product.jpg
# Update code
<Img src={staticFile('images/product.jpg')} />
结果:
Optimized Asset:
- Format: JPEG
- Resolution: 1920x1440 (2x for retina)
- File Size: ~400KB (95% smaller)
- Load Time: ~5ms (90% faster)
预期改进:
- 场景 3 加载时间缩短 50ms
- 场景 3 整体渲染时间:95ms → 85ms
- 最终视频文件更小
**实施时间:**5 分钟
3. 重复的 Spring 计算
**影响:**🟡 每个场景 30ms **位置:**多个场景 **严重程度:**高——会在多个场景中累积
场景 1 中的问题:
// ❌ PROBLEM: Spring calculated 3 times
<div style={{
opacity: spring({ frame, fps, config: SMOOTH }),
scale: spring({ frame, fps, config: SMOOTH }),
y: interpolate(spring({ frame, fps, config: SMOOTH }), [0, 1], [0, 100]),
}} />
速度慢的原因:
- Spring 函数包含内部计算
- 使用相同参数调用了 3 次
- Remotion 无法优化重复调用
- 每个场景浪费 20-30ms
解决方案:
// ✅ OPTIMIZED: Calculate once, reuse
const progress = spring({ frame, fps, config: SMOOTH });
<div style={{
opacity: progress,
scale: progress,
y: interpolate(progress, [0, 1], [0, 100]),
}} />
预期改进:
- 每个场景:快 20-30ms
- 整体:145ms → 125ms(快 15%)
- 影响场景 1、3、4
**实施时间:**10 分钟
中(中等性能影响)
4. 组件未进行记忆化
**影响:**🟡 10-15ms **位置:**场景组件 **严重程度:**中——少量不必要的重新渲染
问题:
// Scene components re-render even when props haven't changed
function Scene1() { ... }
function Scene2() { ... }
解决方案:
import { memo } from 'react';
const Scene1 = memo(() => { ... });
const Scene2 = memo(() => { ... });
预期改进:
- 每个场景 10-15ms
- 复杂合成整体快 10%
**实施时间:**5 分钟
低(轻微性能影响)
5. 在渲染过程中创建数组
**影响:**🟢 2-5ms
位置:Scene4.tsx:23
**严重程度:**低——影响可忽略,但可以修复
问题:
// Array recreated every frame
{Array(50).fill(0).map((_, i) => <Element key={i} />)}
解决方案:
// Reuse array reference
const ELEMENTS = Array.from({ length: 50 }, (_, i) => i);
{ELEMENTS.map((i) => <Element key={i} />)}
**预期改进:**2-5ms(提升有限,但属于良好实践)
**实施时间:**2 分钟
优化实施计划
阶段 1:关键修复(15 分钟)— 性能提升 55%
- 在场景 2 中将 Math.random() 替换为带种子的随机函数
- 预期:285ms → 125ms
阶段 2:高优先级(15 分钟)— 额外提升 20%
- 将 product.png 优化为 JPEG(5 分钟)
- 预期:场景 3 从 95ms → 85ms
- 提取 Spring 计算(10 分钟)
- 预期:整体从 145ms → 125ms
阶段 3:中优先级(10 分钟)— 额外提升 10%
- 对场景组件进行记忆化
- 预期:提升 10-15ms
第 4 阶段:低优先级(5 分钟)——提升 2-5%
- 提取数组常量
- 预期:提升 2-5ms
预计实施时间: 45 分钟 预计总提升: 渲染速度提升 60-70%
优化前后预测
| 指标 | 优化前 | 第 1 阶段后 | 第 2 阶段后 | 全部完成后 | 目标 |
|---|---|---|---|---|---|
| 场景 2 | 285ms | 125ms | 115ms | 110ms | < 150ms ✅ |
| 场景 3 | 95ms | 95ms | 85ms | 80ms | < 100ms ✅ |
| 平均总体耗时 | 145ms | 105ms | 90ms | 85ms | < 100ms ✅ |
| 总渲染时间 | 36min | 22min | 19min | 18min | < 20min ✅ |
完成全部优化后: 已达到所有目标!🎉
性能验证
基准测试命令
# Test single frame render time
npx remotion still src/index.tsx VideoName --frame=150
# Profile specific scene (Scene 2)
npx remotion still src/index.tsx VideoName --frame=225
# Benchmark full render (first 100 frames)
time npx remotion render src/index.tsx VideoName test.mp4 --frames=0-100
# Full production render with timing
time npx remotion render src/index.tsx VideoName output.mp4
性能目标
| 合成类型 | 目标 | 当前值 | 状态 |
|---|---|---|---|
| 简单场景 | < 50ms | 75ms(场景 1、4) | 🟡 可接受 |
| 中等复杂度场景 | < 100ms | 平均 145ms | 🔴 超出目标 |
| 复杂场景 | < 150ms | 285ms(场景 2) | 🔴 超出目标 |
优化后: 所有场景都应达到目标
代码质量检查
✅ 发现的良好模式:
- 已提取常量(COLORS、SPRING_CONFIGS)
- 使用 useVideoConfig 实现响应式尺寸
- 已定义 TypeScript 类型
- 使用 staticFile() 处理资源
⚠️ 优化机会:
- 将 Math.random() 替换为带种子的随机数
- 提取重复的弹簧计算
- 对场景组件进行记忆化
- 优化大型资源
资源优化详情
当前资源
| 资源 | 大小 | 格式 | 状态 | 建议 |
|---|---|---|---|---|
| logo.png | 180KB | PNG | 🟢 良好 | 保持不变 |
| product.png | 8.2MB | PNG | 🔴 需优化 | → JPEG 400KB |
| background.mp3 | 1.8MB | MP3 | 🟢 良好 | 保持不变 |
| whoosh.mp3 | 45KB | MP3 | 🟢 良好 | 保持不变 |
优化命令
# Product image (95% size reduction)
magick public/images/product.png \
-resize 1920x1440 \
-quality 90 \
public/images/product.jpg
建议摘要
立即执行(关键)
- ✅ 替换场景 2 中的 Math.random() —— 速度提升 55%
- 优先级:关键
- 时间:15 分钟
- 影响:每帧提升 160ms
短期执行(高优先级)
-
✅ 优化产品图片 —— 加载速度提升 20%
- 优先级:高
- 时间:5 分钟
- 影响:提升 50ms
-
✅ 提取弹簧计算 —— 速度提升 15%
- 优先级:高
- 时间:10 分钟
- 影响:每个场景提升 20-30ms
长期改进(中/低优先级)
- 对场景组件进行记忆化(提升 10%)
- 提取数组常量(提升 2-5%)
- 考虑延迟加载资源
- 使用 Chrome DevTools 进行性能分析,深入排查
后续步骤
- 实施关键修复: 替换 Math.random()(影响最大)
- 进行基准测试: 验证场景 2 的改进(应从 285ms 降至 125ms)
- 实施高优先级优化: 优化资源和弹簧计算
- 重新运行分析: 验证是否达到所有目标
- 最终渲染: 使用优化后的设置生成生产视频
工具与资源
性能分析工具
# Remotion built-in profiling
npx remotion preview --log=verbose
# Chrome DevTools profiling
# Open preview → DevTools → Performance tab → Record
优化参考
- Remotion 性能文档:https://remotion.dev/docs/performance
- React Profiler:https://react.dev/reference/react/Profiler
- 带种子的随机数模式:参见
/remotion-component-builder技能
审批
状态: ⚠️ 生产前必须进行优化
实施关键和高优先级修复后,此合成将达到所有性能目标,可用于生产。
预计达到可用于生产状态所需时间: 30-45 分钟优化工作
签署者: remotion-performance-optimizer 日期: 2026-01-23
**This document provides:**
- Current vs. target performance metrics
- Prioritized issues by impact (CRITICAL, HIGH, MEDIUM, LOW)
- Before/after projections with concrete numbers
- Specific code locations and fixes
- Implementation time estimates
- Step-by-step optimization plan
- Benchmarking commands for validation
- Asset optimization recommendations
**Feeds into:**
- Developer: Implement fixes
- Re-run `/remotion-video-reviewer` after optimizations
- Final production render
## Performance Analysis Categories
### 1. Expensive Computations
**Issue:** Calculations executed every frame unnecessarily.
**Detection:**
```typescript
// ❌ PROBLEM - Recalculated every frame
function Scene() {
const frame = useCurrentFrame();
// Heavy calculation every frame
const particles = Array.from({ length: 1000 }, () => ({
x: Math.random() * 1920,
y: Math.random() * 1080,
}));
return /* render particles */;
}
解决方案:
// ✓ OPTIMIZED - Deterministic, seeded
function Scene() {
const frame = useCurrentFrame();
// Deterministic calculation
const particles = useMemo(
() => Array.from({ length: 1000 }, (_, i) => ({
x: seededRandom(i * 123) * 1920,
y: seededRandom(i * 456) * 1080,
})),
[] // No dependencies, calculate once
);
return /* render particles */;
}
// Seeded random for consistency
const seededRandom = (seed: number) => {
const x = Math.sin(seed) * 10000;
return x - Math.floor(x);
};
影响: 对包含大量元素的场景,渲染时间可缩短 30-50%。
2. 重复的弹簧计算
问题: 多次执行相同的弹簧计算。
检测:
// ❌ PROBLEM - Spring calculated 3 times
<div style={{
opacity: spring({ frame, fps, config: SMOOTH }),
scale: spring({ frame, fps, config: SMOOTH }),
y: interpolate(spring({ frame, fps, config: SMOOTH }), [0, 1], [0, 100]),
}} />
解决方案:
// ✓ OPTIMIZED - Calculate once, reuse
const progress = spring({ frame, fps, config: SMOOTH });
<div style={{
opacity: progress,
scale: progress,
y: interpolate(progress, [0, 1], [0, 100]),
}} />
影响: 每个场景的渲染时间可缩短 10-20%。
3. 资源文件过大
问题: 未经优化的资源会拖慢加载和渲染速度。
检测:
Product image: 4000x3000 PNG (8.2MB)
Background video: 3840x2160 ProRes (450MB)
Logo: 2000x2000 PNG (1.5MB)
建议:
✓ Product image: 1920x1440 JPEG 90% (400KB) — 95% smaller
✓ Background video: 1920x1080 H.264 (25MB) — 95% smaller
✓ Logo: 800x800 PNG optimized (80KB) — 95% smaller
影响: 渲染更快、输出文件更小、预览性能更好。
4. 不必要的重新渲染
问题: 依赖项未发生变化时,组件仍会重新渲染。
检测:
// ❌ PROBLEM - Re-renders on every frame change
function ExpensiveComponent({ data }) {
// Heavy calculation
const processed = data.map(item => /* complex transform */);
return /* render */;
}
// Parent re-renders every frame
<ExpensiveComponent data={staticData} />
解决方案:
// ✓ OPTIMIZED - Memoized component
const ExpensiveComponent = memo(({ data }) => {
// Heavy calculation
const processed = useMemo(
() => data.map(item => /* complex transform */),
[data]
);
return /* render */;
});
// Or: Extract static data outside component
const processedData = staticData.map(item => /* complex transform */);
function Scene() {
return <Component data={processedData} />;
}
影响: 复杂组件的渲染时间缩短 20-40%。
5. DOM 操作抖动
问题: 过度读取或写入 DOM,导致布局抖动。
检测:
// ❌ PROBLEM - Reading and writing in loop
elements.forEach((el) => {
const width = el.getBoundingClientRect().width; // Read
el.style.width = `${width * 2}px`; // Write (causes reflow)
});
解决方案:
// ✓ OPTIMIZED - Batch reads, then batch writes
const widths = elements.map((el) => el.getBoundingClientRect().width);
elements.forEach((el, i) => {
el.style.width = `${widths[i] * 2}px`;
});
影响: DOM 密集型场景的性能提升 15-30%。
6. 未优化的循环
问题: 迭代模式效率低下。
检测:
// ❌ PROBLEM - Array creation every frame
{Array(100).fill(0).map((_, i) => (
<Particle key={i} index={i} />
))}
解决方案:
// ✓ OPTIMIZED - Reuse array reference
const PARTICLES = Array.from({ length: 100 }, (_, i) => i);
{PARTICLES.map((i) => (
<Particle key={i} index={i} />
))}
影响: 元素较多的场景性能提升 5-10%。
性能优化清单
计算优化
- 渲染过程中不使用 Math.random()(使用带种子的随机数)
- 使用 useMemo 处理复杂计算
- 提取并复用弹簧计算
- 将静态数据移至组件外
- 循环使用 Array.from,而非 Array().fill()
组件优化
- 使用 memo() 包装开销较大的组件
- 使用 useMemo 处理派生状态
- 对传递给子组件的事件处理函数使用 useCallback
- 适当拆分组件(避免组件过大)
资源优化
- 图片尺寸与实际显示尺寸一致(视网膜屏幕使用 2 倍尺寸)
- 照片使用 JPEG,透明图像使用 PNG,图形使用 SVG
- 视频使用 H.264 编码,并设置合理的比特率
- 音频文件裁剪至准确时长
- 字体仅加载所需字重
渲染优化
- 避免在 JSX 中内联创建对象或数组
- 在列表中正确使用 key 属性
- 尽量减少 div 嵌套层级
- 使用 CSS 变换,而非更改位置
- 使用 AbsoluteFill,而非复杂布局
架构优化
- 提取可复用组件
- 场景组件少于 200 行
- 将常量提取至文件顶部
- 将工具函数置于组件外
- 合理组合组件
性能基准测试
测量渲染时间
# Benchmark a specific frame
npx remotion still src/index.tsx VideoName --frame=100
# Benchmark full render (first 100 frames)
time npx remotion render src/index.tsx VideoName output.mp4 --frames=0-100
# Profile with Chrome DevTools
npx remotion preview
# Open Chrome DevTools → Performance tab → Record
性能目标
| 合成类型 | 目标渲染时间 | 说明 |
|---|---|---|
| 简单(文本、形状) | < 50ms/帧 | 计算量极少 |
| 中等(动画、图片) | 50-100ms/帧 | 标准视频 |
| 复杂(粒子、3D) | 100-200ms/帧 | 效果开销较大 |
| 非常复杂(数千个元素) | 200-500ms/帧 | 优化后可接受 |
警示信号:
- 单帧 > 500ms → 需要进行重大优化
- 渲染时间随时间增长 → 内存泄漏
常见瓶颈模式
模式 1:粒子爆炸
问题:
// 1000 particles, each calculating independently
{Array(1000).fill(0).map((_, i) => {
const x = Math.random() * width; // Recalculated every frame!
const y = Math.random() * height;
return <Particle key={i} x={x} y={y} />;
})}
修复:
// Deterministic particles, calculated once
const particles = useMemo(
() => Array.from({ length: 1000 }, (_, i) => ({
x: seededRandom(i * 123.456) * width,
y: seededRandom(i * 789.012) * height,
})),
[width, height]
);
{particles.map((p, i) => (
<Particle key={i} x={p.x} y={p.y} />
))}
模式 2:文本处理
问题:
// String operations every frame
const words = text.split(' ');
const processed = words.map(w => w.toUpperCase());
修复:
// Process once outside render
const processedWords = useMemo(
() => text.split(' ').map(w => w.toUpperCase()),
[text]
);
模式 3:条件渲染
问题:
// Component always rendered, visibility toggled
<HeavyComponent style={{ opacity: frame > 100 ? 1 : 0 }} />
修复:
// Don't render at all when not visible
{frame > 100 && <HeavyComponent />}
优化报告模板
## Performance Optimization Report
### Current Performance
- Average render time: 180ms/frame
- Slowest scene: Scene 3 (350ms/frame)
- Total video render time: 45 minutes (estimated)
### Identified Issues
**CRITICAL (Major Impact)**
1. Particle system using Math.random()
- Location: Scene 2, ParticleSystem component
- Impact: +200ms per frame
- Fix: Replace with seeded random
- Estimated improvement: 55% faster
2. 4K product image not optimized
- Location: Scene 4
- Current: 8.2MB PNG
- Impact: Slow loading, memory pressure
- Fix: Resize to 1920x1440, convert to JPEG
- Estimated improvement: 95% smaller file
**HIGH (Significant Impact)**
1. Repeated spring calculations
- Location: Scene 1, Scene 3, Scene 5
- Impact: +50ms per scene
- Fix: Extract to progress variable
- Estimated improvement: 20% faster
**MEDIUM (Moderate Impact)**
1. Components not memoized
- Location: Scene components
- Fix: Wrap in React.memo()
- Estimated improvement: 10% faster
### Optimization Plan
1. Implement seeded random (15 min) — 55% improvement
2. Optimize assets (30 min) — Better loading
3. Extract spring calculations (10 min) — 20% improvement
4. Memoize components (20 min) — 10% improvement
**Expected Result:**
- Render time: 180ms → 80ms per frame (55% faster)
- Total render: 45 min → 20 min
与其他技能集成
配合使用:
/remotion-video-reviewer— 在审核期间进行性能审计/remotion-best-practices— 确保采用优化模式/remotion-spec-translator— 从一开始就生成优化代码
规则目录
详细的优化指南:
- rules/computation-optimization.md — 优化计算
- rules/asset-optimization.md — 资源大小与格式
- rules/memoization-strategies.md — 何时以及如何进行记忆化
- rules/render-optimization.md — 改进渲染路径
此技能可确保 Remotion 视频在保持质量的同时尽可能快速地渲染。