Film documentation

What is Film

Film renders a Wisent video. One service owns the job: which renderer does it, what that renderer is asked for, who owns the identifier that comes back, and what "still rendering" means. Film records which renderer started a job and asks that renderer when somebody reads it, so what Film says is what the renderer says.

Renderers

Six renderers behind one surface: hedra (Character 3), kling, sora, veo (Veo 3.1 on KIE), wavespeed and wisent, the deployment's own pipeline. A deployment carries the ones whose keys it has (see configuration) and refuses the others by name.

Modes

  • text_to_video and image_to_video on kling, sora and veo.
  • On wavespeed the mode picks the model: scail (one still driven by driving_video_url), lipsync (InfiniteTalk: one portrait driven by audio_url) and image_to_video (Seedance 1.5 Pro: one still animated from prompt, duration 4 to 12 seconds).
  • hedra renders lipsync only and needs prompt, reference_image_url, audio_url, resolution and aspect_ratio.

A mode a renderer does not render is refused with the reason, never rendered as something else.

Every request must name pipeline; Film refuses an omitted renderer with HTTP 400 and the deployment's configured choices.

The service

POST /v1/videos                          start a render
GET  /v1/videos                         list last recorded job states
GET  /v1/videos/{job_id}[?wait=terminal] read one job back
POST /v1/callbacks/{pipeline}            a renderer saying a render ended
GET  /readyz                             configured renderers and remembered job count

/readyz reports configuration, not a renderer probe. Its ok response does not establish that provider credentials work, a renderer is reachable, or the public callback can arrive.

Every /v1/videos call carries the deployment's secret in x-film-secret. A read without wait answers what the renderer says now; with wait=terminal Film holds the read until the job is completed or failed. A callback only names the job: Film reads that job back from the renderer, and that read releases every held read.

A job is job_id, pipeline, status (processing, completed, failed or unknown), and, once known, url, error and completed_at.

A Rust caller uses film::client::FilmClient (start, list, status, settled) and never speaks to WaveSpeed, KIE or the pipeline itself; the CLI is that client on a shell.

Refusals the service answers

  • 400 pipeline is required; this deployment renders on <list>
  • 401 unauthorized when the caller secret is missing or not accepted.
  • 400 no renderer for pipeline `<pipeline>` on this deployment; it has <list>
  • 400 wait=`<value>` is not a read Film offers; use wait=terminal
  • 404 this deployment did not start job `<job id>`
  • 409 job `<job id>` was started on `<pipeline>`, which is no longer configured here
  • 410 job `<job id>` was dropped from this deployment's record while held
  • 422 a request Film refuses before contacting a renderer: missing required fields, unsupported modes or values the adapter cannot parse. The reason names the required input.
  • 502 a renderer submission failure, or a failed provider observation. The response retains the cause; a status-read failure does not establish a failed render.