PTENES
MÓDULO 2.2

🔧 Compuertas, scripts y determinismo

Ahora verás los comandos reales detrás de cada fase. Verás los scripts del motor — islands.py, cut.py, verify-cut.py, lint-timeline.py, captions.py, make-sfx.sh e mix-sfx.py — y la regla de determinismo que hace que todo esto sea confiable. Cada bloque se puede pegar e incluye cómo verificarlo.

6
Temas
~35min
Duración
Intermedio
Nivel
Práctica
Tipo
Secciones leídas en este módulo0% · 0 de 0
1

🎚️ silencedetect, no timestamps de Whisper

El corte no confía en los tiempos que devuelve Whisper — tienen un jitter de ±0,2–0,3s, lo que deja restos de silencio y palabras a medias. En su lugar, el motor mide el silencio real del audio con el silencedetect de ffmpeg. El script islands.py usa esa energía para encontrar los fragmentos de voz y proponer cuáles conservar, quedándote con la última toma de cada frase.

Objetivo

Detectar las islas de voz del material original mediante la energía del audio y generar un islands.json con la propuesta de KEEP/DROP — la base del corte, sin depender de los timestamps imprecisos de la transcripción.

terminal
python3 islands.py \
  --media  \
  --transcript word.json \
  --noise -30dB --d 0.35 \
  --out islands.json

Cómo verificar

El script imprime una tabla legible: cada islote con su tiempo, el texto y la propuesta KEEP/DROP con el motivo. Lee la tabla; si se escapó de la heurística alguna toma repetida o tangencial, corrige el campo "keep" en el islands.json antes de pasar al cut.py.

Conceptos clave: silencedetect, jitter, isla de voz, KEEP/DROP.

2

✂️ islands.py → cut.py → verify-cut.py

El corte es una cadena de tres scripts con una comporta dura al final. islands.py propone qué conservar; cut.py une las islitas con keep=true en un solo archivo; y verify-cut.py comprueba que el resultado esté limpio — sin silencios largos en el cuerpo ni repeticiones. Sale con exit 0 cuando pasa y exit 1 cuando falla. No animas nada antes de ese PASS.

islands.py → islands.json cut.py une keep=true → corte verify-cut.py exit 0 = APRUEBA revise keep comporta dura
La cadena de cortes: cada flecha pasa un artefacto al siguiente. La última caja (cian) bloquea el proceso — si el verify-cut.py si no devuelve exit 0, el corte no avanza a las animaciones.
terminal
# 1) monta o corte a partir das ilhotas com keep=true
python3 cut.py --islands islands.json --out edicion/corte-final.mp4

# 2) re-transcreva o CORTE (word-level) e verifique — bloqueante
python3 verify-cut.py \
  --media edicion/corte-final.mp4 \
  --transcript corte-word.json \
  --max-sil 0.6
echo "exit: $?"   # 0 = PASSA · 1 = FALHA

Cómo verificar

Mira el código de salida (echo "exit: $?"). 0 significa corte limpio — puedes animar. 1 significa que todavía hay un silencio largo en el cuerpo o una repetición audible: el script imprime exactamente lo que falló. Corrige los keep y ejecuta la cadena de nuevo hasta llegar a 0.

Conceptos clave: cadena de scripts, compuerta estricta, exit 0/1.

3

📏 lint-timeline.py: gap > 4s = error

La regla de ritmo «nunca más de 4s sin impacto visual» deja de ser un consejo y se convierte en verificación automática. O lint-timeline.py lee el motion/index.html de Hyperframes, mide la distancia entre los beats visuales y señala un error cuando encuentra un hueco mayor que el --max-gap (4s por defecto). Es una red de seguridad para el ritmo: no reemplaza revisar los fotogramas, pero detecta el fallo obvio antes de renderizar.

Objetivo

Ejecutar un lint estático en la línea de tiempo y fallar (exit ≠ 0) si hay algún tramo de más de 4s sin un beat visual, bloqueando el render de un reel con un bache de ritmo.

terminal
# lint do ritmo: falha se houver >4s sem beat visual
python3 lint-timeline.py motion/index.html --max-gap 4.0
echo "exit: $?"   # 0 = ritmo ok · ≠0 = buraco de ritmo

Cómo verificar

Si pasa, exit 0 y silencio. Si falla, el lint señala la línea y el intervalo del hueco ("gap de X s a partir de Ys"). Agrega un beat (corte, zoom, chip, B-roll o reveal) en ese punto del motion/index.html y vuelve a ejecutarlo hasta eliminar los errores.

Conceptos clave: lint estático, beat visual, --max-gap, compuerta de ritmo.

4

💬 captions.py: subtítulo a la altura del micrófono

