Introducción
Rendervid está diseñado para renderizar en cualquier lugar que tu flujo de trabajo demande. Ya sea que necesites vistas previas instantáneas en el navegador, codificación de video de grado de producción en un servidor, o renderizado masivamente paralelo a través de infraestructura en la nube, Rendervid proporciona un paquete dedicado para cada entorno. Cada destino de despliegue comparte el mismo sistema de plantillas
y biblioteca de componentes
, por lo que una plantilla que funciona en el navegador funciona de manera idéntica en AWS Lambda o en un contenedor Docker.
Esta guía cubre los cuatro entornos de despliegue, las opciones de renderizado disponibles en cada uno, y características avanzadas como desenfoque de movimiento, exportación GIF y optimización del rendimiento. Al final, sabrás exactamente qué ruta de despliegue se ajusta a tu proyecto y cómo configurarla.
+---------------------+
| Plantilla JSON |
+----------+----------+
|
+--------------------+--------------------+
| | |
+--------v--------+ +-------v--------+ +-------v---------+
| Navegador | | Node.js | | Nube |
| @rendervid/ | | @rendervid/ | | @rendervid/ |
| renderer-browser | | renderer-node | | cloud-rendering |
+---------+--------+ +-------+--------+ +-------+---------+
| | |
Canvas / WebM FFmpeg / Playwright Trabajadores Paralelos
| | |
+---------v--------+ +------v---------+ +-------v---------+
| MP4, WebM, PNG, | | MP4, WebM, MOV,| | AWS Lambda |
| JPEG, WebP | | GIF, H.265 | | Azure Functions |
+------------------+ +----------------+ | GCP Functions |
| Docker |
+-----------------+
Renderizado en Navegador
El paquete @rendervid/renderer-browser maneja el renderizado del lado del cliente completamente dentro del navegador del usuario. No se requiere infraestructura de servidor. Esto lo convierte en la ruta más rápida de plantilla a vista previa.
Cuándo Usar el Renderizado en Navegador
- Vistas previas en tiempo real durante la edición de plantillas en el editor visual
- Aplicaciones web que necesitan generar activos de video o imagen sobre la marcha
- Prototipado de nuevas plantillas antes de comprometerse con el renderizado del lado del servidor
- Exportaciones ligeras donde la salida MP4, WebM, PNG, JPEG o WebP es suficiente
Instalación
npm install @rendervid/renderer-browser
Cómo Funciona
El renderizado en navegador utiliza la API Canvas de HTML para dibujar cada fotograma de la plantilla. El renderizador recorre cada escena y capa, aplica animaciones y funciones de suavizado, compone el resultado en un elemento canvas y captura cada fotograma. Para la salida de video, los fotogramas se codifican utilizando la API MediaRecorder integrada del navegador (WebM) o un codificador MP4 basado en WebAssembly.
| Formato | Extensión | Notas |
|---|
| MP4 | .mp4 | H.264 a través de codificador WebAssembly |
| WebM | .webm | VP8/VP9 a través de API MediaRecorder |
| PNG | .png | Fotograma único o secuencia de imágenes |
| JPEG | .jpeg | Fotograma único, calidad configurable |
| WebP | .webp | Fotograma único, tamaño de archivo más pequeño |
Ejemplo de Código
import { BrowserRenderer } from "@rendervid/renderer-browser";
const renderer = new BrowserRenderer();
const template = {
width: 1920,
height: 1080,
fps: 30,
scenes: [
{
duration: 5,
layers: [
{
type: "text",
text: "Hola desde el Navegador",
fontSize: 72,
color: "#ffffff",
position: { x: 960, y: 540 },
animation: {
entrance: { type: "fadeIn", duration: 1 },
},
},
],
},
],
};
// Renderizar a un elemento canvas para vista previa
const canvas = document.getElementById("preview") as HTMLCanvasElement;
await renderer.preview(template, canvas);
// Exportar como MP4
const mp4Blob = await renderer.render(template, {
format: "mp4",
quality: "standard",
});
// Exportar un solo fotograma como PNG
const pngBlob = await renderer.renderFrame(template, {
format: "png",
frameNumber: 0,
});
Limitaciones del Renderizado en Navegador
- Sin acceso a FFmpeg, por lo que H.265/HEVC y MOV no están disponibles
- La exportación GIF requiere el renderizador de Node.js para la optimización de paleta
- La resolución máxima depende de los límites de tamaño de Canvas del navegador (típicamente 4096x4096 u 8192x8192)
- La velocidad de renderizado depende de la CPU y GPU del dispositivo del cliente
Renderizado en Node.js
El paquete @rendervid/renderer-node proporciona renderizado del lado del servidor con integración completa de FFmpeg. Utiliza Playwright o Puppeteer para renderizar cada fotograma en un navegador sin interfaz, luego canaliza los fotogramas a FFmpeg para codificación de video de grado profesional.
Cuándo Usar el Renderizado en Node.js
- Codificación de video de producción con soporte completo de códec (H.264, H.265, VP9)
- Procesamiento por lotes de cientos o miles de plantillas en pipelines automatizados
- APIs REST que aceptan JSON de plantilla y devuelven video renderizado
- Pipelines CI/CD para generación automatizada de contenido
- Exportación GIF con optimización de paleta y control de difuminado
Instalación
# Instalar el renderizador
npm install @rendervid/renderer-node
# Instalar Playwright (incluye binarios del navegador)
npx playwright install chromium
# Instalar FFmpeg (requerido para codificación de video)
# macOS
brew install ffmpeg
# Ubuntu/Debian
sudo apt-get install ffmpeg
# Windows (a través de Chocolatey)
choco install ffmpeg
| Formato | Extensión | Códec | Notas |
|---|
| MP4 | .mp4 | H.264 | Compatibilidad universal |
| MP4 | .mp4 | H.265/HEVC | Archivos 50% más pequeños, dispositivos más nuevos |
| WebM | .webm | VP8/VP9 | Optimizado para web |
| MOV | .mov | ProRes | Flujos de trabajo de edición profesional |
| GIF | .gif | Basado en paleta | Animado con optimización |
| PNG | .png | Sin pérdida | Secuencia de imágenes o fotograma único |
| JPEG | .jpeg | Con pérdida | Calidad configurable |
| WebP | .webp | Con/Sin pérdida | Formato web moderno |
Ajustes de Calidad de Renderizado
Rendervid proporciona cuatro ajustes de calidad que controlan los parámetros de codificación:
| Ajuste | Bitrate | Caso de Uso |
|---|
draft | Bajo | Vistas previas rápidas durante el desarrollo |
standard | Medio | Salida de propósito general, buena calidad/tamaño |
high | Alto | Materiales de marketing, entregables finales |
lossless | Máximo | Archivo, edición adicional, sin pérdida de calidad |
Aceleración por GPU
El renderizador de Node.js admite aceleración por hardware para descargar la codificación a la GPU. Esto reduce significativamente el tiempo de renderizado para plantillas complejas con muchas capas, altas resoluciones y efectos.
const result = await renderer.render(template, {
format: "mp4",
quality: "high",
outputPath: "/output/video.mp4",
hardwareAcceleration: true,
});
La aceleración por GPU está disponible en sistemas con hardware compatible NVIDIA (NVENC), AMD (AMF) o Intel (Quick Sync). FFmpeg debe estar compilado con el soporte de codificador correspondiente.
Ejemplo de Código
import { NodeRenderer } from "@rendervid/renderer-node";
const renderer = new NodeRenderer();
const template = {
width: 1920,
height: 1080,
fps: 60,
scenes: [
{
duration: 10,
layers: [
{
type: "video",
src: "/assets/background.mp4",
fit: "cover",
},
{
type: "text",
text: "{{headline}}",
fontSize: 64,
color: "#ffffff",
fontFamily: "Inter",
position: { x: 960, y: 540 },
animation: {
entrance: { type: "slideInUp", duration: 0.8 },
exit: { type: "fadeOut", duration: 0.5 },
},
},
],
},
],
inputs: {
headline: {
type: "text",
label: "Titular",
default: "Tu Producto, Elevado",
},
},
};
// Renderizar con entradas personalizadas
const result = await renderer.render(template, {
format: "mp4",
quality: "high",
outputPath: "/output/promo.mp4",
renderWaitTime: 2000, // Esperar 2s para que se carguen los medios
inputs: {
headline: "Venta de Verano — 50% de Descuento en Todo",
},
});
console.log(`Renderizado: ${result.outputPath}`);
console.log(`Duración: ${result.duration}s`);
console.log(`Tamaño de archivo: ${(result.fileSize / 1024 / 1024).toFixed(2)} MB`);
Procesamiento por Lotes
Para procesar muchas plantillas en secuencia, usa la API por lotes:
import { NodeRenderer } from "@rendervid/renderer-node";
const renderer = new NodeRenderer();
const templates = [
{ template: socialTemplate, inputs: { name: "Alicia" }, output: "alicia.mp4" },
{ template: socialTemplate, inputs: { name: "Roberto" }, output: "roberto.mp4" },
{ template: socialTemplate, inputs: { name: "Carolina" }, output: "carolina.mp4" },
];
for (const job of templates) {
await renderer.render(job.template, {
format: "mp4",
quality: "standard",
outputPath: `/output/${job.output}`,
inputs: job.inputs,
});
}
Para un verdadero renderizado paralelo en una sola máquina, consulta la sección de Renderizado Local con Docker a continuación.
Renderizado en la Nube
El paquete @rendervid/cloud-rendering permite el renderizado distribuido y paralelo a través de infraestructura en la nube. En lugar de renderizar fotogramas secuencialmente en una máquina, el renderizado en la nube divide el trabajo entre muchas funciones trabajadoras que renderizan fotogramas simultáneamente, luego los fusiona en la salida final.
Cuándo Usar el Renderizado en la Nube
- Pipelines de alto rendimiento procesando cientos de videos por hora
- Contenido de formato largo donde el renderizado secuencial es demasiado lento
- Cargas de trabajo sensibles al tiempo donde una aceleración de 10-50x importa
- Escalado automático para manejar picos de demanda impredecibles
Arquitectura
+------------------+
| Tu App |
| (Coordinador) |
+--------+---------+
|
| 1. Dividir video en fragmentos de fotogramas
v
+--------+---------+
| Divisor de |
| Fragmentos |
+--------+---------+
|
| 2. Distribuir fragmentos a trabajadores
v
+--------+---+---+---+---+--------+
| Trabajador 1| Trabajador 2| Trabajador N |
| (Lambda/ | (Lambda/ | (Lambda/ |
| Azure/ | Azure/ | Azure/ |
| GCP) | GCP) | GCP) |
+-----+------+----+------+----+----+
| | |
| 3. Cada trabajador renderiza sus fotogramas
v v v
+-----+------+----+------+----+----+
| Fotogramas | Fotogramas| Fotogramas |
| 001-030 | 031-060 | 061-090|
+-----+------+----+------+----+----+
| | |
+------+-----+-----+----+
|
v
+-------+--------+
| Fusionador |
| (FFmpeg concat) |
+-------+---------+
|
| 4. Combinar en video final
v
+-------+---------+
| Almacenamiento |
| de Objetos |
| S3 / Blob / GCS |
+------------------+
|
| 5. Descargar o servir
v
+-------+---------+
| Salida Final |
| video.mp4 |
+------------------+
Cómo funciona paso a paso:
- El coordinador analiza la plantilla y determina cuántos fotogramas necesitan ser renderizados según la duración total y FPS.
- El divisor de fragmentos divide el conteo total de fotogramas en fragmentos (por ejemplo, 30 fotogramas por fragmento para un video de 30fps = 1 segundo por fragmento).
- Cada función trabajadora recibe una asignación de fragmento (fotograma inicial, fotograma final), renderiza esos fotogramas usando el renderizador de Node.js, y sube el segmento renderizado al almacenamiento de objetos.
- El fusionador descarga todos los segmentos y los concatena en el video final usando FFmpeg.
- La salida final se almacena en el almacenamiento de objetos del proveedor de nube (S3, Azure Blob o GCS) y opcionalmente se descarga al sistema de archivos local.
Configuración de la Nube
import { CloudRenderer } from "@rendervid/cloud-rendering";
const cloudRenderer = new CloudRenderer({
provider: "aws", // "aws" | "azure" | "gcp" | "docker"
quality: "standard", // "draft" | "standard" | "high"
downloadToLocal: true,
outputPath: "/output/final.mp4",
});
La interfaz de configuración completa:
interface CloudRenderConfig {
provider: "aws" | "azure" | "gcp" | "docker";
quality: "draft" | "standard" | "high";
downloadToLocal: boolean;
outputPath: string;
awsConfig?: {
region: string;
s3Bucket: string;
s3Prefix: string;
};
azureConfig?: {
resourceGroup: string;
storageAccount: string;
containerName: string;
};
gcpConfig?: {
projectId: string;
bucketName: string;
region: string;
};
dockerConfig?: {
volumePath: string;
workersCount: number;
};
}
Configuración de AWS Lambda
AWS Lambda es el destino de despliegue en la nube más común. Cada función trabajadora se ejecuta en una invocación Lambda separada, permitiendo un paralelismo masivo.
Prerrequisitos:
- Cuenta de AWS con acceso a Lambda y S3
- AWS CLI configurado
- Runtime Lambda de Node.js 18+
Configuración:
import { CloudRenderer } from "@rendervid/cloud-rendering";
const renderer = new CloudRenderer({
provider: "aws",
quality: "high",
downloadToLocal: true,
outputPath: "/output/video.mp4",
awsConfig: {
region: "us-east-1",
s3Bucket: "my-rendervid-output",
s3Prefix: "renders/",
},
});
const result = await renderer.render(template);
console.log(`Renderizado en ${result.renderTime}ms`);
console.log(`Trabajadores usados: ${result.workersUsed}`);
console.log(`Salida: ${result.outputUrl}`);
Configuración típica de AWS Lambda:
- Memoria: 1024-3008 MB (más memoria = más CPU = renderizado más rápido)
- Tiempo de espera: 300 segundos (5 minutos)
- Almacenamiento efímero: 512 MB - 10 GB
- Concurrencia: 100-1000 (ajustar según la carga de trabajo)
Configuración de Azure Functions
const renderer = new CloudRenderer({
provider: "azure",
quality: "standard",
downloadToLocal: true,
outputPath: "/output/video.mp4",
azureConfig: {
resourceGroup: "rendervid-rg",
storageAccount: "rendervidstore",
containerName: "renders",
},
});
const result = await renderer.render(template);
Configuración de Google Cloud Functions
const renderer = new CloudRenderer({
provider: "gcp",
quality: "standard",
downloadToLocal: true,
outputPath: "/output/video.mp4",
gcpConfig: {
projectId: "my-project-id",
bucketName: "rendervid-output",
region: "us-central1",
},
});
const result = await renderer.render(template);
Comparación de Costos
| Proveedor | Costo por Minuto | Costo por Hora | Notas |
|---|
| AWS Lambda | ~$0.02 | ~$1.00 | Pago por 1ms de cómputo |
| Azure Functions | ~$0.02 | ~$1.00 | Precios del plan de consumo |
| Google Cloud Functions | ~$0.02 | ~$1.00 | Pago por 100ms de cómputo |
| Docker (local) | Gratis | Gratis | Usa tu propio hardware |
Todos los proveedores de nube ofrecen niveles gratuitos que cubren cargas de trabajo significativas de renderizado durante el desarrollo y producción de bajo volumen.
Benchmarks de Rendimiento
El renderizado en la nube logra una aceleración de 10-50x en comparación con el renderizado secuencial en una sola máquina. La aceleración exacta depende del número de trabajadores, la complejidad de la plantilla y la duración del video.
| Duración del Video | Secuencial (1 máquina) | Nube (50 trabajadores) | Aceleración |
|---|
| 30 segundos | ~90 segundos | ~5 segundos | 18x |
| 2 minutos | ~6 minutos | ~15 segundos | 24x |
| 10 minutos | ~30 minutos | ~45 segundos | 40x |
| 30 minutos | ~90 minutos | ~2 minutos | 45x |
Los videos más largos se benefician más del paralelismo porque el overhead de inicio del trabajador y fusión de fotogramas se amortiza en más fotogramas.
Renderizado Local con Docker
El renderizado basado en Docker te da la misma arquitectura de renderizado paralelo que el renderizado en la nube, pero ejecutándose completamente en tu máquina local. Es completamente gratuito, no usa cuentas de nube, y es ideal para configuraciones auto-hospedadas, desarrollo y equipos que quieren renderizado paralelo sin costos de nube.
Cuándo Usar el Renderizado con Docker
- Renderizado paralelo gratuito sin cuentas de proveedores de nube
- Infraestructura auto-hospedada detrás de un firewall
- Desarrollo y pruebas de flujos de trabajo de renderizado en la nube localmente
- Cargas de trabajo pequeñas a medianas que se benefician del paralelismo pero no necesitan escalado automático
Instalación
# Asegúrate de que Docker esté instalado y ejecutándose
docker --version
# Instalar el paquete de renderizado en la nube
npm install @rendervid/cloud-rendering
Configuración
import { CloudRenderer } from "@rendervid/cloud-rendering";
const renderer = new CloudRenderer({
provider: "docker",
quality: "high",
downloadToLocal: true,
outputPath: "/output/video.mp4",
dockerConfig: {
volumePath: "/tmp/rendervid-work",
workersCount: 8, // Número de contenedores Docker para ejecutar en paralelo
},
});
const result = await renderer.render(template);
console.log(`Renderizado en ${result.renderTime}ms usando ${result.workersUsed} trabajadores`);
Elegir workersCount: Establece esto al número de núcleos de CPU disponibles en tu máquina. Por ejemplo, una máquina de 8 núcleos funciona bien con 8 trabajadores. Ir más allá del conteo de núcleos añade overhead por cambio de contexto sin mejorar el rendimiento.
Arquitectura de Docker
+------------------+
| Coordinador |
| (tu proceso) |
+--------+---------+
|
+-----+-----+-----+-----+
| | | | |
+--v--+ +--v-+ +-v--+ +-v--+
| C1 | | C2 | | C3 | | C4 | ... Contenedores Docker
+--+--+ +--+-+ +-+--+ +-+--+
| | | |
v v v v
+--+------+-----+------+--+
| Volumen Compartido |
| /tmp/rendervid-work |
+-------------+-------------+
|
v
+-------+--------+
| Fusionador |
+-------+---------+
|
v
+-------+---------+
| /output/video |
+-----------------+
Cada contenedor Docker es un trabajador autónomo con Node.js, Playwright y FFmpeg preinstalados. Los trabajadores leen sus asignaciones de fotogramas del volumen compartido, renderizan los fotogramas y escriben los resultados de vuelta. El coordinador luego fusiona todos los segmentos en la salida final.
Desenfoque de Movimiento
Rendervid admite desenfoque de movimiento a través de supermuestreo temporal. En lugar de renderizar un instante único por fotograma, el renderizador captura múltiples sub-fotogramas en puntos ligeramente diferentes en el tiempo y los mezcla juntos. Esto produce el desenfoque natural que las cámaras crean cuando los objetos se mueven durante una exposición.
Ajustes de Calidad
| Ajuste | Muestras por Fotograma | Multiplicador de Tiempo de Renderizado | Calidad Visual |
|---|
low | 5 | 5x | Suavizado sutil |
medium | 10 | 10x | Desenfoque notable en movimiento rápido |
high | 16 | 16x | Desenfoque de movimiento cinematográfico |
ultra | 32 | 32x | Grado de película, desenfoque pesado |
Configuración
const result = await renderer.render(template, {
format: "mp4",
quality: "high",
outputPath: "/output/cinematic.mp4",
motionBlur: {
enabled: true,
quality: "high", // 16 muestras por fotograma
},
});
Cómo Funciona el Supermuestreo Temporal
Fotograma N (sin desenfoque): Fotograma N (con desenfoque, 5 muestras):
Instante único: 5 sub-fotogramas mezclados:
+--------+ +--------+ +--------+ +--------+
| O | | O | + | O | + | O | ...
+--------+ +--------+ +--------+ +--------+
|
v
+--------+
| ~O~ | <- Resultado mezclado
+--------+
Cada sub-fotograma avanza la línea de tiempo de animación por un incremento diminuto (1/fps dividido por el conteo de muestras). Los sub-fotogramas luego se mezclan con alpha para producir el fotograma final. Los objetos que se movieron entre sub-fotogramas aparecen desenfocados a lo largo de su trayectoria de movimiento, mientras que los elementos estacionarios permanecen nítidos.
Consideraciones de Rendimiento
El desenfoque de movimiento multiplica el tiempo de renderizado proporcionalmente al conteo de muestras. Un video de 10 segundos a 30fps tiene 300 fotogramas. Con calidad high (16 muestras), el renderizador debe generar 4,800 sub-fotogramas en lugar de 300. Usa calidad draft durante el desarrollo y cambia a high o ultra solo para exportaciones finales.
El renderizado en la nube y el renderizado paralelo con Docker funcionan bien con desenfoque de movimiento porque el costo por fotograma se distribuye entre los trabajadores. Un aumento de 16x por fotograma dividido entre 16 trabajadores resulta aproximadamente en el mismo tiempo total de renderizado que un renderizado sin desenfoque en una máquina.
Exportación GIF
La exportación GIF de Rendervid va mucho más allá de una simple conversión de fotograma a GIF. Utiliza el pipeline de generación de paleta de FFmpeg para producir GIFs animados optimizados de alta calidad con difuminado configurable, conteos de colores y restricciones de tamaño de archivo.
Cómo Funciona la Optimización GIF
La codificación GIF estándar usa una paleta global única de 256 colores, lo que a menudo resulta en bandas y mala reproducción del color. Rendervid usa un enfoque de dos pasos:
- Paso 1 (palettegen): Analizar todos los fotogramas para generar una paleta óptima de 256 colores que mejor represente el rango completo de colores del video.
- Paso 2 (paletteuse): Re-codificar cada fotograma usando la paleta optimizada con difuminado opcional para gradientes suaves.
Ajustes de Optimización
| Ajuste | Resolución | Colores Máx | Caso de Uso Objetivo |
|---|
social | 480x480 | 256 | Instagram, Twitter, Slack |
web | 640x480 | 256 | Publicaciones de blog, documentación |
email | 320x240 | 128 | Campañas de email, boletines |
Opciones de Difuminado
| Algoritmo | Calidad | Tamaño de Archivo | Descripción |
|---|
floyd_steinberg | Mejor | Más grande | Difuminado de difusión de error, gradientes suaves |
bayer | Bueno | Medio | Difuminado ordenado, patrón consistente |
none | Más bajo | Más pequeño | Sin difuminado, regiones de color plano |
Configuración
const result = await renderer.render(template, {
format: "gif",
outputPath: "/output/animation.gif",
gif: {
preset: "social", // Resolución 480x480
colors: 256, // Paleta de 2-256 colores
dithering: "floyd_steinberg",
targetSizeKB: 5000, // Auto-optimizar para permanecer bajo 5MB
fps: 15, // FPS más bajo = archivo más pequeño
},
});
console.log(`Tamaño GIF: ${(result.fileSize / 1024).toFixed(0)} KB`);
console.log(`Tamaño estimado fue: ${result.estimatedSizeKB} KB`);
Estimación de Tamaño de Archivo y Auto-Optimización
Cuando estableces un targetSizeKB, Rendervid estima el tamaño del archivo de salida antes del renderizado y ajusta automáticamente los parámetros (conteo de colores, resolución, FPS) para cumplir con el objetivo. Esto es particularmente útil para plataformas con límites de tamaño de archivo (por ejemplo, límite de 50 MB de Slack, restricción típica de 10 MB de email).
// Auto-optimizar para ajustarse dentro de una restricción de email de 2MB
const result = await renderer.render(template, {
format: "gif",
outputPath: "/output/email-banner.gif",
gif: {
preset: "email",
targetSizeKB: 2000,
},
});
Arquitectura de Paquetes
Rendervid está organizado como un monorepo con 13 paquetes. Cada paquete tiene una responsabilidad enfocada, y se componen juntos para soportar cada escenario de despliegue.
@rendervid/
├── core Motor, tipos, validación, sistema de animación
│ ├── Analizador y validador de plantillas (AJV + JSON Schema)
│ ├── Motor de animación (40+ presets, 30+ funciones de suavizado)
│ ├── Sistema de capas (text, image, video, shape, audio, group, lottie, custom)
│ └── Gestión de escenas y transiciones (17 tipos)
│
├── renderer-browser Renderizado del lado del cliente
│ ├── Renderizado de fotogramas basado en Canvas
│ ├── MediaRecorder para exportación WebM
│ └── Codificador MP4 WebAssembly
│
├── renderer-node Renderizado del lado del servidor
│ ├── Navegador sin interfaz Playwright/Puppeteer
│ ├── Integración FFmpeg (fluent-ffmpeg)
│ ├── Aceleración por GPU
│ └── Pipeline de optimización GIF
│
├── cloud-rendering Orquestación multi-nube
│ ├── Proveedor AWS Lambda
│ ├── Proveedor Azure Functions
│ ├── Proveedor Google Cloud Functions
│ ├── Proveedor local Docker
│ ├── Divisor y fusionador de fragmentos
│ └── Adaptadores de almacenamiento de objetos (S3, Blob, GCS)
│
├── player Componente reproductor de video/plantilla
├── editor Editor visual de plantillas (estado Zustand)
├── components Componentes React pre-construidos
│ ├── AnimatedLineChart
│ ├── AuroraBackground
│ ├── WaveBackground
│ ├── SceneTransition
│ └── TypewriterEffect
│
├── templates Definiciones y ejemplos de plantillas (100+)
├── testing Utilidades de prueba
│ ├── Comparadores personalizados Vitest
│ ├── Ayudantes de prueba de instantáneas
│ └── Utilidades de regresión visual
│
├── editor-playground Entorno de desarrollo del editor
├── player-playground Entorno de desarrollo del reproductor
├── mcp Servidor Model Context Protocol
└── docs Sitio de documentación VitePress
Cómo se Conectan los Paquetes
- @rendervid/core es la base. Todos los demás paquetes dependen de él para tipos de plantilla, validación y el sistema de animación.
- @rendervid/renderer-browser y @rendervid/renderer-node ambos consumen plantillas core pero producen salida a través de diferentes pipelines (Canvas vs. FFmpeg).
- @rendervid/cloud-rendering envuelve
renderer-node y distribuye su trabajo a través de funciones en la nube o contenedores Docker. - @rendervid/player y @rendervid/editor son paquetes UI basados en React para reproducción y edición visual. El editor usa Zustand para la gestión de estado.
- @rendervid/components proporciona los componentes
React pre-construidos (AnimatedLineChart, AuroraBackground, etc.) que se pueden usar en plantillas.
- @rendervid/testing proporciona comparadores Vitest y ayudantes de prueba de instantáneas para validar plantillas.
- mcp es la capa de integración AI
que expone las capacidades de Rendervid a agentes AI a través del Model Context Protocol.
Stack Tecnológico
Rendervid está construido sobre un stack TypeScript moderno elegido por confiabilidad, rendimiento y experiencia del desarrollador.
| Capa | Tecnología | Propósito |
|---|
| Lenguaje | TypeScript | Seguridad de tipos en los 13 paquetes |
| Construcción | tsup, Vite | Construcciones rápidas, tree-shaking, salida ESM/CJS |
| Pruebas | Vitest | Pruebas unitarias, pruebas de instantáneas, comparadores personalizados |
| Framework UI | React 18.3.1 | Renderizado de componentes, composición de plantillas |
| Gestión de Estado | Zustand | Estado del editor (ligero, sin boilerplate) |
| Estilos | Tailwind CSS | UI del editor y reproductor |
| Validación | AJV con JSON Schema | Validación de plantillas antes del renderizado |
| Renderizado en Navegador | API Canvas HTML | Dibujo fotograma por fotograma en el navegador |
| Navegador sin Interfaz | Playwright, Puppeteer | Captura de fotogramas del lado del servidor |
| Codificación de Video | FFmpeg (fluent-ffmpeg) | Codificación H.264, H.265, VP9, ProRes, GIF |
| Gráficos 3D | Three.js (opcional), CSS 3D | Escenas 3D y transformaciones de perspectiva |
| Documentación | VitePress | Sitio de documentación de paquetes |
Pruebas
Rendervid incluye un paquete de pruebas dedicado (@rendervid/testing) que proporciona comparadores Vitest personalizados, ayudantes de prueba de instantáneas y utilidades de regresión visual para validar plantillas.
Comparadores Personalizados Vitest
import { describe, it, expect } from "vitest";
import "@rendervid/testing/matchers";
describe("Plantilla Showcase de Producto", () => {
it("debería ser una plantilla válida", () => {
expect(template).toBeValidTemplate();
});
it("debería tener las dimensiones correctas", () => {
expect(template).toHaveResolution(1920, 1080);
});
it("debería contener al menos una capa de texto", () => {
expect(template).toContainLayerOfType("text");
});
it("debería tener animaciones en el titular", () => {
expect(template.scenes[0].layers[0]).toHaveAnimation("entrance");
});
});
Pruebas de Instantáneas
Las pruebas de instantáneas renderizan una plantilla a una imagen y la comparan con una referencia almacenada. Cualquier cambio visual hace que la prueba falle, facilitando la detección de regresiones no deseadas.
import { describe, it } from "vitest";
import { renderSnapshot } from "@rendervid/testing";
describe("Regresión Visual de Plantilla", () => {
it("debería coincidir con la instantánea de referencia en el fotograma 0", async () => {
const snapshot = await renderSnapshot(template, { frame: 0 });
expect(snapshot).toMatchImageSnapshot();
});
it("debería coincidir con la instantánea de referencia en el punto medio", async () => {
const totalFrames = template.fps * template.scenes[0].duration;
const snapshot = await renderSnapshot(template, {
frame: Math.floor(totalFrames / 2),
});
expect(snapshot).toMatchImageSnapshot();
});
});
Pruebas de Regresión Visual en CI
Integra pruebas de regresión visual en tu pipeline CI/CD para detectar cambios de renderizado antes de que lleguen a producción:
# .github/workflows/visual-regression.yml
name: Pruebas de Regresión Visual
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- run: npx playwright install chromium
- run: npm ci
- run: npm run test:visual
Optimización del Rendimiento
Obtener los tiempos de renderizado más rápidos posibles requiere entender dónde se gasta el tiempo y qué palancas puedes accionar. Aquí están las estrategias de optimización más impactantes.
1. Elegir el Destino de Despliegue Correcto
| Escenario | Mejor Destino |
|---|
| Vista previa rápida durante la edición | Navegador |
| Video único, calidad de producción | Node.js |
| Lote de 10-100 videos | Node.js o Docker |
| Lote de 100+ videos o crítico en tiempo | Nube (AWS/Azure/GCP) |
2. Optimizar la Complejidad de la Plantilla
- Reducir el conteo de capas. Cada capa se renderiza independientemente. Menos capas significa menos operaciones de dibujo por fotograma.
- Usar calidad
draft durante el desarrollo y pruebas. Cambiar a high o lossless solo para exportaciones finales. - Simplificar animaciones durante la vista previa. Secuencias complejas de keyframes con muchas funciones de suavizado añaden cómputo por fotograma.
3. Usar renderWaitTime Sabiamente
La opción renderWaitTime pausa el renderizado para permitir que los medios externos (imágenes, videos, fuentes) se carguen. Establece esto al valor mínimo que asegure que todos los activos estén cargados. Un valor de 500-2000ms es típico. Establecerlo demasiado alto desperdicia tiempo en cada fotograma.
await renderer.render(template, {
renderWaitTime: 1000, // 1 segundo suele ser suficiente
});
4. Aprovechar el Renderizado Paralelo
Para cualquier video más largo de 10 segundos, el renderizado paralelo (Docker o nube) será más rápido que el renderizado secuencial. El punto de equilibrio depende de tu hardware y configuración de nube, pero como regla general:
- < 10 segundos: Un solo renderizador Node.js está bien
- 10-60 segundos: Docker con 4-8 trabajadores
- 1-10 minutos: Docker con 8-16 trabajadores o nube
- > 10 minutos: Renderizado en la nube con 50+ trabajadores
5. Optimizar la Salida GIF
Los GIFs son inherentemente grandes. Para mantener los tamaños de archivo manejables:
- Reducir el FPS a 10-15. La mayoría de los GIFs se ven bien a tasas de fotogramas reducidas.
- Reducir la resolución usando ajustes (
social, web, email). - Limitar los colores a 128 o menos para animaciones simples.
- Usar
targetSizeKB para dejar que Rendervid auto-optimice los parámetros. - Evitar el difuminado (
none) si el tamaño del archivo importa más que la calidad del gradiente.
6. Habilitar la Aceleración por GPU
En máquinas con GPUs compatibles, la codificación acelerada por hardware puede reducir los tiempos de renderizado en 2-5x para el paso de codificación. Esto es más impactante para salidas de alta resolución (4K+) y alto bitrate.
7. Pre-cargar Activos
Si tu plantilla hace referencia a imágenes o videos externos, pre-descárgalos al almacenamiento local antes del renderizado. La latencia de red durante el renderizado es la causa más común de renderizados lentos o fallidos.
Próximos Pasos