mcpField
R
remotion-performance-optimizer

remotion-performance-optimizer

github.com/ncklrs开发53159 次安装35 周前更新
代码仓库

关于 remotion-performance-optimizer

该技能分析 Remotion 视频合成的性能瓶颈,并生成包含具体修复建议与基准测试方法的优化报告,面向开发 Remotion 视频的人员。分析范围包括计算、重渲染、素材、组件结构和帧耗时。

主要功能

  1. 01识别渲染路径中的高开销计算
  2. 02发现不必要的组件重渲染
  3. 03提出素材尺寸与格式优化建议
  4. 04定位可缓存计算与重复弹簧计算
  5. 05分析帧耗时并提供基准测试方法

适用场景

  1. 01排查特定场景渲染缓慢的原因
  2. 02减少复杂合成的逐帧计算与重渲染
  3. 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 视频合成提供全面的性能分析和优化建议。识别瓶颈并提供可执行的修复方案,以缩短渲染时间。

此工具的功能

执行深入的性能分析:

  1. 计算分析 — 识别渲染路径中开销较大的操作
  2. 重新渲染检测 — 找出不必要的组件重新渲染
  3. 素材优化 — 建议改进素材大小和格式
  4. 记忆化机会 — 识别可缓存的计算
  5. 架构审查 — 建议结构性改进
  6. 渲染分析 — 分析帧渲染时间

输入/输出格式

输入格式: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%
  1. 在场景 2 中将 Math.random() 替换为带种子的随机函数
    • 预期:285ms → 125ms
阶段 2:高优先级(15 分钟)— 额外提升 20%
  1. 将 product.png 优化为 JPEG(5 分钟)
    • 预期:场景 3 从 95ms → 85ms
  2. 提取 Spring 计算(10 分钟)
    • 预期:整体从 145ms → 125ms
阶段 3:中优先级(10 分钟)— 额外提升 10%
  1. 对场景组件进行记忆化
    • 预期:提升 10-15ms
第 4 阶段:低优先级(5 分钟)——提升 2-5%
  1. 提取数组常量
    • 预期:提升 2-5ms

预计实施时间: 45 分钟 预计总提升: 渲染速度提升 60-70%


优化前后预测

指标优化前第 1 阶段后第 2 阶段后全部完成后目标
场景 2285ms125ms115ms110ms< 150ms ✅
场景 395ms95ms85ms80ms< 100ms ✅
平均总体耗时145ms105ms90ms85ms< 100ms ✅
总渲染时间36min22min19min18min< 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
性能目标
合成类型目标当前值状态
简单场景< 50ms75ms(场景 1、4)🟡 可接受
中等复杂度场景< 100ms平均 145ms🔴 超出目标
复杂场景< 150ms285ms(场景 2)🔴 超出目标

优化后: 所有场景都应达到目标


代码质量检查

✅ 发现的良好模式:

  • 已提取常量(COLORS、SPRING_CONFIGS)
  • 使用 useVideoConfig 实现响应式尺寸
  • 已定义 TypeScript 类型
  • 使用 staticFile() 处理资源

⚠️ 优化机会:

  • 将 Math.random() 替换为带种子的随机数
  • 提取重复的弹簧计算
  • 对场景组件进行记忆化
  • 优化大型资源

资源优化详情

当前资源
资源大小格式状态建议
logo.png180KBPNG🟢 良好保持不变
product.png8.2MBPNG🔴 需优化→ JPEG 400KB
background.mp31.8MBMP3🟢 良好保持不变
whoosh.mp345KBMP3🟢 良好保持不变
优化命令
# Product image (95% size reduction)
magick public/images/product.png \
  -resize 1920x1440 \
  -quality 90 \
  public/images/product.jpg

建议摘要

立即执行(关键)
  1. ✅ 替换场景 2 中的 Math.random() —— 速度提升 55%
    • 优先级:关键
    • 时间:15 分钟
    • 影响:每帧提升 160ms
短期执行(高优先级)
  1. ✅ 优化产品图片 —— 加载速度提升 20%

    • 优先级:高
    • 时间:5 分钟
    • 影响:提升 50ms
  2. ✅ 提取弹簧计算 —— 速度提升 15%

    • 优先级:高
    • 时间:10 分钟
    • 影响:每个场景提升 20-30ms
长期改进(中/低优先级)
  1. 对场景组件进行记忆化(提升 10%)
  2. 提取数组常量(提升 2-5%)
  3. 考虑延迟加载资源
  4. 使用 Chrome DevTools 进行性能分析,深入排查

后续步骤

  1. 实施关键修复: 替换 Math.random()(影响最大)
  2. 进行基准测试: 验证场景 2 的改进(应从 285ms 降至 125ms)
  3. 实施高优先级优化: 优化资源和弹簧计算
  4. 重新运行分析: 验证是否达到所有目标
  5. 最终渲染: 使用优化后的设置生成生产视频

工具与资源

性能分析工具
# Remotion built-in profiling
npx remotion preview --log=verbose

# Chrome DevTools profiling
# Open preview → DevTools → Performance tab → Record
优化参考

审批

状态: ⚠️ 生产前必须进行优化

实施关键和高优先级修复后,此合成将达到所有性能目标,可用于生产。

预计达到可用于生产状态所需时间: 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 — 从一开始就生成优化代码

规则目录

详细的优化指南:


此技能可确保 Remotion 视频在保持质量的同时尽可能快速地渲染。

评论

支持 Markdown