Rabatt auf Premium-Pläne, wenn du dich registrierstRabatt sichern
eroq

Blog/developers·24. Sept. 2026·6 Min.·vom eroq-Team

Films-API: Cinema-Projekte von Drehbuch und Storyboard bis Export

Cinema mit Drehbuch per API: v2-Projekte auf /v1/films, wie der Render das Drehbuch liest, neu signierte Medien, Export und Veröffentlichung des Schnitts.


Alles, was der Cinema-Workspace tut, läuft über /v1/films, und das Studio ist ein Client davon wie jeder andere. Dieser Leitfaden richtet sich an Entwickler, die Filme bauen oder automatisieren wollen: das Projektformat, das die Routen als opak behandeln, der Render-Aufruf, der das Drehbuch liest, die Media-Map, die Export-Route und die Obergrenzen. Er setzt voraus, dass du den Leitfaden zum Rendern von Storyboards mit den v1-Grundlagen gelesen hast; hier geht es darum, was v2 hinzufügt.

Das Projekt

Ein Film-Datensatz hat einen title, eine cover_url, eine published_creation_id und ein data-Dokument. data ist das gesamte Projekt: Die Routen prüfen seine Größe (400 KB), normalisieren es beim Lesen und speichern ansonsten, was du schickst. Die v2-Form:

{
  "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",
    "negative": ""
  },
  "notes": "Rooftop night. Rain machine on.",
  "sequences": [
    { "id": "q1", "heading": "EXT. JAZZ CLUB — NIGHT", "cast": ["char:9f3…"], "look": { "lighting": "practicals" } }
  ],
  "scenes": [
    {
      "id": "s1", "sequence": "q1", "heading": "",
      "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": "scene", "sceneId": "s1" }
  ],
  "edit": { "auto": true, "clips": [], "audio": [], "titles": [], "fadeOut": 0 }
}

Seit dem 13. Oktober zeigt das Studio das als Story: Jeder Eintrag in scenes ist eine Einstellung, und sequences sind die Szenen der Story (ein Ort und eine Zeit in heading, ein cast und ein optionaler look, der Licht, Farbpalette, Objektiv, Blende, Kamera oder Tempo des Films überschreibt), wobei jede Einstellung mit sequence auf ihre eigene zeigt. Die Dialogzeilen einer Einstellung liegen in der Einstellung selbst (dialogue: Sprecher als char:<id> oder freier Name, Sprechweise, Zeile); notes am Film, an einer Szene oder an einer Einstellung erreichen nie eine Engine, und der link einer Einstellung (continue oder angle) sagt, wie sie auf die vorherige folgt. Vier Regeln setzt der Normalizer durch, damit du es nicht tun musst: script behält einen scene-Block pro Einstellung und legt deren Reihenfolge fest (alte Textblöcke im Notion-Stil werden in notes eingefaltet), das alte heading einer Einstellung wandert zu ihrer Szene, ein altes look.chain wird zu Verknüpfungen und geleert, und jede libraryId in options ist eine Creation-ID – Medien werden nie im Projekt gespeichert, sondern nur referenziert. Ein v1-Entwurf (look + scenes mit prompt/shot/seconds/cast/takes) wird beim Lesen in diese Form normalisiert, damit alte Integrationen weiter funktionieren.

Obergrenzen: 24 Einstellungen, 30 Sekunden pro Einstellung, 8 Optionen pro Einstellung, 30 Dialogzeilen pro Einstellung, 80 Clips, 40 Audioclips, 120 Titel, 4.000 Zeichen pro Prompt oder Notiz.

Erstellen, lesen, aktualisieren

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} liefert neben dem Projekt eine media-Map: jeden Take, jeden Clip und jeden Sound, auf den das Projekt verweist, mit dem Schlüssel creation:<id> oder upload:<id>, jeweils mit frisch signierter URL, Content-Type, Länge und Thumbnail. Dein Speicher ist privat, deshalb laufen URLs ab; über die Map bekommt ein Client funktionierende Links, ohne für jede Datei einen eigenen Schlüssel zu besitzen. Um einen Teil davon zu erneuern – bevor eine signierte URL abläuft oder wenn eine neue Datei in die Ablage kommt –, liefert POST /v1/films/media mit { "keys": ["creation:…", "upload:…"] } (1 bis 300) dieselbe Form für diese Schlüssel. Unbekannte oder fremde Schlüssel fehlen einfach.

PATCH ersetzt data vollständig. Lesen, ändern, schreiben; es gibt kein partielles Mergen, und ein veralteter Schreibvorgang überschreibt einen neueren, also serialisiere deine Schreibzugriffe.

Rendern

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

Ein einziger Aufruf stellt jede Szene mit Prompt in die Warteschlange, als einen asynchronen Video-Job pro Take, auf der Engine des Looks – dieselbe Pipeline wie POST /v1/videos/generations, jeder Job einzeln abgerechnet. Die Antwort ordnet jeder Szenen-ID ihre Job-IDs zu oder den Fehler, der das Einreihen verhindert hat; Szenen schlagen unabhängig voneinander fehl, und ein abgerechneter Fehlschlag wird automatisch erstattet. Poll die Jobs wie jeden anderen Render.

