# Producción de audio: locución, canción y mezcla

Documentación 2026.11.01.3 · Contrato `auroflow/public-agent/v1`.

Entrada para un agente externo con su credencial propia. Usa [Conectar agente](https://auroflow.club/connect-agent.md) y la [skill de audio](https://auroflow.club/skills/auroflow-audio-production/SKILL.md). Descubre las capacidades vivas antes de escribir: esta página no certifica que Music esté operativo ni que una entrega se haya escuchado.

## Contrato de narración y mezcla

El esquema de `tools/list` y la respuesta viva prevalecen. En MCP comprobar
`isError` y `structuredContent.http_status`; un HTTP interno de error no es un
trabajo admitido. Los ejemplos con `<…>` son plantillas **no enviables**: usar
IDs observados y persistir los nuevos antes de enviar. REST recibe el objeto
directamente; MCP lo envuelve en `arguments.request` donde se indica.

Bootstrap JSON-RPC tras la inicialización del cliente MCP:

```json
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{"_meta":{"auroflow/toolset":"audio"}}}
```

Después, una llamada usa `method:"tools/call"` y
`params:{name:NOMBRE_ANUNCIADO,arguments:ARGUMENTOS}`. Conservar el esquema
devuelto; no enviar nombres de rutas REST como herramientas MCP. El Bearer es
una cabecera privada del transporte HTTPS, no parte del JSON del prompt.

`auroflow_queue {}` usa `GET /v1/queue` y forma parte del catálogo `audio`
de 14 herramientas. `response.queue.auxiliary_items` incluye sólo actividad
propia: tipos `narration` (`tts-…`), `music` (`mus-…`) y `native_media`
(`nm-…`), además de otros procesos propios. Mantiene el estado durable y una
proyección de actividad: `active`, `waiting` o `needs_attention`. Las rutas
`status_url` llevan al mismo trabajo autenticado; no son URLs del proveedor.

Los contadores son `auxiliary_pending` y `auxiliary_attention_required`.
Posición y ETA son null: esta proyección no inventa un orden entre los tres
recorridos. `waiting_native_turn` sólo se muestra cuando el recurso compartido
tiene otro propietario observado; si la causa no se conoce, se conserva
`waiting_for_worker`. Un envío ya efectuado puede esperar su resultado con
`waiting_for_result`. La consulta no inicia, recupera ni repite el trabajo.
Una base de actividad no verificable produce `auxiliary_metadata_degraded`
y conserva las otras filas disponibles; nunca se interpreta como cola vacía
confirmada. No confundir los contadores de Flow con la finalización del audio.

### Narración independiente

| MCP | REST |
| --- | --- |
| `auroflow_capabilities {area:"vids_voices", voice_id?}` | `GET /v1/voices/catalog?voice_id=…` |
| `auroflow_plan_narration {request}` | `POST /v1/voices/plan` |
| `auroflow_generate_narration_zero {request}` | `POST /v1/voices/jobs` |
| `auroflow_get {id}` | `GET /v1/voices/jobs/{id}` |
| `auroflow_list {kind:"narrations"}` | `GET /v1/voices/jobs` |
| `auroflow_recover {id,cost_max:0}` | `POST /v1/voices/jobs/{id}/recover` |
| `auroflow_recover {action:"resume_preparation", id,cost_max:0}` | `POST /v1/voices/jobs/{id}/resume-preparation` |
| Descargar `output.download_url` | `GET /v1/voices/jobs/{id}/audio` |

Request:

```json
{
  "id": "<NEW_PERSISTED_TTS_ID>",
  "voice_id": "<OBSERVED_VIDS_VOICE_ID>",
  "text": "Una idea. Una historia. Tu siguiente película.",
  "experimental_spanish_spain": false,
  "approved": true,
  "cost_max": 0
}
```

`id` tiene prefijo `tts-`; `voice_id`, `vids-`. Texto literal hasta 2400
caracteres, sin CR; `cost_max` es el entero 0. El esquema no tiene un campo de
duración ni velocidad. La opción regional añade una etiqueta al texto enviado
y puede pronunciarse; false evita ese experimento. Un `approved:true` representa
la autorización existente del usuario, no una nueva aprobación del contenido.

El plan está en `response.plan`; el trabajo y su recuperación, en
`response.job`; la lista, en `response.jobs`. Exigir `state:"completed"` antes
de usar `output`, con `sha256`, `bytes`, `technical` y `download_url`. El WAV es
PCM derivado de la exportación MP4 nativa, no el fichero TTS original. La
descarga es privada y autenticada. Los límites observados son tres trabajos
propios pendientes y cuarenta nuevas locuciones en 24 h; la cuota viva puede
bloquear antes.

Leer el mismo trabajo tras un error o timeout. Recover sólo recoge el envío
original. Para una preparación fallida **antes del primer envío**, usar
`auroflow_recover {action:"resume_preparation"}` con `{id,cost_max:0}` en MCP o
`POST /v1/voices/jobs/{id}/resume-preparation` con `{cost_max:0}` en REST.
No existe un alias `/v1/narration`. Conserva el request original autorizado,
propietario, voz, literal, fingerprint e ID nativo; responde en `response.job`.

Una admisión puede dejar `queued` y aún no acredita prueba nativa ni envío.
El servidor verifica la misma petición, voz, cuenta, documento y lock, con
estado nativo `preparation_required` o `prepared` y ausencia demostrada de
submit, ACK, resultado incierto, reserva, finalización o descarte. Un dato
desconocido bloquea. Sólo después puede retomar la preparación y su primer
envío con preflight vivo a0. No abre otro documento ni elige otra voz para
resolver esa intención. No aportar pruebas privadas desde el cliente.

Tras incertidumbre leer otra vez el mismo `tts-…`; no repetir ciegamente la
reanudación. Una ausencia de intención recuperable no permite fabricar una
salida, cambiar el texto ni crear otro ID. Un envío existente conserva su
recuperación collect-only.

### Música original de Vids

Consultar `auroflow_capabilities {area:"production"}` y su `features.vids_music`. Las
herramientas pueden estar publicadas y el adaptador de generación seguir
deshabilitado. Exigir disponibilidad nativa viva, misma cuenta, inclusión y
precio exacto0 antes de una única generación autorizada; un plan puro no
habilita el adaptador. No tomar un `cost` de política máxima por gasto observado.

| MCP | REST |
| --- | --- |
| `auroflow_plan_music {request}` | `POST /v1/music/plan` |
| `auroflow_generate_music_zero {request}` | `POST /v1/music/jobs` |
| `auroflow_get {id}` | `GET /v1/music/jobs/{id}` |
| `auroflow_list {kind:"music"}` | `GET /v1/music/jobs` |
| `auroflow_recover {id,cost_max:0}` | `POST /v1/music/jobs/{id}/recover` |
| `auroflow_recover {action:"resume_preparation", id,cost_max:0}` | `POST /v1/music/jobs/{id}/resume-preparation` |
| Descargar `output.download_url` | `GET /v1/music/jobs/{id}/audio` |

Request original de ejemplo **no enviable**, para un instrumental bajo la voz:

```json
{
  "id": "<NEW_PERSISTED_MUS_ID>",
  "prompt": "Instrumental original de pop cinematográfico cálido: piano sencillo, bajo suave y percusión discreta. Desarrollo luminoso, con espacio para una locución grave en español y un cierre limpio.",
  "duration_mode": "clip",
  "instrumental": true,
  "approved": true,
  "cost_max": 0
}
```

El prompt literal admite hasta2400 caracteres y LF, sin CR. No hay selector de
voz Vids en este request musical. El modelo observado depende del modo:
`clip` usa **Lyria 3**, aproximadamente30 s; `full_song` usa **Lyria 3.5**,
aproximadamente180 s. Conservar el modelo devuelto en plan, trabajo y recibo.
Ninguno garantiza duración
exacta ni un stem separado; medir el WAV terminado. `instrumental:false`
permite pedir canto con letra original dentro del prompt, sin garantizar que
se cante palabra por palabra. El ejemplo instrumental es una decisión de esta
receta; no convertir automáticamente una canción con canto pedida por el usuario.

El plan está en `response.plan`; crear/leer/recuperar devuelve `response.job`
y listar devuelve `response.jobs`. Exigir `completed` y comprobar el WAV
privado, SHA/bytes, metadatos y origen. Mantener canción, narración y mezcla
como recursos separados. Hay una cuota musical propia, que no es la cuota de
locuciones; leer los límites y disponibilidad anunciados sin inventar saldo.

Tras incertidumbre leer el mismo `mus-…`. Recover es sólo recogida del envío
original y no sintetiza. Un fallo anterior al envío puede quedar en atención.
Para retomar sólo esa primera preparación autorizada existe
`auroflow_recover {action:"resume_preparation"}`: MCP recibe `{id,cost_max:0}` y REST
`POST /v1/music/jobs/{id}/resume-preparation` recibe sólo `{cost_max:0}`.
Conservar el mismo `mus-…` y request ya guardado; la respuesta está en
`response.job`. La operación puede conducir al **primer envío** autorizado,
por lo que no es una lectura ni una recuperación collect-only.

Una respuesta admitida puede dejar el trabajo `queued`; no demuestra todavía
que la prueba nativa haya pasado ni que se haya enviado. El cliente no aporta
documentos, cuentas o pruebas privadas: el adaptador del servidor las verifica
antes de preparar o enviar. Consultar el mismo ID hasta conocer ese resultado.

El servidor exige prueba nativa de la misma petición y del estado
`preparation_required` o `prepared`, con ausencia demostrada de intención de
submit, ack y estado incierto. Si falta una prueba, existe un envío o su
estado no puede determinarse, rechaza y conserva atención; no reenvía.
Ante incertidumbre de esta operación leer el mismo trabajo antes de actuar.
Nunca crear otro ID ni usarla para sortear un envío incierto. Flow Music es otro
proveedor, con presupuesto incluido potencialmente positivo, y continúa
bloqueado mientras su cotización y colector no estén verificados.

### Fuentes propias y subida

`auroflow_list {kind:"sources"}` usa `GET /v1/motion/sources`. Fuentes admitidas:
`job` (`api-…`), `sequence` (`seq-…`), `casting` (UUID), `narration` (`tts-…`)
y `music` (`mus-…`) o `audio_upload` (`aud_<32hex>`). Son medios propios
terminados, no nombres de voces. `variant` es entera; para narración, música
Vids y upload sólo admite 1.

`music` resuelve sólo el WAV propio `completed` de Vids, con origen verificado
`native_vids_music_mp4_export`, SHA/bytes y PCM reales. Admite mono/estéreo,
8–192 kHz, 1–600 s y hasta128 MiB. La lectura y el caché vuelven a verificar
la fuente; no llaman a generar, recuperar ni avanzar la canción. El catálogo
la declara `video_available:false`, `audio_available:true`; no sirve como
`background`. Su descarga privada es `/v1/music/jobs/{id}/audio`. No pasar por
upload10 MiB una canción grande ya propia ni regenerarla para poder mezclarla.
La API/MCP no acredita que el selector web reconozca este tipo nuevo.

`auroflow_upload_audio {filename,mime_type,data_base64}` devuelve
`response.upload`. Para un archivo grande preferir `POST /v1/audio/uploads`
con cuerpo binario, su `Content-Type` y `X-Audio-Name:encodeURIComponent(filename)`.
No enviar JSON a esa ruta binaria. Admite hasta 10 MiB y 600 s, con MIME
`audio/wav`, `audio/x-wav`, `audio/mpeg`, `audio/mp4`, `audio/aac`, `audio/ogg`
o `audio/flac`. El recurso canónico es WAV PCM; su SHA puede diferir del
archivo comprimido de entrada. GET de la colección lista las subidas propias;
GET del ID lee metadatos y `/{id}/audio` descarga con autenticación.

No asumir que un `mix-…` terminado es un `source.kind` admitido. Si hay que
reutilizar su WAV en otro contrato, descargarlo con autenticación y subirlo
por la ruta de audio propia, respetando sus límites; conservar ambos SHA y el
vínculo de procedencia. No convertir una URL de descarga en fuente arbitraria.

### Mezcla WAV independiente

Usar este recorrido sólo si las herramientas y rutas están anunciadas por la
instancia. No necesita una base de vídeo ni una composición gráfica.

| MCP | REST |
| --- | --- |
| `auroflow_plan_audio_mix {request}` | `POST /v1/audio/mixes/plan` |
| `auroflow_create_audio_mix {request}` | `POST /v1/audio/mixes` |
| `auroflow_get {id}` | `GET /v1/audio/mixes/{id}` |
| `auroflow_list {kind:"audio_mix_queue"}` | `GET /v1/audio/mixes/queue` |
| `auroflow_recover {id,cost_max:0}` | `POST /v1/audio/mixes/{id}/recover` |
| Descargar `output.download_url` | `GET /v1/audio/mixes/{id}/audio` |

Request: `id:"mix-…"`, `duration_seconds` numérico de 0.05 a 600,
`tracks` con 0–8 capas, `cost_max:0`; `format:"wav"` es opcional.
Cada capa requiere `id:"audio-…"`, `role:"music"|"narration"|"video"` y
`source:{kind,id,variant?}`. Campos de mezcla:

| Campo | Regla |
| --- | --- |
| `timeline_start_seconds` | Inicio en la mezcla, 0 por defecto. |
| `source_start_seconds` | Inicio dentro de la fuente, 0; debe quedar audio real. |
| `duration_seconds` | Por defecto toda la mezcla. Inicio+duración debe caber; fijarla explícitamente si se retrasa la capa. |
| `gain_db` | −60 a +12; 0 por defecto. |
| `fade_in_seconds`, `fade_out_seconds` | 0 por defecto; cada uno hasta la mitad de la duración de su capa. |
| `muted` | Booleano, false por defecto; no elimina los controles de la fuente. |

El plan es puro: no resuelve fuentes, guarda, genera ni renderiza. Sus
`assets_verified:false` y `render_ready:false` no son un error de render.
La admisión fija propiedad, SHA y bytes; la cola asigna prioridad y turnos en
el servidor. No enviar prioridad, cuenta, ruta, código o URL del proveedor.

Leer `response.plan` para el plan, `response.job` para crear/leer/recuperar y
`response.queue` para la cola. REST `GET /v1/audio/mixes` devuelve `jobs`
propios. La cola pública muestra posiciones propias y agregados; no expone
IDs de otros usuarios. Una creación nueva responde 202; el mismo ID/intención
puede responder 200. Ninguna de esas respuestas acredita escucha.

El trabajo devuelve `request_sha256`, `fingerprint`, `source_pins`, revisión,
estado y, al terminar, `output` con `sha256`, `bytes`, `receipt_sha256`,
`technical`, `hash_verified` y `download_url`. El WAV final es PCM16 estéreo
a 48 kHz, con `round(duration_seconds*48000)` muestras. No se sintetiza audio;
un tramo insuficiente se rellena con silencio. `tracks:[]` o todas silenciadas
producen silencio. No hay loops, ducking, normalización ni estiramiento.

Persistir el request y el `mix-…` antes de crear. Ante incertidumbre leer ese
ID. Si quedó `needs_attention` por interrupción, la recuperación explícita del
mismo ID verifica las mismas fuentes fijadas y puede volver a encolar sólo el
render local; un recibo completo válido se reconcilia sin renderizar otra vez.
Un `failed` no garantiza recuperación automática: leer su error y conservar el
ID. No generar otra voz o canción para reparar una mezcla.

La intención WAV es inmutable. Para una corrección editorial de volumen o
tiempos, leer primero la mezcla anterior y guardar un request nuevo con otro
`mix-…` identificado como revisión de esa entrega, reutilizando las fuentes.
No hacerlo para sortear una respuesta incierta. `revision` en el trabajo
describe su evolución; no existe aquí un parche de composición por revisión.

### Descarga local y acabado sobre vídeo

En el Mac de este proyecto existe además el cliente local. Son plantillas no
ejecutadas, con IDs ficticios a sustituir:

```sh
python3 scripts/auroflow_agent.py music-audio mus-id-observado salida-musica.wav
python3 scripts/auroflow_agent.py audio-mix mix-id-observado salida-mezcla.wav
```

Son comandos de descarga del recurso terminado, no de generación. Sustituir
los IDs por los reales y elegir una salida nueva. Este helper adicional lee la
credencial original del Llavero del Mac; no copiar Llavero ni configuración a
otro ordenador. Un agente externo puede usar la URL autenticada y su propia
clave; no necesita instalar ese helper local ni acceder a la cuenta del operador.

Vids Music y Flow Music son adaptadores distintos. El primero exige su coste
vivo cero; el segundo puede consumir créditos **incluidos**, distintos del
coste cero de locución y mezcla. El request tipado de Music descrito arriba no
prueba su activación, precio vivo o salida recuperable. Una cuenta
autorizada o la existencia de un panel Music no certifican esas tres cosas.
Si permanece bloqueada, informar el bloqueo; usar una canción ya propia sólo
si eso satisface el encargo, sin fingir una canción nueva.

Para el vídeo, `composition.audio.tracks` usa estas mismas capas en las pistas
gráficas. Audio explícito reemplaza la base; añadir una capa `video` para
conservar su sonido. El alcance Motion es 1–60 segundos enteros a 24 fps,
distinto de la mezcla WAV de hasta 600 s. Guardar → planificar la revisión
observada → renderizar con un `motion-…` persistido → leer el mismo trabajo.
Cambiar volumen o título requiere nueva revisión/exportación, sin regenerar
las fuentes. `set_audio:null` restaura la base y `tracks:[]` la silencia.


## Ejemplo original: canción y narración grave en español

Propuesta editorial, **sin generación ni escucha acreditadas**. El objetivo es
una pieza de unos30 s con música instrumental y locución de unos20–25 s;
no fijar la duración final hasta medir los medios.
El nombre Auroflow y el texto hablado se conservan literalmente.

### Narración

Descubrir el catálogo. La descripción observada de `vids-holt`, «Tono grave e
informativo», encaja como candidata; `vids-knox`, «Tono grave y suave», es una
alternativa si no se ha fijado la voz. No sustituir una elección del usuario ni
atribuir región o género a esos nombres. La voz en español no certifica es-ES.

Literal original, 49 palabras:

> Cada historia empieza con una idea. Con Auroflow, conviertes esa idea en escenas, eliges tus personajes y construyes tu película. La narración, la música y los títulos se pueden ajustar por separado. Así puedes pulir el montaje sin volver a crear las tomas. Dale forma a tu próxima historia.

La lectura podría rondar 20–23 s; es una estimación, no un timing observado.
Usar `experimental_spanish_spain:false` evita añadir una etiqueta al envío.
Mantener el literal, medir el WAV y dejar su cola; no acelerarlo ni recortar
palabras para encajarlo. Si se necesita otra duración, decidir un nuevo texto
antes de sintetizar y conservar la intención anterior.

Si esa misma primera preparación queda en atención antes de cualquier envío,
usar la reanudación explícita `auroflow_recover {action:"resume_preparation"}` del
contrato, sin otro ID, texto o voz. Requiere prueba nativa de ausencia de envío;
la recuperación ordinaria sólo recoge un envío existente.

### Canción

Brief original: pop cinematográfico cálido, piano sencillo, bajo suave,
percusión discreta y un cierre luminoso. La voz en off debe seguir entendible.
Para este ejemplo usar el request musical `duration_mode:"clip"`,
`instrumental:true` del contrato, con intención propia `mus-…`. El objetivo
nativo ronda30 s y se verifica al terminar; no garantiza exactamente30 s.
El modo `clip` se observó con Lyria 3; `full_song`, con Lyria 3.5. No fijar
3.5 como modelo de la receta corta ni usar un nombre de voz como modelo musical.
Si se pide canción con canto, conservar letra y disponer ventanas musicales
sin narrador; no cambiarla automáticamente por instrumental.

Estribillo original opcional para ese canto:

> Una idea prende luz.  
> Una historia empieza en ti.  
> Auroflow, dale forma.  
> Tu película está por venir.

La letra y el brief no habilitan Music. Consultar proveedor, disponibilidad,
contrato, coste y recuperación antes de cualquier envío autorizado. Vids Music
exige coste vivo cero; Flow Music puede consumir créditos incluidos. Si el
adaptador no está operativo, conservar la canción pendiente. Si la primera
preparación autorizada falló antes de cualquier envío, consultar el mismo
`mus-…` y la operación explícita `auroflow_recover {action:"resume_preparation"}` descrita
en el contrato. Sólo se admite con prueba nativa de que nunca fue enviada;
`auroflow_recover` sigue siendo sólo recogida del envío original.
Una música propia subida es otra procedencia y debe identificarse como tal.

### Mezcla

Este request MCP es una plantilla **no enviable**. Los IDs deben resolverse;
los 30/23 s sólo sirven si se ha observado que la narración entera y su cola
caben en 23 s y que la música elegida cubre 30 s. En otro caso, cambiar esos
tiempos antes de crear la intención, nunca después de un envío incierto.

```json
{
  "request": {
    "id": "<NEW_PERSISTED_MIX_ID>",
    "duration_seconds": 30,
    "format": "wav",
    "cost_max": 0,
    "tracks": [
      {
        "id": "audio-narration",
        "role": "narration",
        "source": {"kind":"narration","id":"<OBSERVED_COMPLETED_TTS_ID>","variant":1},
        "timeline_start_seconds": 0,
        "source_start_seconds": 0,
        "duration_seconds": 23,
        "gain_db": 0,
        "fade_in_seconds": 0,
        "fade_out_seconds": 0,
        "muted": false
      },
      {
        "id": "audio-music",
        "role": "music",
        "source": {"kind":"audio_upload","id":"<OBSERVED_COMPLETED_AUDIO_UPLOAD_ID>","variant":1},
        "timeline_start_seconds": 0,
        "source_start_seconds": 0,
        "duration_seconds": 30,
        "gain_db": -20,
        "fade_in_seconds": 0.5,
        "fade_out_seconds": 2,
        "muted": false
      }
    ]
  }
}
```

−20 dB es un punto de partida editorial, no un nivel de sonoridad medido ni
garantía de inteligibilidad. Si hay canto simultáneo, escuchar su competencia
con el narrador y redistribuir las ventanas o el volumen conservando el encargo.
El rol `music` no aplica ducking por sí solo.

Si la canción ya se generó en Vids y figura propia, `completed` y verificada,
la capa `audio-music` puede referenciar directamente
`source:{kind:"music",id:"<OBSERVED_COMPLETED_MUS_ID>",variant:1}` en vez del
upload. No son dos capas simultáneas: elegir la procedencia real. Un WAV de
180 s puede superar 10 MiB y sigue siendo utilizable como `music` sin subirlo
otra vez. Medir esa duración; `full_song` no garantiza exactamente180 s.

Revisar el SHA final completo: primera y última palabra, literal de Auroflow,
respiraciones, posibles clics o clipping, huecos, colas y equilibrio musical.
La transcripción ayuda a encontrar diferencias pero no verifica el acento ni
la voz. Registrar duración/SHA técnicos y qué revisión se realizó; dejar
indeterminado lo que no se pudo oír.
