📐 Formato vertical — 1080×1920 con useVideoConfig
El Reel comienza con la definición de la Composition: width: 1080, height: 1920. Todo dentro del componente lee esas dimensiones mediante useVideoConfig() para adaptarse — fuentes más grandes, márgenes más pequeños, contenido centrado verticalmente en el tercio superior (donde está el pulgar del usuario).
// Root.tsx — declaração do formato <Composition id="Reel" component={ReelVideo} width={1080} height={1920} fps={30} durationInFrames={900} // 30 s /> // Reel.tsx — layout responsivo const { width, height } = useVideoConfig(); // fonte escala com a largura const baseFontSize = width * 0.055; // ~60px em 1080px // conteúdo no terço superior (fora da área do polegar) const contentTop = height * 0.15;
📱 Reglas de diseño para 9:16
- Tercio superior (0–30%): título y texto principal — área más visible
- Tercio central (30–70%): visual/imagen — zona donde se enfoca la mirada
- Tercio inferior (70–100%): CTA y suscripción: zona del pulgar, interacción
- Fuente mínima: 60px en 1080px (width * 0.055) — legible en un celular pequeño
💬 Subtítulo animado — typewriter y bounce-text
El 85% de los Reels se ve sin sonido. Eso significa que el texto es el audio del video. El typewriter-subtitle.tsx revela el texto letra por letra, mientras el bounce-text.tsx hace que cada palabra entre con un pequeño salto — ambos crean la sensación de que alguien está "escribiendo en vivo".
const words = text.split(" "); const FRAMES_PER_WORD = 8; // ritmo: 1 palavra a cada 8 frames {words.map((word, i) => { const startFrame = i * FRAMES_PER_WORD; const opacity = interpolate( frame, [startFrame, startFrame + 6], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" } ); // bounce: entra de baixo const y = interpolate( frame, [startFrame, startFrame + 10], [20, 0], { easing: Easing.out(Easing.back(1.5)), extrapolateLeft: "clamp", extrapolateRight: "clamp" } ); return <span key={i} style={{ opacity, transform: `translateY(${y}px)`, display: "inline-block", margin: "0 4px" }}>{word}</span>; })}
💡 Ritmo: 8 frames por palabra = 0.27 s
A 30fps, 8 frames por palabra producen una lectura natural y fluida. Para frases impactantes que necesitan más énfasis, usa 12–15 frames por palabra. Para listas rápidas («fácil · rápido · barato»), usa 5–6 frames. El ritmo del texto debe imitar el ritmo del habla.
⚡ Glitch en el destaque — impacto visual en los primeros frames
El algoritmo de Reels mide la retención de los primeros 3 segundos. El glitch-text.tsx crea un efecto de «interferencia» en la palabra clave del video: desplazamientos rápidos de color (channel offset) durante 2–4 frames, que generan un impacto visual que capta la atención de inmediato.
✓ Glitch que funciona
- ✓Glitch en los primeros 0–15 frames: capta la atención antes de que sigas deslizando.
- ✓Offset pequeño (3–8px) — perceptible sin ser nauseabundo.
- ✓random("glitch-N") con seed — el mismo glitch en todos los renders.
✗ Glitch que aleja
- ✗Glitch durante todo el video: cansa y parece un error, no un efecto.
- ✗Offset grande (20px+) — hace que el texto sea ilegible.
- ✗Math.random() sin seed — texto «parpadeando» sin control durante el render.
Frame 0–3: glitch intenso
Tres capas del texto desplazadas aleatoriamente en X e Y (pero con semilla). Colores: ámbar, cian y blanco, separadas entre 3–6px.
Frame 4–6: glitch residual
Offset se reduce a 1–2px. La "cura" del glitch es tan importante como el glitch — la estabilización refuerza la palabra como recuerdo.
Frame 7+: texto estable
El texto principal permanece estable durante el resto de la escena. El efecto glitch puede reaparecer brevemente cuando surge una nueva frase.
🎵 Visualización de onda sonora — ritmo sin audio
O sound-wave.tsx renderiza una fila de barras que oscilan con Math.sin(), simulando una visualización de audio. En el Reel sin sonido, este elemento indica "este video tiene energía"; es el equivalente visual de un ritmo musical.
const frame = useCurrentFrame(); const BAR_COUNT = 32; const MAX_H = 80; // px, relativo ao height do container {Array.from({ length: BAR_COUNT }).map((_, i) => { const seed = random(`wave-${i}`); // fase aleatória por barra const barH = Math.abs( Math.sin(frame * 0.15 + seed * Math.PI * 2) ) * MAX_H + 4; // mínimo 4px para não sumir return <div key={i} style={{ width: 4, height: barH, background: i % 3 === 0 ? "#38bdf8" : "#fbbf24", borderRadius: 2 }} />; })}
🫧 Fondo bokeh — profundidad de campo sintética
O bokeh-circles.tsx genera círculos desenfocados que flotan en el fondo: el efecto bokeh de una cámara real, pero 100% computacional. Cada círculo tiene un tamaño, una posición, una opacidad y una velocidad vertical aleatorios (con semilla), lo que crea profundidad de campo sin una cámara física.
🫧 Cómo se genera el bokeh
- Posición: random("bokeh-x-N") y random("bokeh-y-N") — fijas y determinísticas
- Tamaño: random("bokeh-r-N") * 80 + 20 — entre 20 y 100px de radio
- Flotación: translateY = -frame * random("bokeh-speed-N") * 0.3 — sube lentamente
- Reaparición: cuando y < -r, reubicar en height + r (loop)
- Desenfoque: filter: blur(Npx) — entre 8 y 20px para que parezca desenfocado
🔔 Subscribe reminder — CTA en los últimos 5 s
O subscribe-reminder.tsx aparece en los últimos 150 frames (5 s) del Reel — una animación de campana + texto «Suscríbete» que no compite con el contenido principal, pero está ahí cuando el espectador está más interesado (porque lo vio hasta el final).
const { durationInFrames } = useVideoConfig(); const frame = useCurrentFrame(); // aparece nos últimos 150 frames return ( <Sequence from={durationInFrames - 150}> <SubscribeWidget /> </Sequence> ); // SubscribeWidget — sino com shake e texto const bellFrame = useCurrentFrame(); // local frame (0–150) const scale = spring({ frame: bellFrame, fps, config: { damping: 10, stiffness: 200 } }); // shake: oscila 3x por segundo const shakeX = Math.sin(bellFrame * 0.5) * interpolate(bellFrame, [0, 10], [8, 0], { extrapolateRight: "clamp" });
💡 ¿Por qué el último quinto?
Los espectadores que llegan a los últimos 5 s del Reel ya están «interesados»: aprobaron el contenido. Ese es el mejor momento para pedirles que hagan algo. El subscribe antes de ese momento parece spam; después, no hay tiempo para reaccionar. El timing correcto es lo que distingue un CTA eficaz de una intrusión.
🏆 Resumen del módulo — y del curso
🎓 ¡Completaste la Ruta 4 y el curso!
Recorriste las 4 rutas: Fundamentos (T1), Recursos y plantillas (T2), Combinación y composición (T3) y ahora Proyectos completos (T4). Con las 81 plantillas de la biblioteca y las técnicas que aprendiste, tienes todo lo necesario para crear cualquier video programático, desde aperturas de canal hasta Reels virales.