# 03 · Crear tu primer video

Esta es la guía principal del kit. Vas a producir un video vertical (9:16) de
principio a fin con el proyecto de ejemplo `ejemplo/proyecto-demo`. Primero a
mano, un comando por paso, para entender qué hace cada parte. Al final está el
atajo que corre todo con un solo comando.

> Todos los comandos se ejecutan desde la **raíz del repo**
> (`editor-video-estandar/`). Las rutas que aparecen son relativas a esa raíz.

---

## Antes de empezar

1. Tené resueltas las herramientas y las keys. Verificá con:

   ```bash
   npm run check
   ```

   Si algo falta, mirá `docs/01-instalar.md` (Node, ffmpeg, ffprobe, npx) y
   `docs/02-configurar-keys.md` (Kie, ElevenLabs, Suno). El check no imprime
   ninguna key: solo dice si está o no.

2. Tené presente que los pasos de imagen, animación, voz y música consumen
   créditos o cuota de API (Kie, ElevenLabs, Suno). El de la demo gasta alrededor
   de **72 créditos de Kie** (3 escenas × 6 cr de imagen + 18 cr de animación),
   más el consumo de voz en ElevenLabs y de un tema en Suno.

---

## El proyecto de ejemplo

Dentro de `ejemplo/proyecto-demo/` hay dos archivos de entrada que vos editás:

- **`guion.txt`** — el texto que va a leer la voz. Texto plano, en español.
- **`escenas.json`** — la lista de escenas y los ajustes del proyecto.

Cada **escena** es un **tramo** del video: una imagen creada con IA y luego
animada. El video final es la suma de los tramos, con la voz y los subtítulos por
encima y la música de fondo al final.

Así se ve `escenas.json` de la demo (resumido):

```json
{
  "slug": "demo",
  "aspect": "9:16",
  "voz": { "voice": "rachel", "model": "eleven_multilingual_v2" },
  "musica": { "prompt": "tech minimal, calm, cinematic, instrumental, no vocals", "volume": 0.12 },
  "escenas": [
    { "id": "escena-1", "imagen": "a friendly cartoon robot mascot waving...", "movimiento": "subtle breathing, one gentle blink..." },
    { "id": "escena-2", "imagen": "...pointing to the right...",              "movimiento": "subtle head tilt, gentle blink..." },
    { "id": "escena-3", "imagen": "...giving a thumbs up...",                 "movimiento": "subtle bounce, gentle blink..." }
  ]
}
```

Cada escena tiene:

- `id` — nombre del tramo (se usa para nombrar sus archivos).
- `imagen` — el prompt de texto con el que se crea la imagen.
- `movimiento` — el prompt con el que esa imagen cobra movimiento al animarse.

> **Dónde van los archivos.** Durante todo el flujo vamos a dejar el material
> intermedio en `ejemplo/proyecto-demo/composicion/assets/` y el video final en
> `ejemplo/proyecto-demo/export/`. Usá siempre esas mismas rutas: el paso de
> *build* las espera ahí.

---

## Modo manual: los 8 pasos

El orden es fijo:

```
imagen → animar → voz → transcribir → música → build → render → mezcla
```

### Paso 1 — Imagen

**Qué hace.** Crea la imagen de una escena a partir de un texto (texto → imagen,
como cuando le pedís una imagen a ChatGPT). Usa Kie.ai con el modelo `gpt-image`
por defecto. Además de guardar el PNG en disco, imprime una **URL remota** que
sirve para el paso siguiente (animar).

**Comando** (uno por escena):

```bash
node src/runners/imagen.mjs \
  --prompt "a friendly cartoon robot mascot waving at the camera, clean flat illustration, soft shapes, pure white background, centered with empty margins" \
  --out ejemplo/proyecto-demo/composicion/assets/escena-1.png \
  --aspect 9:16
```

Repetí con el prompt de `escena-2` y `escena-3`, cambiando también el `--out`
(`escena-2.png`, `escena-3.png`).

**Flags.** `--prompt` (obligatorio), `--out` (obligatorio),
`--model gpt-image|nano-banana` (por defecto `gpt-image`; `nano-banana` es más
barato pero **no escribe bien texto en español**), `--aspect` (por defecto
`9:16`).

**Produce.** `composicion/assets/escena-1.png` y, en la consola, la URL remota
de esa imagen.

---

### Paso 2 — Animar

**Qué hace.** Toma la imagen estática y le da movimiento sutil con un modelo I2V
(image-to-video). El modelo por defecto es Grok. El clip resultante queda
normalizado a 1080×1920, 30 fps y **sin audio**.

