--- name: remotion-performance-optimizer description: Analyzes Remotion compositions for performance issues and provides optimization recommendations. Identifies expensive computations, unnecessary re-renders, large assets, memoization opportunities, and architecture improvements. Use when optimizing render times or when asked to "improve performance", "speed up renders", "optimize Remotion video". --- # Remotion Performance Optimizer Comprehensive performance analysis and optimization recommendations for Remotion video compositions. Identifies bottlenecks and provides actionable fixes to reduce render times. ## What This Skill Does Performs deep performance analysis: 1. **Computation analysis** — Identify expensive operations in render path 2. **Re-render detection** — Find unnecessary component re-renders 3. **Asset optimization** — Recommend asset size and format improvements 4. **Memoization opportunities** — Identify cacheable calculations 5. **Architecture review** — Suggest structural improvements 6. **Render profiling** — Analyze frame render times ## Input/Output Formats ### Input Format: Remotion Composition Code Accepts implemented Remotion composition files: **Files to analyze:** ``` 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 ``` **Context needed:** - Target render time goals (e.g., < 100ms/frame) - Composition complexity (simple, moderate, complex) - Any specific performance concerns **Example request:** ``` Analyze performance of VideoName composition. Target: < 100ms/frame average render time. Scene 2 is rendering slowly (200ms/frame). ``` ### Output Format: OPTIMIZATION_REPORT.md Generates detailed performance analysis with actionable fixes: ```markdown # 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 ; })} ``` **Why This Is Slow:** - Math.random() is non-deterministic (different each frame) - 70 particles × 3 random calls = 210 random calls per frame - Remotion can't cache because values change - Browser must recalculate positions every frame **Solution:** ```typescript // ✅ 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) => ( ))} ``` **Expected Improvement:** - Scene 2: 285ms → 125ms (55% faster) - Overall: 145ms → 105ms (28% faster) - Total render time: 36min → 22min (40% faster) **Implementation Time:** 15 minutes --- ### HIGH (Significant Performance Impact) #### 2. Large Unoptimized Product Image **Impact:** 🟡 50ms asset loading delay **Location:** `public/images/product.png` **Severity:** High - Affects loading and memory **Problem:** ``` Current Asset: - Format: PNG (unnecessary transparency) - Resolution: 4000x3000 (2x larger than needed) - File Size: 8.2MB - Load Time: ~50ms ``` **Why This Is Slow:** - 8.2MB file takes time to load and decode - 4000x3000 is overkill for 1920x1080 display - PNG format unnecessary (no transparency used) **Solution:** ```bash # Resize and convert to JPEG magick public/images/product.png \ -resize 1920x1440 \ -quality 90 \ public/images/product.jpg # Update code ``` **Result:** ``` Optimized Asset: - Format: JPEG - Resolution: 1920x1440 (2x for retina) - File Size: ~400KB (95% smaller) - Load Time: ~5ms (90% faster) ``` **Expected Improvement:** - Scene 3 load time: 50ms faster - Overall render: 95ms → 85ms in Scene 3 - Smaller final video file **Implementation Time:** 5 minutes --- #### 3. Repeated Spring Calculations **Impact:** 🟡 30ms per scene **Location:** Multiple scenes **Severity:** High - Accumulates across scenes **Problem in Scene 1:** ```typescript // ❌ PROBLEM: Spring calculated 3 times
``` **Why This Is Slow:** - Spring function has internal calculations - Called 3 times with identical parameters - Remotion can't optimize duplicate calls - Wastes 20-30ms per scene **Solution:** ```typescript // ✅ OPTIMIZED: Calculate once, reuse const progress = spring({ frame, fps, config: SMOOTH });
``` **Expected Improvement:** - Per scene: 20-30ms faster - Overall: 145ms → 125ms (15% faster) - Affects Scenes 1, 3, 4 **Implementation Time:** 10 minutes --- ### MEDIUM (Moderate Performance Impact) #### 4. Component Not Memoized **Impact:** 🟡 10-15ms **Location:** Scene components **Severity:** Medium - Minor unnecessary re-renders **Problem:** ```typescript // Scene components re-render even when props haven't changed function Scene1() { ... } function Scene2() { ... } ``` **Solution:** ```typescript import { memo } from 'react'; const Scene1 = memo(() => { ... }); const Scene2 = memo(() => { ... }); ``` **Expected Improvement:** - 10-15ms per scene - Overall: 10% faster in complex compositions **Implementation Time:** 5 minutes --- ### LOW (Minor Performance Impact) #### 5. Array Creation in Render **Impact:** 🟢 2-5ms **Location:** `Scene4.tsx:23` **Severity:** Low - Negligible but fixable **Problem:** ```typescript // Array recreated every frame {Array(50).fill(0).map((_, i) => )} ``` **Solution:** ```typescript // Reuse array reference const ELEMENTS = Array.from({ length: 50 }, (_, i) => i); {ELEMENTS.map((i) => )} ``` **Expected Improvement:** 2-5ms (minimal but good practice) **Implementation Time:** 2 minutes --- ## Optimization Implementation Plan ### Phase 1: Critical Fixes (15 minutes) — 55% improvement 1. Replace Math.random() with seeded random in Scene 2 - Expected: 285ms → 125ms ### Phase 2: High Priority (15 minutes) — 20% additional improvement 1. Optimize product.png to JPEG (5 min) - Expected: 95ms → 85ms in Scene 3 2. Extract spring calculations (10 min) - Expected: 145ms → 125ms overall ### Phase 3: Medium Priority (10 minutes) — 10% additional improvement 1. Memoize scene components - Expected: 10-15ms improvement ### Phase 4: Low Priority (5 minutes) — 2-5% improvement 1. Extract array constants - Expected: 2-5ms improvement **Total Implementation Time:** 45 minutes **Total Expected Improvement:** 60-70% faster renders --- ## Before/After Projections | Metric | Before | After Phase 1 | After Phase 2 | After All | Target | |--------|--------|---------------|---------------|-----------|--------| | Scene 2 | 285ms | 125ms | 115ms | 110ms | < 150ms ✅ | | Scene 3 | 95ms | 95ms | 85ms | 80ms | < 100ms ✅ | | Overall Avg | 145ms | 105ms | 90ms | 85ms | < 100ms ✅ | | Total Render | 36min | 22min | 19min | 18min | < 20min ✅ | **After all optimizations:** All targets met! 🎉 --- ## Performance Validation ### Benchmarking Commands ```bash # 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 ``` ### Performance Targets | Composition Type | Target | Current | Status | |-----------------|--------|---------|--------| | Simple scenes | < 50ms | 75ms (Scenes 1,4) | 🟡 Acceptable | | Moderate scenes | < 100ms | 145ms avg | 🔴 Over target | | Complex scenes | < 150ms | 285ms (Scene 2) | 🔴 Over target | **After optimizations:** All scenes should meet targets --- ## Code Quality Checks ✅ **Good Patterns Found:** - Constants extracted (COLORS, SPRING_CONFIGS) - useVideoConfig used for responsive sizing - TypeScript types defined - staticFile() used for assets ⚠️ **Optimization Opportunities:** - [ ] Replace Math.random() with seeded random - [ ] Extract repeated spring calculations - [ ] Memoize scene components - [ ] Optimize large assets --- ## Asset Optimization Details ### Current Assets | Asset | Size | Format | Status | Recommendation | |-------|------|--------|--------|----------------| | logo.png | 180KB | PNG | 🟢 Good | Keep as-is | | product.png | 8.2MB | PNG | 🔴 Optimize | → JPEG 400KB | | background.mp3 | 1.8MB | MP3 | 🟢 Good | Keep as-is | | whoosh.mp3 | 45KB | MP3 | 🟢 Good | Keep as-is | ### Optimization Commands ```bash # Product image (95% size reduction) magick public/images/product.png \ -resize 1920x1440 \ -quality 90 \ public/images/product.jpg ``` --- ## Recommendations Summary ### Immediate Actions (Critical) 1. ✅ **Replace Math.random() in Scene 2** — 55% faster - Priority: CRITICAL - Time: 15 minutes - Impact: 160ms per frame improvement ### Short-Term Actions (High Priority) 1. ✅ **Optimize product image** — 20% faster loading - Priority: HIGH - Time: 5 minutes - Impact: 50ms improvement 2. ✅ **Extract spring calculations** — 15% faster - Priority: HIGH - Time: 10 minutes - Impact: 20-30ms per scene ### Long-Term Improvements (Medium/Low) 1. Memoize scene components (10% improvement) 2. Extract array constants (2-5% improvement) 3. Consider lazy loading assets 4. Profile with Chrome DevTools for deeper analysis --- ## Next Steps 1. **Implement Critical Fix:** Replace Math.random() (highest impact) 2. **Benchmark:** Verify Scene 2 improvement (should be 285ms → 125ms) 3. **Implement High Priority:** Optimize assets and springs 4. **Re-run analysis:** Verify all targets met 5. **Final render:** Generate production video with optimizations --- ## Tools & Resources ### Profiling Tools ```bash # Remotion built-in profiling npx remotion preview --log=verbose # Chrome DevTools profiling # Open preview → DevTools → Performance tab → Record ``` ### Optimization References - Remotion Performance Docs: https://remotion.dev/docs/performance - React Profiler: https://react.dev/reference/react/Profiler - Seeded Random Pattern: See `/remotion-component-builder` skill --- ## Approval **Status:** ⚠️ OPTIMIZATION REQUIRED BEFORE PRODUCTION After implementing critical and high-priority fixes, this composition will meet all performance targets and be production-ready. **Estimated Time to Production-Ready:** 30-45 minutes of optimization work **Signed:** remotion-performance-optimizer **Date:** 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 */; } ``` **Solution:** ```typescript // ✓ 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); }; ``` **Impact:** 30-50% render time reduction for scenes with many elements. ### 2. Repeated Spring Calculations **Issue:** Same spring calculation multiple times. **Detection:** ```typescript // ❌ PROBLEM - Spring calculated 3 times
``` **Solution:** ```typescript // ✓ OPTIMIZED - Calculate once, reuse const progress = spring({ frame, fps, config: SMOOTH });
``` **Impact:** 10-20% render time reduction per scene. ### 3. Large Asset Sizes **Issue:** Unoptimized assets slow down loading and rendering. **Detection:** ```markdown Product image: 4000x3000 PNG (8.2MB) Background video: 3840x2160 ProRes (450MB) Logo: 2000x2000 PNG (1.5MB) ``` **Recommendations:** ```markdown ✓ Product image: 1920x1440 JPEG 90% (400KB) — 95% smaller ✓ Background video: 1920x1080 H.264 (25MB) — 95% smaller ✓ Logo: 800x800 PNG optimized (80KB) — 95% smaller ``` **Impact:** Faster renders, smaller output files, better preview performance. ### 4. Unnecessary Re-renders **Issue:** Components re-render when dependencies haven't changed. **Detection:** ```typescript // ❌ 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 ``` **Solution:** ```typescript // ✓ 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 ; } ``` **Impact:** 20-40% render time reduction for complex components. ### 5. DOM Thrashing **Issue:** Excessive DOM reads/writes causing layout thrashing. **Detection:** ```typescript // ❌ PROBLEM - Reading and writing in loop elements.forEach((el) => { const width = el.getBoundingClientRect().width; // Read el.style.width = `${width * 2}px`; // Write (causes reflow) }); ``` **Solution:** ```typescript // ✓ 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`; }); ``` **Impact:** 15-30% improvement in DOM-heavy scenes. ### 6. Unoptimized Loops **Issue:** Inefficient iteration patterns. **Detection:** ```typescript // ❌ PROBLEM - Array creation every frame {Array(100).fill(0).map((_, i) => ( ))} ``` **Solution:** ```typescript // ✓ OPTIMIZED - Reuse array reference const PARTICLES = Array.from({ length: 100 }, (_, i) => i); {PARTICLES.map((i) => ( ))} ``` **Impact:** 5-10% improvement in scenes with many elements. ## Performance Optimization Checklist ### Computation Optimizations - [ ] No Math.random() in render (use seeded random) - [ ] Heavy calculations use useMemo - [ ] Spring calculations extracted and reused - [ ] Static data moved outside components - [ ] Loops use Array.from instead of Array().fill() ### Component Optimizations - [ ] Expensive components wrapped in memo() - [ ] useMemo for derived state - [ ] useCallback for event handlers passed to children - [ ] Components split appropriately (not too large) ### Asset Optimizations - [ ] Images sized to actual display dimensions (2x for retina) - [ ] JPEG for photos, PNG for transparency, SVG for graphics - [ ] Videos use H.264 codec with reasonable bitrate - [ ] Audio files trimmed to exact duration - [ ] Fonts load only required weights ### Render Optimizations - [ ] Avoid inline object/array creation in JSX - [ ] Use key prop correctly in lists - [ ] Minimize div nesting depth - [ ] Use CSS transforms over position changes - [ ] AbsoluteFill instead of complex layouts ### Architecture Optimizations - [ ] Extract reusable components - [ ] Scene components under 200 lines - [ ] Constants extracted to top of file - [ ] Utility functions outside components - [ ] Logical component composition ## Performance Benchmarking ### Measuring Render Time ```bash # 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 ``` ### Performance Targets | Composition Type | Target Render Time | Notes | |-----------------|-------------------|-------| | Simple (text, shapes) | < 50ms/frame | Minimal computations | | Moderate (animations, images) | 50-100ms/frame | Standard videos | | Complex (particles, 3D) | 100-200ms/frame | Heavy effects | | Very Complex (thousands of elements) | 200-500ms/frame | Acceptable with optimization | **Red flags:** - Single frame > 500ms → Major optimization needed - Render time increases over time → Memory leak ## Common Bottleneck Patterns ### Pattern 1: Particle Explosion **Issue:** ```typescript // 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 ; })} ``` **Fix:** ```typescript // 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) => ( ))} ``` ### Pattern 2: Text Processing **Issue:** ```typescript // String operations every frame const words = text.split(' '); const processed = words.map(w => w.toUpperCase()); ``` **Fix:** ```typescript // Process once outside render const processedWords = useMemo( () => text.split(' ').map(w => w.toUpperCase()), [text] ); ``` ### Pattern 3: Conditional Rendering **Issue:** ```typescript // Component always rendered, visibility toggled 100 ? 1 : 0 }} /> ``` **Fix:** ```typescript // Don't render at all when not visible {frame > 100 && } ``` ## Optimization Report Template ```markdown ## 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 ``` ## Integration with Other Skills **Works with:** - `/remotion-video-reviewer` — Performance audit during review - `/remotion-best-practices` — Ensures optimized patterns - `/remotion-spec-translator` — Generates optimized code from start ## Rules Directory Detailed optimization guides: - [rules/computation-optimization.md](rules/computation-optimization.md) — Optimizing calculations - [rules/asset-optimization.md](rules/asset-optimization.md) — Asset size and format - [rules/memoization-strategies.md](rules/memoization-strategies.md) — When and how to memoize - [rules/render-optimization.md](rules/render-optimization.md) — Render path improvements --- This skill ensures Remotion videos render as fast as possible while maintaining quality.