Un descuento en los planes premium al registrarteConsigue tu descuento

blog/developers·24 sept 2026·7 min·por el equipo de eroq

Cinema vía API de films: guion, storyboard, render y exportación

El lado guionizado de Cinema: el proyecto v2 en /v1/films, cómo la ruta de render lee el guion, la re-firma de medios y cómo guardar y publicar un montaje.


Todo lo que hace el espacio de Cinema pasa por /v1/films, y el estudio es un cliente más de esa API. Esta guía es para el desarrollador que quiere construir o automatizar películas: el formato de proyecto que las rutas tratan como opaco, la llamada de render que lee el guion, el mapa de medios, la ruta de exportación y los límites. Da por hecho que leíste la guía de render de storyboards para lo básico de v1; esta cubre lo que añade v2.

El proyecto

Una fila de film tiene title, cover_url, published_creation_id y un documento data. data es el proyecto entero: las rutas validan su tamaño (400 KB) y lo normalizan al leerlo, y por lo demás guardan lo que envías. La forma v2:

{
  "v": 2,
  "look": {
    "model": "seedance-2-0-mini",
    "aspect": "16:9",
    "resolution": "720p",
    "audio": true,
    "seed": 4242,
    "filmType": "noir", "era": "1960s", "tempo": "tense",
    "cameraType": "35mm film", "lens": "anamorphic", "aperture": "f/1.4",
    "palette": "neon noir", "lighting": "practicals",
    "chain": true,
    "negative": ""
  },
  "scenes": [
    {
      "id": "s1", "heading": "EXT. JAZZ CLUB — NIGHT",
      "prompt": "A detective in a rain-soaked trench coat waits under a flickering neon sign, slow push-in.",
      "shot": "push-in", "seconds": 5, "cast": ["char:9f3…"], "takes": 1,
      "dialogue": [{ "id": "l1", "speaker": "char:9f3…", "manner": "whispering", "line": "It's still lit." }],
      "options": [{ "libraryId": "cr_…", "contentType": "video/mp4", "seconds": 5 }],
      "pick": 0
    }
  ],
  "script": [
    { "id": "b1", "type": "h1", "html": "Rooftop night" },
    { "id": "b2", "type": "scene", "sceneId": "s1" },
    { "id": "b3", "type": "p", "html": "Rain machine on for this one." }
  ],
  "edit": { "auto": true, "clips": [], "audio": [], "titles": [], "fadeOut": 0 }
}

Las líneas de diálogo de una escena viven en la escena (dialogue: el hablante como char:<id> o un nombre libre, la manera y la línea); cualquier otro bloque del guion es una nota y nunca llega a un motor. Hay cuatro reglas que el normalizador aplica para que tú no tengas que hacerlo: cada escena tiene exactamente un bloque scene en el guion (los huérfanos se descartan y los que faltan se añaden al final), las escenas se ordenan según el guion, los bloques dialogue de un borrador antiguo se integran en la escena que tienen encima (uno escrito antes de cualquier escena se convierte en nota), y cada libraryId de options es un id de creación: los medios nunca se guardan en el proyecto, solo se referencian. Un borrador v1 (look + scenes con prompt/shot/seconds/cast/takes) se normaliza a esta forma al leerse, así que las integraciones antiguas siguen funcionando.

Límites: 24 escenas, 30 segundos por escena, 8 opciones por escena, 30 líneas de diálogo por escena, 400 bloques, 80 clips, 40 clips de audio, 40 títulos, 4,000 caracteres por prompt o bloque.

Crear, leer, actualizar

POST /v1/films
{ "title": "Rooftop night", "data": { … } }

GET /v1/films              → cards: scenes, rendered, seconds, aspect, cover, preview
GET /v1/films/{id}         → the row + data + media
PATCH /v1/films/{id}       → title and/or data (whole document)
DELETE /v1/films/{id}      → the draft; renders stay in the library

GET /v1/films/{id} devuelve un mapa media junto al proyecto: cada toma, clip y sonido al que apunta el proyecto, con clave creation:<id> o upload:<id>, una URL firmada nueva, el tipo de contenido, la duración y la miniatura. Tu almacenamiento es privado, así que las URL caducan; el mapa es la forma en que un cliente obtiene enlaces que funcionan sin tener una clave por archivo. Para refrescar un subconjunto (antes de que caduque una URL firmada, o cuando un archivo nuevo entra en la bandeja), POST /v1/films/media con { "keys": ["creation:…", "upload:…"] } (de 1 a 300) devuelve la misma forma para esas claves. Las claves desconocidas o ajenas simplemente no aparecen.

PATCH sustituye data entero. Lee, modifica, escribe: no hay fusión parcial, y una escritura obsoleta gana sobre una más reciente, así que serializa a quienes escriben.

Renderizar