Tenés dos formas de pasarle la imagen:

- `--image <png>` — un archivo local. El runner lo sube a Kie para obtener una
  URL pública y después lo anima.
- `--image-url <url>` — la URL remota que imprimió el Paso 1.

**Comando** (uno por escena, usando el archivo local):

```bash
node src/runners/animar.mjs \
  --image ejemplo/proyecto-demo/composicion/assets/escena-1.png \
  --out ejemplo/proyecto-demo/composicion/assets/escena-1.mp4 \
  --movement "subtle breathing, one gentle blink, tiny hand wave, camera locked, seamless loop"
```

Repetí con `escena-2` y `escena-3` y su `movimiento`.

**Flags.** `--out` (obligatorio), y uno de `--image` o `--image-url`
(obligatorio). Opcionales: `--movement "..."` (si no lo pasás, usa un movimiento
sutil por defecto: respiración leve, un parpadeo, cámara fija, loop),
`--model grok|wan` (por defecto `grok`).

**Produce.** `composicion/assets/escena-1.mp4` (el tramo animado).

> El nombre del clip (`escena-1.mp4`) tiene que coincidir con el `id` de la
> escena en `escenas.json`. Así el *build* sabe qué clip va en cada tramo.

---

### Paso 3 — Voz

**Qué hace.** Genera la narración con ElevenLabs a partir de `guion.txt`.

**Comando** (una sola vez para todo el guion):

```bash
node src/runners/voz.mjs \
  --file ejemplo/proyecto-demo/guion.txt \
  --out ejemplo/proyecto-demo/composicion/assets/voz.mp3 \
  --voice rachel
```

**Flags.** Uno de `--text "..."` o `--file <txt>` (obligatorio), `--out`
(obligatorio), `--voice <id|alias>` (por defecto `rachel`),
`--model` (por defecto `eleven_multilingual_v2`).

> **Para español.** El alias `rachel` es una voz del catálogo en inglés. El
> modelo `eleven_multilingual_v2` lee español sin problema, pero para que suene
> natural conviene usar una voz en español: copiá su `voice_id` desde tu panel de
> ElevenLabs y pasalo con `--voice <id>`.

**Produce.** `composicion/assets/voz.mp3`.

---

### Paso 4 — Transcribir

**Qué hace.** Transcribe la voz con Whisper (local, vía HyperFrames, sin key) y
arma los subtítulos sincronizados palabra por palabra (estilo karaoke). Genera
tres archivos junto al audio: `transcript.json` (palabras crudas), `words.json`
(palabras limpias) y `groups.json` (grupos de 1–2 palabras, que es lo que usa el
*build* para los subtítulos).

**Comando:**

```bash
node src/runners/transcribir.mjs \
  --audio ejemplo/proyecto-demo/composicion/assets/voz.mp3 \
  --language es \
  --model small
```

**Flags.** `--audio <voz.mp3|video.mp4>` (obligatorio),
`--language` (por defecto `es`), `--model` (por defecto `small`).

> **Regla dura.** Nunca uses un modelo terminado en `.en` (como `small.en`) con
> audio en español: traducen al inglés y arruinan el original. Para español:
> `--language es --model small`.

**Produce.** `composicion/assets/transcript.json`, `words.json` y `groups.json`.

---

### Paso 5 — Música

**Qué hace.** Genera la música de fondo con Suno. Por defecto es **instrumental**
(no compite con la voz).

**Comando:**

```bash
node src/runners/musica.mjs \
  --prompt "tech minimal, calm, cinematic, soft synth pads, instrumental, no vocals" \
  --out ejemplo/proyecto-demo/composicion/assets \
  --name musica
```

**Flags.** `--prompt` (obligatorio), `--out <dir>` (obligatorio, es una
**carpeta**), `--name base` (por defecto `musica`), `--model` (por defecto
`V4_5`), `--withVocals` (sin este flag, sale instrumental).

**Produce.** Uno o dos archivos en la carpeta indicada, nombrados
`<base>-track<n>.mp3` — por ejemplo `composicion/assets/musica-track0.mp3`. Ese
es el que vas a usar en la mezcla.

---

### Paso 6 — Build (armar la composición)

**Qué hace.** Arma la composición HTML (HyperFrames) juntando los clips de cada
tramo, los subtítulos karaoke (`groups.json`) y la voz (`voz.mp3`), y escribe el
`index.html` que después se renderiza.

