Estilo de Video Cinematic Beats
Filosofía Central
Lo visual marca el ritmo. El audio sigue. Las animaciones y escenas ASCII se reproducen en su duración natural — NO se truncan, aceleran ni mantienen en fotogramas finales para coincidir con la duración del audio. El silencio entre beats es un diseño intencional, no un vacío que llenar.
- TTS: Una oración por clip. Máxima relación señal-ruido. Sin narración de relleno.
- Visuales: Duración natural completa. Deja que las animaciones respiren.
- Cortes: Solo cortes directos. Sin encadenados.
- Música: Pistas proporcionadas por el usuario con reducción automática de volumen durante las secciones de diálogo.
- Puntos de control: Después de cada fase de producción, entrega los activos al usuario para revisión antes de continuar.
Estructura del Proyecto
~/videos/[nombre-del-proyecto]/
project.md # Documento vivo — guion gráfico, decisiones, notas de revisión
beats/ # Activos individuales de cada beat
beat-01/
visual.mp4 # Visual generado (imagen con movimiento o animación)
audio.mp3 # Clip TTS para este beat (solo MP3 — ver Reglas Críticas)
note.txt # Descripción de una línea de lo que muestra este beat
beat-02/
...
music/ # Pistas de música de fondo proporcionadas por el usuario
output/ # Renderizados intermedios y finales
Fase 1: Guion de Beats
Crea project.md con el desglose de beats. Cada beat = un visual + una oración TTS.
Escribiendo Beats
Reglas TTS:
- UNA oración por beat. Punto.
- Máxima relación señal-ruido — cada palabra se gana su lugar.
- Si un pensamiento necesita dos oraciones, son dos beats.
- Objetivo: 5-15 palabras por clip. Más corto es mejor.
- Sin relleno introductorio ("Entonces...", "Ahora veamos..."). Empieza en el punto.
Reglas visuales:
- Describe lo que muestra el visual — no cuánto dura.
- La duración del visual se determina por su finalización natural, NO por la duración del TTS.
- Cortes de imagen: imagen estática con movimiento Ken Burns (zoom/desplazamiento lento). Duración: 4-6s mínimo.
- Cortes animados (p5js/manim/ascii): la animación completa se reproduce. Lo que sea necesario — 8s, 12s, 15s.
- La duración del beat = max(duración_visual, duraci án_audio) + pausa.
Plantilla de beat en project.md:
# [Nombre del Proyecto]
## Concepto
[Un párrafo — de qué trata este video y la sensación que buscamos]
## Música
- Pista: [nombre del archivo o descripción de la música que el usuario proporcionará]
- Ambiente: [descripción]
## Beats
### Beat 01
**Visual:** [tipo: image | p5js | manim | ascii] — [prompt/descripción]
**TTS:** "Una oración contundente."
**Estado:** [ ] visual [ ] audio [ ] aprobado
### Beat 02
...
## Notas
[Registro continuo de decisiones, revisiones, comentarios del usuario]
Tipos de Corte
| Tipo | Herramienta | Duración | Mejor Para |
|---|---|---|---|
image | image_generate + Ken Burns | 4-6s | Fotos, escenas, retratos, planos de establecimiento |
p5js | skill p5js | Natural (8-15s) | Arte generativo, partículas, visualización de datos, campos de flujo |
manim | skill manim-video | Natural (8-20s) | Animaciones matemáticas, diagramas, explicaciones técnicas |
ascii | skill ascii-video | Natural (6-12s) | Estética de terminal, computación retro, temas de hacking |
caption | ffmpeg drawtext | 4-8s | Texto TTS centrado sobre fondo oscuro — enfoca la atención en las palabras |
CRÍTICO: Antes de producir cualquier beat p5js/manim/ascii, carga el skill con skill_view(name) primero. Estos skills contienen paletas de marca, reglas de fuentes y patrones de implementación que deben seguirse exactamente.
Fase 2: Puerta de Aprobación del Guion
DETENTE. Presenta project.md al usuario. No generes activos hasta que esté explícitamente aprobado.
Actualiza la sección de Notas de project.md con la marca de tiempo de aprobación.
Fase 3: Generar Visuales
Genera todos los activos visuales según su tipo. Guárdalos como beats/beat-XX/visual.mp4.
Beats de imagen (Ken Burns con filtro VHS)
- Genera la imagen mediante
image_generate - Aplica el filtro VHS a la imagen (grano, líneas de escaneo, viñeta, aberración cromática):
python3 scripts/vhs-filter.py \
--input beat-XX-image.png \
--output beat-XX-vhs.png \
--seed 42 \
--intensity 1.0
Requisitos: pip install numpy Pillow (numpy para los efectos de matriz, Pillow para E/S de imagen).
Niveles de intensidad: 0.7 (sutil — solo grano + viñeta), 1.0 (estándar — todos los efectos), 1.5 (fuerte — aberración cromática marcada, líneas de escaneo visibles). El valor predeterminado es 1.0.
- Aplica el movimiento Ken Burns a la imagen con filtro VHS para crear MP4:
ffmpeg -loop 1 -i beat-XX-vhs.png -t 5 \
-vf "zoompan=z='min(zoom+0.001,1.3)':x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':d=125:s=1920x1080:fps=25" \
-c:v libx264 -pix_fmt yuv420p -r 25 beats/beat-XX/visual.mp4
¿Por qué VHS primero, luego Ken Burns? El filtro zoompan difuminaría el grano y las líneas de escaneo. Aplica VHS a la imagen estática primero, luego añade movimiento encima. El movimiento Ken Burns sobre la imagen con filtro VHS crea una sensación analógica vivida — como ver grabaciones antiguas a través de un CRT ligeramente degradado.
Beats animados (p5js/manim/ascii)
Carga el skill relevante primero, luego genera. Guarda la salida como beats/beat-XX/visual.mp4.
Resolución: Todos los visuales deben ser 1920x1080 a 25fps. Escala las salidas de manim:
ffmpeg -y -i raw-manim.mp4 \
-vf "scale=1920:1080:flags=lanczos,setsar=1:1,fps=25" \
-c:v libx264 -pix_fmt yuv420p -r 25 beats/beat-XX/visual.mp4
Agrupa las llamadas a image_generate en grupos de 6. Si se marca, reformula neutralmente y reintenta una vez.
Referencia del Filtro VHS
El filtro VHS (scripts/vhs-filter.py) aplica estos efectos a una sola imagen:
| Efecto | Qué hace | Resultado visual |
|---|---|---|
| Aberración cromática | Desplazamiento de canales R/B (0-2px) | Franjas de color en los bordes, como un CRT desalineado |
| Ruido analógico | ±8 de grano por canal (escalado por intensidad) | Textura similar a película en sombras y tonos medios |
| Líneas de escaneo | Cada 4ª fila oscurecida al 96% | Superposición de rejilla de fósforo CRT |
| Viñeta CRT | Oscurecimiento de bordes (15-35% según intensidad) | Esquinas de pantalla redondeadas, como TV antigua |
Para imágenes: Todos los efectos se aplican una vez con una sola semilla aleatoria. La aberración cromática y el ruido son visibles; la vibración/líneas de seguimiento son sutiles ya que solo hay un fotograma.
Nota: Este filtro es solo para imágenes — no procesa entrada de video. Para obtener movimiento, aplica el filtro a un fotograma estático primero, luego añade Ken Burns/zoompan encima.
Fase 3.5: Punto de Control Visual
DETENTE. Envía cada clip visual al usuario para revisión.
Incluye la captura de pantalla o MP4 con rutas MEDIA. Preséntalos numerados:
Beat 01: [ruta MEDIA] — [breve descripción]
Beat 02: [ruta MEDIA] — [breve descripción]
...
Pregunta: "¿Alguna edición necesaria antes de continuar con el audio?"
No generes TTS hasta que el usuario apruebe los visuales. Registra los comentarios en las Notas de project.md.
Si se solicitan cambios, regenera solo los beats afectados y vuelve a realizar el punto de control.
Fase 4: Generar Audio TTS
Genera TODOS los clips TTS — uno por beat. Usa la herramienta text_to_speech con output_path como .mp3. Guárdalos como beats/beat-XX/audio.mp3.
CRÍTICO: Usa siempre formato MP3 para el audio. OGG tiene problemas de compatibilidad de códec con la entrega por Telegram y las operaciones de concat de ffmpeg. Configura el proveedor TTS como OpenAI con salida MP3.
Reglas:
- Una oración por llamada. Sin concatenación.
- Mide la duración de cada clip con ffprobe después de la generación.
- Registra las duraciones en project.md junto a cada beat.
ffprobe -v error -show_entries format=duration -of csv=p=0 beats/beat-XX/audio.mp3
Fase 4.5: Punto de Control de Audio
DETENTE. Presenta los clips de audio al usuario.
Aplicar filtro de voz (obligatorio)
Aplica la cadena de bitcrush seco-húmedo a cada clip TTS — esta es nuestra voz característica. Consulta references/dry-wet-bitcrush.md para la técnica completa y los posibles problemas.
Dos enfoques disponibles:
A) Mezcla estática (simple, consistente):
# Paso 1: Crear versión triturada mediante intermediario wav (preserva la duración)
ffmpeg -y -i beats/beat-XX/audio.mp3 \
-af "aresample=resampler=soxr:osr=2000,aformat=sample_fmts=u8,aresample=resampler=soxr,lowpass=f=2500" \
temp-crushed.wav
# Paso 2: Mezclar seco + húmedo con pegamento de compresión
ffmpeg -y -i beats/beat-XX/audio.mp3 -i temp-crushed.wav \
-filter_complex "[0:a]volume=0.7[dry];[1:a]volume=0.3[wet];[dry][wet]amix=inputs=2:duration=first:normalize=0,acompressor=threshold=0.05:ratio=4:attack=10:release=100[out]" \
-map "[out]" beats/beat-XX/audio-filtered.mp3
rm temp-crushed.wav
B) Mezcla dinámica (efecto de degradación de señal — preferido):
Usa el script de Python (scripts/vibey-mix.py) con sobremuestreo de retención de orden cero para un bitcrush auténtico al tono correcto.
Requisitos: pip install numpy pydub (numpy para procesamiento de matrices, pydub para lectura/escritura de MP3).
Parámetros fijos (variante dec5-bit8):
- Decimación: 5× (elimina cada 5ª muestra, luego repite mediante retención de orden cero)
- Cuantización: 8 bits (constante)
- Línea base seco/húmedo: 80% seco / 20% húmedo
- Patrón de caída: Cada ~1.2s, lo seco cae a ~35%, lo húmedo sube a ~65% (duración ~0.25s)
- Trémolo solo en húmedo: Onda triangular de 4Hz, profundidad 70% (lo húmedo pulsa entre 30-100%)
- Retardo slapback: 80ms a -18dB (~0.12 de volumen), aplicado a la mezcla final
python3 scripts/vibey-mix.py beats/beat-XX/audio.mp3
cp beats/beat-XX/audio-dynamic.mp3 beats/beat-XX/audio-filtered.mp3
Desglose de la cadena: Señal seca limpia superpuesta con artefactos digitales extremos (decimación 5×, cuantización de 8 bits mediante sobremuestreo de retención de orden cero), caídas periódicas que elevan el nivel húmedo para un efecto de "transmisión degradante", trémolo en la señal húmeda para pulsaciones rítmicas, y retardo slapback para espacio. Mantén la estructura de la cadena intacta — solo ajusta parámetros individuales si es necesario.
Usa audio-filtered.mp3 en todas las fases posteriores. Conserva el audio.mp3 original como referencia.
Registra las decisiones en las Notas de project.md.
Fase 5: Componer Beats
Para cada beat, fusiona el visual + audio con corte directo (sin transición). La duración del beat se determina por el que sea más largo — visual o audio.
Si visual >= audio:
El audio se reproduce durante todo el visual. No se necesita relleno.
ffmpeg -i beats/beat-XX/visual.mp4 -i beats/beat-XX/audio-filtered.mp3 \
-c:v libx264 -pix_fmt yuv420p -c:a aac \
-shortest -r 25 output/beat-XX-composed.mp4
Si audio > visual:
El visual mantiene su fotograma final para llenar el tiempo restante. Usa tpad en el video:
AUDIO_DUR=$(ffprobe -v error -show_entries format=duration -of csv=p=0 beats/beat-XX/audio-filtered.mp3)
ffmpeg -i beats/beat-XX/visual.mp4 -i beats/beat-XX/audio-filtered.mp3 \
-vf "tpad=stop_mode=clone:stop_duration=$AUDIO_DUR" \
-c:v libx264 -pix_fmt yuv420p -c:a aac \
-t $AUDIO_DUR -r 25 output/beat-XX-composed.mp4
Si no se ha aplicado filtro de audio, usa audio.mp3 en lugar de audio-filtered.mp3.
Pausa entre beats
Añade un breve fotograma negro entre beats para dar espacio:
ffmpeg -f lavfi -i color=c=black:s=1920x1080:d=0.15:r=25 \
-c:v libx264 -pix_fmt yuv420p output/pause-XX.mp4
Beats de caption ASCII (enfoque en palabras)
Cuando la narración misma es el punto focal — no el visual — usa un beat de estilo ASCII con el texto TTS centrado en pantalla. Marca estos en project.md como tipo [caption]:
Plantilla de beat:
### Beat 03 [caption]
**Visual:** caption ascii — texto centrado, fondo oscuro, estética sutil de terminal
**TTS:** "Las palabras exactas que aparecen en pantalla."
**Estado:** [ ] visual [ ] audio [ ] aprobado
Genera con ffmpeg drawtext sobre un fondo negro/oscuro con fuente monoespaciada y texto en oro ALLMIND (#C5A55A):
TEXT="Tu oración TTS aquí"
ffmpeg -f lavfi -i color=c=black:s=1920x1080:d=6:r=25 \
-vf "drawtext=text='${TEXT}':fontsize=42:fontcolor='#C5A55A':fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf:x=(w-tex