import React, { useEffect, useRef } from 'react'; import { useCurrentFrame, useVideoConfig, interpolate, Easing, AbsoluteFill, Img, } from 'remotion'; import * as Tone from 'tone'; // ============================================================================= // COMPOSITION CONFIG // ============================================================================= export const compositionConfig = { id: 'DiffusionProcess', durationInSeconds: 12, fps: 30, width: 1080, height: 1920, }; // ============================================================================= // STYLE CONSTANTS // ============================================================================= const COLORS = { primary: '#A855F7', secondary: '#6366F1', accent: '#06B6D4', background: '#08080F', text: '#FFFFFF', } as const; const TYPOGRAPHY = { fontFamily: 'Inter, system-ui, sans-serif', } as const; const EASINGS = { easeOut: Easing.bezier(0.33, 1, 0.68, 1), easeIn: Easing.bezier(0.32, 0, 0.67, 0), easeInOut: Easing.bezier(0.37, 0, 0.63, 1), }; const IMAGE_URL = 'https://s3.powerkit.dev/videofiles/studio/assets/1/72bf716f79a1.png'; const TOTAL_STEPS = 50; // ============================================================================= // PRE-GENERATED DATA // ============================================================================= const seededRandom = (seed: number): number => { const x = Math.sin(seed * 9999) * 10000; return x - Math.floor(x); }; // Grid configurations for multi-scale noise (coarse → fine) const NOISE_SCALES = [ { cols: 16, rows: 16 }, // Big blocky noise (early steps) { cols: 32, rows: 32 }, // Medium grain { cols: 64, rows: 64 }, // Fine grain (late steps) ]; const generateNoiseGrid = (cols: number, rows: number, seed: number) => { const cells: { r: number; c: number; color: string }[] = []; for (let r = 0; r < rows; r++) { for (let c = 0; c < cols; c++) { const s = seed + r * 1000 + c; const hue = seededRandom(s) * 360; const sat = 20 + seededRandom(s + 1) * 60; const light = 15 + seededRandom(s + 2) * 55; cells.push({ r, c, color: `hsl(${hue}, ${sat}%, ${light}%)` }); } } return cells; }; // Pre-generate multiple noise frames per scale for cycling const NOISE_FRAMES_COUNT = 6; const PRE_NOISE = NOISE_SCALES.map((scale) => ({ cols: scale.cols, rows: scale.rows, frames: Array.from({ length: NOISE_FRAMES_COUNT }, (_, i) => generateNoiseGrid(scale.cols, scale.rows, i * 100000 + scale.cols * 7777) ), })); // Floating particles const PARTICLES = Array.from({ length: 50 }, (_, i) => ({ x: seededRandom(i * 7) * 100, y: seededRandom(i * 7 + 1) * 100, size: 2 + seededRandom(i * 7 + 2) * 4, speed: 0.3 + seededRandom(i * 7 + 3) * 0.7, hue: seededRandom(i * 7 + 4) * 360, phase: seededRandom(i * 7 + 5) * Math.PI * 2, drift: (seededRandom(i * 7 + 6) - 0.5) * 30, })); // ============================================================================= // DIMENSIONS // ============================================================================= const GRID_SIZE = 820; // ============================================================================= // AUDIO (ToneJS) // ============================================================================= const useToneAudio = (frame: number, progress: number, fps: number) => { const noiseSynthRef = useRef(null); const filterRef = useRef(null); const noiseVolRef = useRef(null); const padSynthRef = useRef(null); const reverbRef = useRef(null); const pingSynthRef = useRef(null); const lastStepRef = useRef(-1); const lastChordRef = useRef(-1); const initedRef = useRef(false); // Initialize audio graph once useEffect(() => { if (initedRef.current) return; initedRef.current = true; const noiseVol = new Tone.Volume(-18).toDestination(); const filter = new Tone.Filter(400, 'lowpass').connect(noiseVol); const noiseSynth = new Tone.NoiseSynth({ noise: { type: 'pink' }, envelope: { attack: 0.1, decay: 0.1, sustain: 1, release: 0.5 }, }).connect(filter); const reverb = new Tone.Reverb({ decay: 4, wet: 0.5 }).toDestination(); const padSynth = new Tone.PolySynth(Tone.Synth, { oscillator: { type: 'sine' }, envelope: { attack: 0.8, decay: 0.5, sustain: 0.6, release: 2 }, volume: -14, }).connect(reverb); const pingSynth = new Tone.MetalSynth({ envelope: { attack: 0.001, decay: 0.3, release: 0.2 }, harmonicity: 5.1, modulationIndex: 32, resonance: 4000, octaves: 1.5, volume: -28, }).connect(reverb); noiseVolRef.current = noiseVol; filterRef.current = filter; noiseSynthRef.current = noiseSynth; reverbRef.current = reverb; padSynthRef.current = padSynth; pingSynthRef.current = pingSynth; // Start context on user interaction (preview) const start = async () => { try { await Tone.start(); noiseSynth.triggerAttack(); } catch (e) { /* ignore */ } }; start(); return () => { try { noiseSynth.triggerRelease(); noiseSynth.dispose(); filter.dispose(); noiseVol.dispose(); padSynth.dispose(); pingSynth.dispose(); reverb.dispose(); } catch (e) { /* ignore */ } }; }, []); // React to progress: noise fades out, filter opens, pad chords swell useEffect(() => { const filter = filterRef.current; const noiseVol = noiseVolRef.current; if (filter && noiseVol) { // Filter opens as denoising progresses (brighter = more detail) const cutoff = 300 + progress * 6000; filter.frequency.rampTo(cutoff, 0.1); // Noise fades out as image resolves const vol = -18 + (progress < 0.9 ? progress * -4 : -40); noiseVol.volume.rampTo(progress > 0.95 ? -60 : vol, 0.1); } }, [progress]); // Step ping on each denoising step useEffect(() => { const currentStep = Math.min( Math.floor(progress * TOTAL_STEPS), TOTAL_STEPS ); if ( currentStep !== lastStepRef.current && currentStep > 0 && pingSynthRef.current ) { lastStepRef.current = currentStep; try { pingSynthRef.current.triggerAttackRelease('C6', '32n'); } catch (e) { /* ignore */ } } }, [progress]); // Pad chord progression over time useEffect(() => { const chords = [ ['C3', 'Eb3', 'G3'], ['Ab2', 'C3', 'Eb3'], ['F2', 'Ab2', 'C3', 'Eb3'], ['G2', 'B2', 'D3', 'F3'], ['C3', 'E3', 'G3', 'B3'], ]; const chordIdx = Math.min( Math.floor(progress * chords.length), chords.length - 1 ); if ( chordIdx !== lastChordRef.current && padSynthRef.current && frame > fps * 0.3 ) { lastChordRef.current = chordIdx; try { padSynthRef.current.releaseAll(); padSynthRef.current.triggerAttack(chords[chordIdx]); } catch (e) { /* ignore */ } } }, [progress, frame, fps]); }; // ============================================================================= // SUB-COMPONENTS // ============================================================================= /** The actual image — starts heavily blurred, progressively sharpens */ const RevealImage: React.FC<{ progress: number }> = ({ progress }) => { const blur = interpolate(progress, [0, 0.85, 1], [60, 4, 0], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); const brightness = interpolate(progress, [0, 0.5, 1], [0.3, 0.7, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); const saturation = interpolate(progress, [0, 0.6, 1], [0.2, 0.8, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); const scale = interpolate(progress, [0, 0.5, 1], [1.05, 1.02, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); return (
); }; /** Multi-scale noise: coarse blocks → medium → fine grain → gone */ const NoiseOverlay: React.FC<{ progress: number; frame: number }> = ({ progress, frame, }) => { // Fade ranges for each scale [fadeInStart, fadeInEnd, fadeOutStart, fadeOutEnd] const fadeRanges = [ [0, 0.05, 0.3, 0.5], // Coarse: visible early, gone by 50% [0.15, 0.25, 0.55, 0.72], // Medium: mid-range [0.4, 0.5, 0.78, 0.95], // Fine: visible late, last to go ]; return (
{PRE_NOISE.map((scaleData, scaleIdx) => { const [fi0, fi1, fo0, fo1] = fadeRanges[scaleIdx]; const scaleOpacity = interpolate( progress, [fi0, fi1, fo0, fo1], [0, 1, 1, 0], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' } ); if (scaleOpacity <= 0.01) return null; // Coarse cycles fastest, fine slowest const cycleSpeed = 4 - scaleIdx; const noiseFrameIdx = Math.floor(frame / cycleSpeed) % NOISE_FRAMES_COUNT; const cells = scaleData.frames[noiseFrameIdx]; const cellW = GRID_SIZE / scaleData.cols; const cellH = GRID_SIZE / scaleData.rows; return (
{cells.map((cell, i) => (
))}
); })}
); }; /** Animated border glow that intensifies as image resolves */ const ImageFrame: React.FC<{ progress: number }> = ({ progress }) => { const glowIntensity = interpolate(progress, [0.6, 1], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); const borderOpacity = interpolate(progress, [0, 0.3, 1], [0.1, 0.2, 0.5], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); return (
0 ? `0 0 ${30 * glowIntensity}px rgba(139, 92, 246, ${0.3 * glowIntensity}), 0 0 ${60 * glowIntensity}px rgba(139, 92, 246, ${0.15 * glowIntensity})` : 'none', pointerEvents: 'none', }} /> ); }; const StepCounter: React.FC<{ progress: number }> = ({ progress }) => { const currentStep = Math.min( Math.floor(progress * TOTAL_STEPS), TOTAL_STEPS ); return (
Denoising Step
{currentStep}/{TOTAL_STEPS}
); }; const ProgressBar: React.FC<{ progress: number }> = ({ progress }) => { const barWidth = 600; return (
t=T (noise) t=0 (clean)
); }; const TimestepLabel: React.FC<{ progress: number; frame: number }> = ({ progress, frame, }) => { const labels = [ 'Pure Gaussian Noise', 'Removing Noise...', 'Structure Emerging', 'Refining Details', 'Image Resolved', ]; const idx = Math.min( Math.floor(progress * labels.length), labels.length - 1 ); const labelOpacity = interpolate(frame % 90, [0, 15, 75, 90], [0.6, 1, 1, 0.6], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); return (
{labels[idx]}
); }; const FloatingParticles: React.FC<{ frame: number; progress: number }> = ({ frame, progress, }) => ( <> {PARTICLES.map((p, i) => { const t = frame * 0.01 * p.speed; const x = p.x + Math.sin(t + p.phase) * p.drift; const y = ((p.y + frame * p.speed * 0.3) % 110) - 5; const particleOpacity = (1 - progress * 0.8) * 0.35; return (
4 ? 2 : 1}px)`, }} /> ); })} ); const GlowOrbs: React.FC<{ frame: number; progress: number }> = ({ frame, progress, }) => { const orbs = [ { x: 15, y: 30, size: 300, color: COLORS.primary, speed: 0.008 }, { x: 85, y: 70, size: 250, color: COLORS.secondary, speed: 0.012 }, { x: 50, y: 85, size: 200, color: COLORS.accent, speed: 0.01 }, ]; return ( <> {orbs.map((orb, i) => { const moveX = Math.sin(frame * orb.speed + i) * 5; const moveY = Math.cos(frame * orb.speed * 0.7 + i) * 5; return (
); })} ); }; const Title: React.FC<{ frame: number; fps: number }> = ({ frame, fps }) => { const titleOpacity = interpolate(frame, [0, fps * 0.5], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: EASINGS.easeOut, }); const titleY = interpolate(frame, [0, fps * 0.5], [30, 0], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: EASINGS.easeOut, }); return (
Diffusion Denoising
x_{'{'}t-1{'}'} = denoise(x_t, t)
); }; // ============================================================================= // MAIN COMPONENT // ============================================================================= const DiffusionProcess: React.FC = () => { const frame = useCurrentFrame(); const { fps, height } = useVideoConfig(); const denoiseStart = fps * 0.8; const denoiseEnd = fps * 10; const denoiseProgress = interpolate( frame, [denoiseStart, denoiseEnd], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: EASINGS.easeInOut, } ); // Hook up ToneJS audio, driven by denoise progress useToneAudio(frame, denoiseProgress, fps); const scanlineY = (frame * 3) % height; return ( {/* Background glow orbs */} {/* Floating noise particles */} {/* Scanline overlay */}
{/* Moving scanline */}
{/* Title */} {/* Step counter */} <StepCounter progress={denoiseProgress} /> {/* === THE DIFFUSION REVEAL === */} {/* Layer 1: Actual image (blurred → sharp) */} <RevealImage progress={denoiseProgress} /> {/* Layer 2: Multi-scale noise overlay (coarse → fine → gone) */} <NoiseOverlay progress={denoiseProgress} frame={frame} /> {/* Layer 3: Glow border frame */} <ImageFrame progress={denoiseProgress} /> {/* Timestep label */} <TimestepLabel progress={denoiseProgress} frame={frame} /> {/* Progress bar */} <ProgressBar progress={denoiseProgress} /> {/* Vignette */} <div style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', background: 'radial-gradient(ellipse at center, transparent 50%, rgba(0,0,0,0.6) 100%)', pointerEvents: 'none', zIndex: 15, }} /> </AbsoluteFill> ); }; export default DiffusionProcess;