timeline-video
Un modelo de video largo puede mantener una sola toma durante 30 segundos si el prompt le dice qué sucede en cada segundo. Este skill es la capa de guionización: el formato, el arte que lo hace funcionar y scripts/timeline_video.py, que verifica un guión, lo cotiza, lo renderiza en la API asíncrona de OpenRouter y genera una hoja de contactos para revisarlo. Python 3.8+ librería estándar; ffmpeg solo para la hoja de contactos.
Los seis bloques
Un guión es un archivo Markdown: front matter opcional, luego seis bloques en este orden. Todo después del front matter se envía como prompt, palabra por palabra.
---
duration: 30
aspect: 16:9
resolution: 720p
model: bytedance/seedance-2.5
---
[CHARACTER] Quién, exactamente: edad, rostro, cabello, gafas, cada prenda, postura, qué tiene en las manos, el vehículo o accesorio y su color, dónde está. Terminar con el candado: "Mantener rostro, cabello, atuendo y <accesorio> idénticos durante los 30 segundos."
[STYLE] Live-action o no, "una sola toma sin cortes", aspecto, enfoque según tamaño de plano, hora del día y la luz que proporciona, la paleta como colores nombrados, textura, un pequeño movimiento constante (viento en el cabello), el registro cómico y una prohibición de cortes, congelados y cámara lenta.
[AUDIO] La base ambiental como lista de sonidos específicos. Luego señales en el reloj: "0.8s: un alerta de mensaje nítido." "1.2–4.0s: <quién>, fuera de cuadro, <cómo suena>: "<las palabras exactas>" ." Luego qué hace el sonido mientras la imagen cambia.
[TIMELINE]
0.0–1.0s — <encuadre> <acción> <un detalle>.
1.0–4.0s — ...
... (las ventanas tocan final con inicio, de 0 a la duración, sin espacios)
[CAMERA RULES] Las leyes de continuidad: un movimiento ininterrumpido por etapa, suavizando entrada y salida, horizonte nivelado, sujeto cerca del centro, cada etapa más lejos que la anterior, qué línea directriz se queda dónde.
[NEGATIVE] Sin cortes ni fotogramas negros, sin otras personas, sin texto, subtítulos, o logos, ...
templates/script.md es una plantilla en blanco para copiar; examples/the-sandbar.md es un guión completo de 30 segundos.
Qué lo hace funcionar
- Una premisa, cuatro compases. Calma → un desencadenante que oyes (un ping, luego una nota de voz pidiendo algo) → una reacción inexpresiva en primer plano → la revelación. En la forma de zoom out, la revelación es el remate: cada alejamiento muestra lo imposible que es la petición desde aquí.
- El primer segundo ya muestra a la persona. Sin plano de establecimiento; el desplazamiento se detiene en un rostro.
- Bloquea la identidad por escrito. Nombra cada atributo visible una vez, luego la línea "idéntico durante todos los N segundos". La deriva es lo que rompe una toma larga.
- Un acento saturado. Silencia la paleta y dale al accesorio del sujeto el único color fuerte, para que el ojo lo encuentre cuando mida tres píxeles al final.
- Escala la revelación. Cada etapa viaja más lejos que la anterior, y cada ventana nombra qué se vuelve visible a esa escala: la entrada, la salida, el horizonte. La geografía cuenta la historia.
- El audio refleja la cámara. Ajustado y cercano al inicio, luego solo viento, más amplio y vacío a medida que se aleja.
- Sincroniza la voz. Aproximadamente 2.5 palabras por segundo: una ventana de 2.8 segundos contiene unas siete palabras.
- Deja el último tercio en silencio. Lento, amplio y vacío es donde va el copy después.
- Nunca pidas al modelo texto, logos o marcas. Los distorsiona y pinta insignias en vehículos a menos que los negativos lo prohíban. Coloca las líneas después con tus propias fuentes, sobre el silencio amplio.
Formas además del zoom out: el push-in (el remate es un detalle), el follow (una caminata larga comprime el tiempo), la órbita (el mundo cambia alrededor de un sujeto quieto). Mismos seis bloques; las reglas de cámara cambian.
Ejecútalo
S=<directorio de este skill>/scripts/timeline_video.py
python3 $S check film.md # analiza los bloques, verifica el reloj, imprime los compases
python3 $S models --model bytedance/seedance-2.5 # duraciones, resoluciones, aspectos, audio, precio
python3 $S render film.md -o out/ --key-file ~/keys/openrouter.key # cotiza, envía, consulta, descarga
python3 $S sheet out/film.mp4 film.md # un fotograma por compás → out/film_beats.jpg
| Banderas (render) | Qué hace |
|---|---|
-o DIR | Dónde va el MP4 y su sidecar. El nombre del archivo es el del guión. |
--model, --duration, --resolution, --aspect | Sobreescribe el front matter. Cada uno se verifica contra las capacidades publicadas del modelo antes de enviar nada. |
--seed N | Pasa una semilla (se respeta solo donde el modelo lo soporta). |
--no-audio | Solicita un video sin audio. El audio está activado por defecto para modelos que lo generan. |
--key-file F | Lee la clave de OpenRouter desde un archivo. Sino, se usa OPENROUTER_API_KEY. La clave nunca se imprime ni se guarda. |
--dry-run | Solo verifica y cotiza. |
Costo. render imprime el precio antes de enviarlo. Los modelos por segundo son exactos. Seedance se cotiza por token de video, y OpenRouter no publica la conversión, por lo que su cifra está etiquetada como estimación (tokens ≈ ancho × alto × 24 fps × segundos ÷ 1024). Verificado en un trabajo real: 30s a 720p se estimó en $6.93 y se cobró $6.94. El cargo real siempre está en el usage.cost del sidecar. Renderiza uno, míralo y luego decide sobre repeticiones.
Lo que obtienes: <nombre>.mp4 y <nombre>.json — modelo, parámetros, el prompt y su SHA-256, los IDs del trabajo y generación, tiempos y el bloque usage. Mantenlos juntos; el sidecar es cómo se reproduce una toma.
Revisa antes de usarlo
ffprobeal archivo: la duración que pediste y un flujo de audio si lo pediste.sheet, luego mira cada compás: mismo rostro, cabello y atuendo en todo momento; el color de acento se mantiene; la revelación escala; sin texto, logos ni personas extra.- Escucha: el desencadenante llega en su señal y la voz dice las palabras exactas.
Un compás fallido es una repetición (nueva semilla) o una corrección del guión, generalmente una ventana vaga hecha más específica.
Cuando falla
| Salida | Significado |
|---|---|
0 | Hecho |
1 | OpenRouter rechazó o el trabajo terminó en failed, cancelled o expired; su error se imprime tal cual |
2 | El guión o un parámetro está mal (bloque faltante, espacio en el reloj, duración que el modelo no ofrece) |
4 | Sin clave |
Un trabajo de video no es de retención de datos cero: el proveedor conserva la salida brevemente para la descarga.
Crédito
El formato sigue el prompt de Seedance que @iamneubert compartió con el desglose de un anuncio viral de una sola toma (https://x.com/iamneubert/status/2099199895039336459). Este skill no contiene nada de ese prompt o video.