/remotion-best-practices
Usa esta skill cada vez que escribas una composición de Remotion — videos demo animados, recorridos de productos, presentaciones para hackathons, presentaciones narradas — cualquier cosa renderizada a MP4 mediante npx remotion render.
La skill agrupa dos capas de conocimiento:
- Fundamentos de Remotion — los archivos de reglas oficiales mantenidos por el equipo de Remotion en
github.com/remotion-dev/skills(composiciones, animaciones, fuentes, audio, transiciones, FFmpeg, subtítulos, etc.). - Reglas de artesanía para videos demo — lecciones obtenidas de un largo ciclo de iteración construyendo la demo del hackathon vskill / Skill Studio. Estas son las reglas que, si se rompen, producen una "presentación de diapositivas" en lugar de un recorrido de producto creíble.
Lee ambas capas antes de crear contenido.
Alcance y aplicabilidad
Las reglas de artesanía de la Capa 2 que se presentan a continuación se derivaron de un proyecto específico: la demo del hackathon vskill / Skill Studio (hackathon "Built with Opus" de Anthropic / Claude Code, abril de 2026). Reflejan la apariencia y sensación de ese producto: el chrome de Studio con encabezado de migas de pan, árbol lateral, páginas oscuras de verified-skill.com con fuentes mono, escenas de terminal, y la tesis editorial "Inter es basura de IA, la serifa distintiva es excelencia".
No apliques estas reglas al pie de la letra a demos no relacionadas. Una app móvil de consumo, un panel de finanzas, un juego o una presentación B2B SaaS tendrán su propio lenguaje visual, su propio ritmo y sus propias expectativas de audiencia. Un flujo de Guardar luego Publicar, una página
verified-skill.com/queueo un panel lateral de Studio con contadores de PROYECTOS/PERSONAL/PLUGINS son contenido, no artesanía.Usa esta capa como referencia para la técnica subyacente: el patrón de zoom de cámara, la disciplina de apuntado del cursor, el rectángulo de resaltado ajustado al contenido, las transiciones de estado en el lugar, el acoplamiento de voz en off/script.ts, el pipeline de render + aumento de audio — esos se generalizan. Las constantes exactas (zoom 1.72×, centro del botón x=1488, píldora de versión v1.0.0 → v1.0.1, atribución "Patrones Nivel 1 · LLM Nivel 2 · Socket") son específicas de Skill Studio — traduce, no copies.
Capa 1 — Fundamentos de Remotion
Refleja la skill remotion-best-practices oficial en https://github.com/remotion-dev/skills/blob/HEAD/skills/remotion/SKILL.md.
Configuración de nuevo proyecto
Cuando estés en una carpeta vacía o un espacio de trabajo sin un proyecto Remotion existente, crea uno usando:
npx create-video@latest --yes --blank --no-tailwind my-video
Iniciar la vista previa
Inicia el Studio de Remotion para previsualizar un video. El HMR del Studio recarga en vivo a medida que los archivos cambian — no necesitas un mecanismo preview_start separado, y Bash run_in_background es la forma correcta de mantenerlo activo entre ediciones.
npx remotion studio --port=3030
Renderizado
# El punto de entrada debe ser el archivo que llama a registerRoot() (normalmente src/remotion/index.ts)
npx remotion render src/remotion/index.ts <CompositionId> out/video.mp4 --concurrency=8 --log=info
Errores comunes:
- Pasar
Root.tsxcomo entrada → error: "este archivo no contiene registerRoot". Usaindex.ts. TransitionSerieshace introspección de props en hijos directos; no envuelvas hijos en<React.Fragment>. UsaflatMapdevolviendo un array plano de elementos<TransitionSeries.Sequence>y<TransitionSeries.Transition>.interpolate(frame, [a, b], …)requiere estrictamentea < b. Si obtienesbde constantes, verifica la cordura en el diseño del presupuesto de escena — Remotion lanza "inputRange debe ser estrictamente monótona creciente" en el primer fotograma evaluado y toda la composición falla al cargar.
Verificación de un fotograma
npx remotion still <composition-id> --scale=0.25 --frame=30
Temas cubiertos por los archivos de reglas oficiales
(Carga bajo demanda desde el repositorio de skills oficial — github.com/remotion-dev/skills/tree/HEAD/skills/remotion/rules/.)
compositions.md— Definir composiciones, fotogramas fijos, carpetas, props por defecto, metadatos dinámicosanimations.md—interpolate,spring, easing, matemática basada en fotogramastransitions.md—@remotion/transitions(fundido, deslizamiento, cortinilla), cómo encadenarlos dentro deTransitionSeriesassets.md—staticFile(),Img,Audio,Video, carga de fuentesfonts.md—@remotion/google-fontsy registro de fuentes localesaudio.md— Importar, recortar, volumen, velocidad, tonocaptions.md,subtitles.md— Pistas de subtítulos y sincronizaciónffmpeg.md— Recortar, concatenar, operaciones de audio mediante FFmpeg shell-outsilence-detection.md,extract-frames.md,get-audio-duration.md,get-video-duration.md— Utilidades de Mediabunnycharts.md,gifs.md,light-leaks.md,3d.md— Recetas de renderizado especializadas
Capa 2 — Reglas de artesanía para videos demo
Estas son las reglas obtenidas tras un largo ciclo de iteración. Trátalas como valores predeterminados, no como mejoras opcionales — la mayoría surgieron de comentarios de "esto se ve raro, arréglalo" que requirieron múltiples rondas para resolverse.
A. Fidelidad de referencia
A1. Siempre usa la referencia real
Si el usuario dice "haz que se vea como en el minuto 2:43 de este video de YouTube", extrae el fotograma y estúdialo. No te bases en la memoria.
SOURCE="/Users/antonabyzov/Movies/.../Source.mov"
DEST_DIR=".specweave/.../assets/keyframes"
for t in 102 105 108 110 112; do
ffmpeg -y -ss "$t" -i "$SOURCE" -frames:v 1 -q:v 2 "$DEST_DIR/at-${t}s.jpg" -loglevel error
done
Luego Lee cada JPG y diseña a partir de lo que realmente está en pantalla — tipografía, etiquetas de botones exactas, colores de insignias, diseño del árbol lateral, posicionamiento del campo de búsqueda, valores de contadores (por ejemplo, PROYECTO (1), PERSONAL (0 de 12), PLUGINS (0 de 50), DISPONIBLE (62)).
A2. Usa logotipos e iconos reales, no aproximaciones
- Logotipo de campana
skill-studio-logo.png— cópialo en cada escena de Studio como<Img src={staticFile("...")} />. No renderices un glifo✷y lo llames logotipo. - Iconos de proveedores — obtén el SVG/PNG real de Claude, Anthropic, OpenAI, OpenRouter, Ollama, LM Studio (por ejemplo, de
lobehub/static-png). No sustituyas con emojis. - Mascotas — dibuja con divs estilizados para que coincidan exactamente con la forma. La mascota de Claude Code tiene un cuerpo color melocotón
#e08160con dos ojos cuadrados, dos protuberancias laterales a la altura media del cuerpo, y dos pares de patas debajo (▪ ▪ ▪ ▪). No arte ASCII. - Chrome de ventana de app — al mostrar un sitio web en un "navegador Chrome", renderiza un marco real de navegador Chrome: esquinas redondeadas, puntos de semáforo, navegación ‹ › ↻, barra de URL con candado cerrado y una URL real (
localhost:3000/hero, sin espacios extra, sin punto medio).
A3. Coincide con los diseños de referencia de YouTube píxel por píxel
Antes de rediseñar una escena desde la imaginación, enumera los elementos visibles en el fotograma de referencia y verifica cada uno contra tu salida:
- Texto del banner — redacción exacta (
Enviar habilidades para verificación, noEnviar una Habilidad) - Orden de pestañas —
Resumen · Editar · Pruebas · Ejecutar · Disparador · Versiones - Insignias de confianza —
T1 NO EXAMINADO,Seguridad Examinada —,Editor de Confianza - Campo de filtro — siempre arriba de
DISPONIBLEen el panel lateral - Contadores — mantenlos consistentes entre diapositivas (
PERSONAL (0 de 12)en todas partes, no(11)en una diapositiva y(0 de 12)en otra) - Controles del lado derecho del encabezado (en este orden):
🔍 Buscar habilidades [⌘K]·+ Nueva Habilidad·● Selector de modelo·🔔 campana
B. Zoom de cámara
B1. El zoom de cámara es de lienzo completo, no de sección escalada
No escales un solo panel dentro del chrome. Envuelve todo el chrome (barra superior + cuerpo) en un div de transformación y escala + traslada eso:
<div
style={{
width: "100%",
height: "100%",
transform: `translate(${cameraTx}px, ${cameraTy}px) scale(${cameraScale})`,
transformOrigin: "50% 50%",
willChange: "transform",
}}
>
{/* BARRA SUPERIOR + CUERPO */}
</div>
Los SVG del cursor + ondulación de clic van dentro de este envoltorio para que se escalen con el chrome y permanezcan pegados a su objetivo.
B2. Primero el clic, luego el zoom
El espectador necesita ver el objetivo del clic en contexto, luego ser transportado para ver la consecuencia. Orden:
fotograma 130 el cursor se acerca al botón
fotograma 174 ondulación del clic
fotograma 184 el botón muestra "Ejecutando…"
fotograma 188 el zoom de cámara comienza (1.0 → 1.55+ en ~30 fotogramas)
fotograma 220+ zoom mantenido — aquí ocurre la cascada de pase / resultados / revelación de desplazamiento
Hacer zoom primero y luego hacer clic se siente como una diapositiva de presentación. Hacer clic primero y luego hacer zoom se siente como si el usuario realizara la acción y la cámara lo siguiera.
B3. Elige una escala que realmente empuje el chrome fuera del lienzo
Un modesto 1.1× apenas cambia nada. Para que "la barra superior salga del borde superior del lienzo", necesitas ≥ 1.5× combinado con una traslación que lleve el punto focal al centro del lienzo. Calcula el objetivo ≥ (alturaMediaLienzo) / (distancia del punto focal a la barra superior) — para una fila en y=540 y una barra superior de 64 px, eso es ≥ ~1.5×. Usa 1.55–1.85× como valores predeterminados para "llenar el viewport".
C. Objetivos de clic del cursor
C1. Golpea el elemento real
Cuando el cursor aterriza en el botón equivocado (+ Nueva Habilidad vs la píldora del selector de modelo), el espectador piensa que la demo está rota. Vuelve a derivar el objetivo del diseño cada vez — no adivines valores de píxeles.
Para una tira de controles alineada a la derecha con flex y padding: "0 22px":
// Borde derecho → 22 de relleno → campana (32) → 14 → modelo (~290) → 14 → Nueva Habilidad (~120) → 14 → Buscar habilidades (~150)
NUEVA_HABILIDAD_PILL_X = 1920 - 22 - 32 - 14 - 290 - 14 - 60 // = 1488 (centro del botón)
BUSCAR_PILL_X = 1920 - 22 - 32 - 14 - 290 - 14 - 120 - 14 - 75 // = 1339
Una vez que tengas la constante, úsala tanto en la interpolación de acercamiento del cursor como en la de alejamiento para que la ondulación del clic aterrice exactamente en la píldora, no 200 px a la derecha.
C2. Resalta el objetivo mientras el cursor se acerca
Agrega una prop *Activo en componentes compartidos del encabezado (por ejemplo, buscarActivo, nuevaHabilidadActivo en StudioHeader) que la escena del cursor active durante la ventana de acercamiento + clic. El botón obtiene:
- Escala 1.08×
- Anillo suave índigo o púrpura mediante
box-shadow: 0 0 0 4px rgba(99,102,241,0.30) transition: all 0.15s ease
D. Resaltados y rectángulos
D1. Los rectángulos de resaltado tienen el ancho del contenido, no de la línea completa
Cuando el usuario quiere un rectángulo rojo alrededor de dos líneas de terminal, no envuelvas la columna flex padre — eso se extiende a lo ancho de la fila. Usa:
<div
style={{
display: "inline-flex",
flexDirection: "column",
alignSelf: "flex-start",
width: "fit-content",
border: "2px solid #dc2626",
borderRadius: 6,
padding: "10px 16px",
backgroundColor: "transparent",
}}
>
{/* las dos líneas, nada más */}
</div>
Cualquier cosa que deba estar fuera del rectángulo (por ejemplo, la tercera línea "Generando componente…") debe ser un hermano, no un hijo.
D2. Anotaciones: prefiere rectángulos sobre elipses
Un trazo de rectángulo estilo dibujado a mano alrededor de una fila se lee como "resaltador en el lienzo", que es lo que la mayoría de los usuarios quieren decir con "resalta esto". Una elipse puede sentirse decorativa.
<svg viewBox="0 0 1000 100" preserveAspectRatio="none">
<rect
x="6" y="6" width="988" height="88" rx="6" ry="6"
fill="none"
stroke="#ea580c"
strokeWidth="3.6"
strokeDasharray="2160"
strokeDashoffset={2160 * (1 - progress)}
/>
</svg>
D3. Usa naranja (#ea580c) para "esto es lo nuevo" y rojo (#dc2626) para "esto es el error"
La misma demo puede llevar ambos. No los mezcles.
E. Patrones de diseño para chrome de producto
E1. El encabezado de Studio es un único componente compartido
Usa un StudioHeader.tsx con este diseño canónico, llamado desde cada escena de Studio:
- Izquierda: imagen del logotipo (PNG 40 × 40) + marca "Skill Studio" + migas de pan
[Autoría|Disponible] / [ámbito] / [carpeta] / [habilidad] - Derecha: 🔍 Buscar habilidades
[⌘K]· ✦ + Nueva Habilidad · ● Selector de modelo · 🔔 Campana
Pasa migasDePan, insigniaCampana, buscarActivo, nuevaHabilidadActivo como props. El encabezado de cada escena es entonces estable en píxeles.
E2. El panel lateral tiene un campo de filtro constante arriba de DISPONIBLE
Cada panel lateral de Studio — Explorar, Actualizar, EvaluarAutoría, ConsumirInstalar, EditarYPublicarAutoría — recibe el mismo campo Filtrar habilidades… arriba del árbol DISPONIBLE. Pre-rellénalo con la consulta del contexto (diseño-frontend) en diapositivas donde el usuario ya haya buscado.
E3. Anchos y tipografía del panel lateral
- Ancho: 400 px (o 460 px en diapositivas con árboles profundamente anidados)
- Relleno exterior: 24–30 px
- Encabezados de grupo (
DISPONIBLE,AUTORÍA): 18–19 pt, interletraje 1.6, peso 700 - Sub-encabezados (
HABILIDADES,.CLAUDE): 15–16 pt, interletraje 1.4 - Texto de fila: 17–19 pt
- Píldora de versión: 13–14 pt mono con borde de 1 px, relleno 3/10
- Espacios verticales: 12–14 px entre secciones, 22–36 px arriba de los encabezados de sección
Los paneles laterales estrechos y densos se sienten como paneles de Configuración. Los paneles laterales amplios y abiertos se sienten como interfaz de producto real.
F. Transiciones de estado en el lugar
F1. No deslices hacia la izquierda entre escenas que deberían sentirse como una sola pantalla
Si "clic en Instalar → el árbol se actualiza con la nueva habilidad" debe leerse como una interacción continua:
- Establece
transitionType: nullen la siguiente escena o fusiona las dos escenas en una - Mantén el chrome idéntico entre las escenas
- Anima el elemento que cambia (giro del contador, rotación del cheurón, deslizamiento de la fila) — no hagas un fundido completo
F2. Resalta los nuevos elementos con fuerza
Un fondo melocotón + borde naranja sólido de 2 px + sombra paralela + píldora ✓ Recién instalado es la intensidad adecuada para "esto acaba de llegar". Un matiz de fondo sutil se lee como estado predeterminado y el espectador no lo nota.
backgroundColor: "#fff5ee",
boxShadow: `0 0 0 2px ${ORANGE}, 0 8px 22px rgba(234,88,12,0.22)`,
F3. Giros de contador: halo pulsante + rotación del cheurón
Cuando un contador cambia (PROYECTO (0) → (1)):
- Rota el cheurón
▸ → ▼(transición de 200 ms) - Renderiza un breve halo naranja detrás del contador: opacidad
0.45 → 0, escala0.4 → 2.2en 18 fotogramas - Desliza las nuevas filas hijos desde
translateY: -12 → 0en 24 fotogramas
G. Patrones de edición de Editor / SKILL.md
G1. Reemplaza, nunca elimines, campos obligatorios
Una habilidad siempre debe tener una description. Para actualizar la descripción: tacha la línea primitiva en rojo, desliza la nueva descripción