La carpeta `composicion/` es un proyecto HyperFrames: trae su `build.mjs` (el que
arma el `index.html`), su `package.json` con HyperFrames fijado en la versión
`0.6.20` y su configuración. El `build.mjs` lee los archivos de `assets/` que
generaste en los pasos anteriores.

**Comando** (se corre **dentro** de la carpeta de la composición):

```bash
cd ejemplo/proyecto-demo/composicion
node build.mjs
cd -
```

**Produce.** `ejemplo/proyecto-demo/composicion/index.html`.

---

### Paso 7 — Render

**Qué hace.** Renderiza la composición a MP4. Antes corre una validación de
HyperFrames; si hay avisos, igual continúa. El MP4 que sale ya incluye la voz y
los subtítulos (todavía sin la música de fondo).

**Comando:**

```bash
node src/runners/render.mjs \
  --dir ejemplo/proyecto-demo/composicion \
  --out ejemplo/proyecto-demo/export/demo-render.mp4
```

**Flags.** `--dir <carpeta con index.html>` (obligatorio),
`--out <mp4>` (opcional; si no lo pasás, deja el MP4 dentro de la carpeta de la
composición y te dice cuál es el más reciente).

**Produce.** `ejemplo/proyecto-demo/export/demo-render.mp4`. Puede tardar 1 a 3
minutos.

---

### Paso 8 — Mezcla

**Qué hace.** Mezcla la música de fondo con el video renderizado (que ya trae la
voz) y masteriza para redes (−16 LUFS y techo de pico). Si la música parece tener
voces, **bloquea** la mezcla y avisa: la música de fondo tiene que ser
instrumental para no taparse con la narración.

**Comando:**

```bash
node src/runners/mezclar.mjs \
  --video ejemplo/proyecto-demo/export/demo-render.mp4 \
  --music ejemplo/proyecto-demo/composicion/assets/musica-track0.mp3 \
  --out ejemplo/proyecto-demo/export/demo-final.mp4 \
  --volume 0.12
```

**Flags.** `--video` (obligatorio), `--music` (obligatorio), `--out`
(obligatorio), `--volume` (por defecto `0.12`; es el volumen de la música, de 0 a
1).

**Produce.** `ejemplo/proyecto-demo/export/demo-final.mp4` — el video final.

---

## Modo atajo: todo con un comando

Cuando ya entendiste los pasos, `pipeline.mjs` corre el flujo completo leyendo
`escenas.json` y `guion.txt`:

```bash
node src/runners/pipeline.mjs --project ejemplo/proyecto-demo
```

Hace, en orden: imagen y animación de cada escena → voz desde `guion.txt` →
transcripción → música → build → render → mezcla. Deja el material en
`composicion/assets/` y el video en `ejemplo/proyecto-demo/export/demo-final.mp4`.

**Reanuda donde quedó.** Si una escena ya tiene su `.mp4` en `assets/`, la saltea
en vez de volver a pagarla. Así, si algo se corta a mitad de camino, volvés a
correr el mismo comando y sigue desde donde estaba.

### Cortar en un paso con `--until`

Para frenar después de cierto paso (por ejemplo, revisar la voz antes de gastar
en música y render):

```bash
node src/runners/pipeline.mjs --project ejemplo/proyecto-demo --until voz
```

Valores de `--until`: `imagen`, `animar`, `voz`, `transcribir`, `musica`,
`build`, `render`. El paso indicado se ejecuta y el flujo se detiene ahí.

---

## Animar una imagen propia (la que creaste con ChatGPT)

Si ya tenés una imagen en disco (la que armaste con ChatGPT u otra herramienta),
podés saltarte el Paso 1 y animarla directo. El runner la sube a Kie para obtener
una URL pública y la anima con Grok:

```bash
node src/runners/animar.mjs \
  --image ./mi-imagen.png \
  --out ./mi-clip.mp4 \
  --movement "subtle breathing, gentle blink, camera locked, seamless loop"
```

Si en cambio ya tenés la imagen publicada en una URL, pasala con `--image-url`
en lugar de `--image` (no hace falta subirla).

> Las imágenes subidas a Kie se borran a los ~3 días. Animá poco después de
> subir.

---

## Abrir el video final

En macOS:

```bash
open ejemplo/proyecto-demo/export/demo-final.mp4
```

En Linux usá `xdg-open <archivo>` y en Windows `start <archivo>`.

Cuando estés conforme con la demo, copiá `guion.txt` y `escenas.json` a tu propia
carpeta de proyecto, cambiá los prompts y volvé a correr el flujo.