Was die Route in v2 pro Einstellung zusammensetzt: Überschrift und Besetzung ihrer Szene, die Handlung und die dialogue-Zeilen (Mina (whispering) says: "…"), wobei die Charakterbögen und Stimmen der Sprecher zu den Referenzen hinzukommen – derselbe Prompt, den auch das Studio sendet. Der Look gilt für jede Szene, einschließlich audio und seed. Die Grenzen der Engine beschneiden Format, Auflösung, Länge und Referenzen vor der Abrechnung; eine Szene, die eine Funktion verlangt, die der Engine fehlt, wird abgelehnt und nicht stillschweigend reduziert.

Wenn ein Take fertig ist, schreib ihn mit seiner libraryId in die options der Einstellung und setz pick; das Studio erledigt das für dich, eine Integration tut es nach dem Polling. Verknüpfungen zwischen Einstellungen (link) sind ein Verhalten des Clients: Bei Einstellung fortsetzen greift das Studio das letzte Frame des vorherigen Takes ab, lädt es hoch und übergibt es als Startframe; bei Gleiche Szene, neuer Winkel übergibt es das Frame als Referenz. Über die API schickst du references[0] selbst mit einem POST /v1/videos/generations pro Einstellung, wenn du die Verkettung willst; die Sammel-Render-Route rendert die Einstellungen so, wie sie geschrieben sind.

Schnitt und Export

Das edit-Dokument besteht nur aus Daten: Clips, die auf { "kind": "scene", "sceneId" }, creation oder upload verweisen, mit In-/Out-Trims, Übergängen, Lautstärke und Einpassung; Audioclips auf bis zu acht Spuren mit Blenden; Titel in zwölf Stilen; eine Abblende am Ende. Das Studio rendert es im Browser zu einer MP4; die API rendert Schnitte nicht serverseitig.

Die API bewahrt dafür das Ergebnis auf:

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

<raw MP4 bytes>

Der Body ist die Datei selbst, gestreamt. Sie landet als Video-Creation in der Bibliothek – lässt sich also wie jeder Clip abspielen, herunterladen und veröffentlichen – und zählt wie jede Bibliotheksdatei zum Speicher des Workspace. Kostenlos. Die signature ist ein Hash des Schnitts zum Zeitpunkt des Exports; der Film speichert ihn, und eine spätere Änderung am Schnitt macht die gespeicherte Fassung veraltet. Ein erneuter Export ersetzt die vorherige Fassung, wenn diese nie veröffentlicht wurde und nichts im Schnitt sie verwendet.

Das Rate Limit teilt sich die Route mit den Uploads; ein voller Bucket lehnt ab, bevor überhaupt etwas gelesen wird.

Veröffentlichen

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 }

Ein Film mit gespeicherter Fassung veröffentlicht diese als einziges Segment; ein Film ohne Fassung veröffentlicht seine ausgewählten Takes der Reihe nach. Jedes Segment muss ein Video in deiner Bibliothek sein. Veröffentlichungen durchlaufen eine Prüfung (review beginnt bei pending auf GET /v1/films/{id}); DELETE /v1/films/{id}/publish nimmt den Film wieder offline und behält das Engagement.

Was die API nicht macht

  • Den Schnitt rendern. Der Compositor steckt im Studio; die API speichert das Ergebnis.
  • Letzte Frames abgreifen. Verkette, indem du references[0] pro Szene mitschickst.
  • Rohe Speicher-URLs ausliefern. Alles ist signiert, über GET /v1/films/{id} oder POST /v1/films/media.

Häufige Fragen

Ist das Projektformat dokumentiert?

Die Routen behandeln data als opakes JSON mit Größenlimit und normalisieren es beim Lesen. Die Form oben ist das, was das Studio schreibt; die Felder sind stabil, Ergänzungen sind optional.

Berechnet die Render-Route auch Szenen, die schon Takes haben?

Sie rendert jede Szene mit Prompt, auch solche mit Takes. Um eine einzelne Szene neu zu rendern, ruf POST /v1/videos/generations für diese Szene auf und schreib das Ergebnis in ihre options.

Kann ich eigenes Material in einen Film hochladen?

Lad es mit POST /v1/uploads hoch und verweise im Schnitt darauf als { "kind": "upload", "id": … }. Die Media-Map signiert es wie jeden Take.

Warum ist store eine Option beim Rendern?

store: true speichert jeden Clip zum Tarif des Store (2 Credits pro 10 MB) dauerhaft in deinem Speicher; standardmäßig bleibt es bei der kostenlosen Kopie in der Bibliothek. Die Takes von Cinema liegen so oder so in der Bibliothek.

Alle Felder findest du in der Films-Referenz, den Durchgang für v1 im Storyboard-Leitfaden.

Tagsfilms-apicinemaapivideostoryboard

In eroq machen

Baue es auf der API

Ein API-Schlüssel ist in einer Minute da. Dieselben Engines, dieselben Preise, asynchrone Jobs und Webhooks.

40 Gratis-Credits · keine Kreditkarte · Privatmodus für jedes Konto