O captions.py genera «beats» de subtítulos de 2–3 palabras, sincronizados con la voz, con estilo de retención. El truco anticliché está en el resaltado: las palabras que pasas en --keywords (números, nombres de marca, conceptos clave) se pintan en la tu color de acento. Como las keywords cambian con cada video, tus subtítulos nunca salen iguales a los de nadie.

Objetivo

Producir uno captions.json con beats cortos y una palabra clave destacada por beat, para subtítulos que apoyen lo que dices (a la altura del pecho/micrófono) en vez de repetirlo en la parte inferior de la pantalla.

terminal
python3 captions.py \
  --transcript corte-final.json \
  --max-words 3 \
  --keywords "" \
  --out captions.json

Cómo verificar

Abre el captions.json: cada beat tiene start, end y una lista words con hi:true en la palabra destacada. Comprueba que los tiempos coincidan con la voz y que la palabra destacada sea la correcta (si no hay coincidencia en las keywords, el script destaca la palabra más larga del beat).

Conceptos clave: beat de subtítulos, --keywords, color de acento, área segura.

5

🔊 make-sfx.sh + mix-sfx.py: SFX bajo la voz

El sonido se crea en dos pasos. make-sfx.sh sintetiza la paleta de efectos (whoosh, pop, type, buzz, boom, ding, riser) con ffmpeg — sin descargar nada, libre de derechos y siempre igual. Después, mix-sfx.py superpone cada efecto en el momento justo por debajo de la voz, con un limitador para que no sature. Pasas los eventos como una lista de [nome, segundo].

Objetivo

Generar la paleta de SFX localmente y mezclarla en el render en los tiempos de los cortes, entregando un final.mp4 con efectos que «producen» las transiciones sin competir con lo que dices.

terminal
# 1) sintetiza a paleta de SFX em ./sfx
bash make-sfx.sh sfx

# 2) mistura os efeitos sobre o render, por baixo da voz
python3 mix-sfx.py \
  --base render.mp4 --sfx-dir sfx --out final.mp4 \
  --events '[["boom",0.0],["whoosh",6.5],["ding",8.6]]'

Cómo verificar

Después del make-sfx.sh, comprueba que la carpeta sfx/ tiene los .wav (whoosh, boom, ding…). Después del mix-sfx.py, escucha el final.mp4: los efectos deben coincidir exactamente con los cortes y quedar por debajo de la voz. Si vuelves a recortar el video, los tiempos de los eventos cambian — retemporiza la lista --events.

Conceptos clave: paleta de SFX, eventos [nombre, t], ducking, limitador.

6

🎲 Determinismo en Hyperframes

Nada de esto funciona si cada render sale diferente. Por eso, las animaciones de Hyperframes son determinísticas: sin Math.random() y sin Date.now(), nada de repeat:-1 (repeticiones infinitas), y las líneas de tiempo quedan en estado paused, registradas para que el motor controle cada frame. Mismo proyecto → mismo frame, cada vez — condición para que el lint y el QC sean confiables.

✗ Rompe el determinismo

  • ✗Math.random() para posiciones/tiempos
  • ✗Date.now() / reloj del sistema
  • ✗repeat:-1 (bucle infinito)

✓ Mantiene el determinismo

  • ✓Valores fijos o derivados de la duración
  • ✓Repeticiones finitas calculadas
  • ✓gsap.timeline({paused:true}) registrada

Objetivo

Confirmar que el motor de motion (Hyperframes) esté instalado y disponible: el requisito previo para renderizar las timelines deterministas.

terminal
# confere que o motor de motion está disponível
npx hyperframes --version

# checagem rápida: nenhuma fonte de aleatoriedade na timeline
grep -nE "Math\.random|Date\.now|repeat:\s*-1" motion/index.html || echo "OK: determinístico"

Cómo verificar

O --version debe imprimir un número (motor instalado). El grep debe imprimir OK: determinístico: si enumera líneas, hay una fuente de aleatoriedad que debe eliminarse antes de renderizar. Ejecuta el lint-timeline.py justo después: los dos juntos garantizan un render reproducible.

Conceptos clave: determinismo, repetición finita, pausado, reproducibilidad.

✅ Resumen del módulo

✓
Corte por silencio real — islands.py encuentra las islitas por energía, no por las marcas de tiempo de Whisper.
✓
Cadena con compuerta estricta — cut.py monta y verify-cut.py bloquea (exit 0/1) antes de animar.
✓
Ritmo y subtítulos verificados — lint-timeline.py bloquea gaps >4s; captions.py destaca tus keywords.
✓
SFX local y render determinista — make-sfx.sh/mix-sfx.py y Hyperframes sin random/now: misma entrada, misma salida.

Siguiente ruta:

Ruta 3 — Cómo usarla: instalar el stack, generar tu skill en la entrevista y crear el primer reel.