POST /v1/films/{id}/render
{ "store": false }

Una sola llamada pone en cola cada escena que tiene prompt, como un job de video asíncrono por toma, en el motor de la estética: el mismo pipeline que POST /v1/videos/generations, con cada job cobrado por separado. La respuesta asocia cada id de escena con sus ids de job, o con el error que le impidió entrar en la cola; las escenas fallan de forma independiente, y un fallo cobrado se reembolsa solo. Consulta los jobs como cualquier render.

Lo que la ruta compone por escena, en v2: el encabezado de escena, su acción y sus líneas de dialogue (Mina (whispering) says: "…"), con las fichas de personaje y las voces de los hablantes sumándose a las referencias: el mismo prompt que envía el estudio. La estética acompaña a cada escena, incluidos audio y seed. Los límites del motor ajustan formato, resolución, duración y referencias antes de cobrar; una escena que pide una función que el motor no tiene se rechaza, no se reduce en silencio.

Cuando llega una toma, escríbela en las options de la escena con su libraryId y fija pick; el estudio lo hace por ti, y una integración lo hace después de consultar el job. Los planos continuos (look.chain) son un comportamiento del cliente: el estudio toma el último fotograma de la toma anterior, lo sube y lo pasa como primera referencia. En la API, envía tú mismo references[0] en un POST /v1/videos/generations por escena si quieres el encadenado; la ruta de render masivo renderiza las escenas tal como están escritas.

La edición y la exportación

El documento edit son datos puros: clips que referencian { "kind": "scene", "sceneId" }, creation o upload, con recortes de entrada y salida, transiciones, volumen y ajuste; clips de audio en tres pistas con fundidos; títulos en cuatro estilos; un fundido de salida. El estudio lo renderiza a un MP4 en el navegador; la API no renderiza ediciones en el servidor.

Lo que sí hace la API es guardar el resultado:

POST /v1/films/{id}/export?seconds=42.5&signature=<edit signature>
Content-Type: video/mp4

<raw MP4 bytes>

El cuerpo es el archivo, enviado en streaming. Llega a la biblioteca como una creación de video (así que se reproduce, se descarga y se publica como cualquier clip) y cuenta para el almacenamiento del espacio de trabajo como cualquier archivo de la biblioteca. Gratis. La signature es un hash de la edición en el momento de exportar; la película la registra, y un cambio posterior en la edición deja desactualizado el montaje guardado. Una nueva exportación reemplaza el montaje anterior cuando ese nunca se publicó y nada en la edición lo usa.

Comparte el límite de solicitudes con las subidas; un bucket lleno rechaza la solicitud antes de leer nada.

Publicar

POST /v1/films/{id}/cover        (multipart file, image ≤ 5 MB, free)
POST /v1/films/{id}/publish
{ "title": "Rooftop night", "segments": ["<the saved cut's URL>"], "durationSeconds": 42 }

Una película con un montaje guardado publica ese montaje como su único segmento; una película sin montaje publica sus tomas elegidas en orden. Cada segmento debe ser un video de tu biblioteca. La publicación pasa por revisión (review empieza en pending en GET /v1/films/{id}); DELETE /v1/films/{id}/publish la retira y conserva las interacciones.

Lo que la API no hace

  • Renderizar la edición. El compositor está en el estudio; la API guarda el resultado.
  • Capturar los últimos fotogramas. Encadena enviando references[0] por escena.
  • Servir URL de almacenamiento sin firmar. Todo va firmado, a través de GET /v1/films/{id} o POST /v1/films/media.

Preguntas frecuentes

¿Está documentado el formato del proyecto?

Las rutas tratan data como JSON opaco con un límite de tamaño y lo normalizan al leerlo. La forma de arriba es la que escribe el estudio; los campos son estables y lo que se añada será opcional.

¿La ruta de render cobra las escenas que ya tienen tomas?

Renderiza todas las escenas que tienen prompt, incluidas las que ya tienen tomas. Para volver a renderizar una sola escena, llama a POST /v1/videos/generations para esa escena y escribe el resultado en sus options.

¿Puedo subir mi propio material a una película?

Súbelo con POST /v1/uploads y referéncialo desde la edición como { "kind": "upload", "id": … }. El mapa de medios lo firma como cualquier toma.

¿Por qué store es una opción del render?

store: true guarda cada clip en tu almacenamiento con la tarifa del Store (2 créditos por 10 MB); la opción por defecto conserva la copia gratuita en la biblioteca. Las tomas de Cinema viven en la biblioteca en cualquier caso.

Lee la referencia de films para cada campo, y la guía de storyboards para el recorrido por v1.

Etiquetasfilms-apicinemaapivideostoryboard

Crea esto con los modelos detrás del artículo: empieza con 50 créditos gratis o explora todos los motores y sus precios.