# README_harness — Compositor del Short flagship "Equipo híbrido"

Harness de composición para el Short vertical 9:16 (~40s, voz Roberto) de Ai4Managers.
Toma el avatar HeyGen como capa base y produce el MP4 final con b-roll, carteles y
captions karaoke — todo en un solo render ffmpeg.

> Estética: editorial oscura obsidian + champagne. Carteles en Playfair Display
> (champagne #d4af37, tercio superior). Captions karaoke en Space Grotesk, zona segura.

---

## Archivos del harness

| Archivo | Qué es |
|---|---|
| `beats.json` | Timeline del flagship: 6 beats con ventanas de tiempo, `broll_file`, `cartel_text` y `cartel_t_start/t_end`. Incluye el cartel del HOOK "Y A DOCE AGENTES" (0–3s, sobre el avatar). |
| `compose_short.sh` | Script bash robusto (`set -euo pipefail`) que compone el Short. Idempotente, loguea cada paso, salta b-rolls ausentes sin romper. |
| `README_harness.md` | Este archivo. |
| `broll/` | B-rolls renderizados que se overlayean por beat: `broll/beat1.mp4` … `broll/beat6.mp4`. Faltan → se saltan. |
| `captions/` | Salida intermedia: `words.json` (transcripción), `captions.ass`, `carteles.ass`. |
| `tmp/` | Intermedios: `avatar_norm.mp4`, `filtergraph.txt`, logs. |
| `out/` | Render final (por defecto `out/equipo-hibrido-short.mp4`). |

---

## Dependencias (todas verificadas en el VPS)

- **ffmpeg** + **ffprobe** (6.1.1) — con filtros `ass`, `overlay`, `drawtext`, `volume`.
- **jq** (1.7) — parseo de `beats.json` / `words.json`.
- **hyperframes** (v0.4.6) — `hyperframes transcribe` para word-timings del VO.
- **faster-whisper** en `~/agents-claude-env` — fallback si hyperframes falla.
- **Fuentes** (instaladas en `~/.fonts/`):
  - `Playfair Display` — carteles (ya estaba en `~/.fonts/viral/`).
  - `Space Grotesk`, `Fraunces`, `JetBrains Mono` — paleta de marca, instaladas en `~/.fonts/ai4m-shorts/` por este harness (`fc-cache` corrido).

Verificación rápida:
```bash
hyperframes --version && ffmpeg -version | head -1 && jq --version
fc-match "Playfair Display"; fc-match "Space Grotesk"
```

---

## Orden exacto de ejecución

1. **(Paso previo, fuera del harness)** Roberto genera el avatar HeyGen 9:16 leyendo el VO
   completo y lo deja en `avatar/roberto-flagship.mp4` (ver `handoff/HANDOFF.md`).
2. **(Opcional)** Renderizar los b-roll a `broll/beat1.mp4` … `broll/beat6.mp4`.
   Si falta alguno, el harness lo salta — el render igual corre.
3. **Componer el Short:**

```bash
cd /home/clawd/playgrounds/ai4m-fear-shorts-prod
./compose_short.sh \
  --avatar /home/clawd/playgrounds/ai4m-fear-shorts-prod/avatar/roberto-flagship.mp4 \
  --work   /home/clawd/playgrounds/ai4m-fear-shorts-prod \
  --out    /home/clawd/playgrounds/ai4m-fear-shorts-prod/out/equipo-hibrido-short.mp4 \
  --lang   es
```

El resultado queda en `out/equipo-hibrido-short.mp4`.

---

## Qué hace el script (pasos A–F)

- **A. Normalizar avatar** → 1080×1920 @30fps. `scale=...:force_original_aspect_ratio=increase`
  (cubrir) + `crop` centrado. Mantiene el audio (VO) intacto. Verifica que tenga pista de audio.
- **B. Captions karaoke** → `hyperframes transcribe <avatar> -l es --json` (fallback a
  faster-whisper del venv). Genera `captions.ass`: 2–4 palabras por línea, Space Grotesk bold
  grande, texto blanco con borde/sombra oscura, **centrado**, en **zona segura** (`MarginV=420`
  px desde abajo, márgenes laterales 90 px). Resaltado word-by-word con tags `\k`.
- **C. Carteles** → del `beats.json`, un evento ASS por cartel en su ventana de tiempo.
  Playfair Display, champagne `#d4af37`, **tercio superior** (Alignment 8, `MarginV=300` desde
  arriba), fade-in/out sutil, fuera de la zona de captions. Soporta multi-línea (`\n` → `\N`).
- **D. B-roll** → por cada beat con `broll_file` existente: cover+crop a 1080×1920, se reubica su
  PTS al `t_start` del beat y se hace `overlay=0:0:enable='between(t,t_start,t_end)'` sobre el
  avatar. El audio sigue siendo el del avatar (VO continuo). B-rolls ausentes → skip, sin romper.
- **E. Audio** → mide `mean_volume` con `volumedetect` y aplica `volume=(-20 - mean)dB` para
  llegar a ~−20 dB. **No** usa `loudnorm`.
- **F. Export** → `libx264`, `-pix_fmt yuv420p`, `-movflags +faststart`, 1080×1920, `-r 30`.
  Carteles + captions se queman vía filtro `ass` en el mismo render. Verifica resolución y
  duración del output.

---

## Notas operativas

- **Idempotente:** re-correr sobrescribe intermedios y output. El filtergraph se guarda en
  `tmp/filtergraph.txt` para debug.
- **Sin avatar no corre:** error claro si falta `--avatar` o el archivo no existe. (El script
  **sí** se puede escribir/lintar sin el avatar — solo lo necesita para ejecutar.)
- **Validación de sintaxis:** `bash -n compose_short.sh` → sin errores.
- **B-roll incremental:** se puede correr el harness con 0, 1 o los 6 b-rolls; entrega siempre.
