# The film package

> One folder per film: the film, every image it was made from, and the record of how. The page is drawn from it; nothing on a film page is typed in by hand.

When a film is finished, `python3 -m castpad_mv publish` writes a package the site reads. It is files, like all artwork on Castpad, so a film can be added without touching the code or the ledger.

## Where it lives

```
public/media/films/<artist>/<film>/
  film.json            the facts (format castpad-film/1)
  film.mp4             the master
  film-vertical.mp4    the vertical cut
  loop.mp4             eight silent seconds for the top of the page
  poster.jpg, og.jpg   a still and a share image
  frames/01–24.jpg     frames from the cut, with their times
  record/*.md          the making-of documents
public/media/films/<artist>/_img/<film>/<batch>/
  <job>-<n>.s.webp     720 px
  <job>-<n>.m.webp     1800 px
  <job>-<n>.full.jpg   full size
```

## A series: stills with no film

The same package with `"kind": "series"` and no master: a casting, a photo shoot, an editorial. It has
a cover instead of a loop, no theater and no frames; everything else — every image, the batches, the
record — is the same. The renderer's `stills publish` writes one (see *Stills* below). Its rows are
Stills (prompts · images · picks), Looks, Sets, Framings and Made with (the model, whether her face was
a reference, the cost at list price, the choices made by hand). The page says "Series k of N"; a
"picked" image is the one chosen from its prompt, and the others from the same call are kept.

## The numbers

Five rows, each a list of facts read from what the renderer wrote while it worked:

| Row | Facts |
|---|---|
| Song | length · source · BPM · lines |
| Edit | shots · sections · sung lines on screen |
| Stills | prompts · images · plates |
| Motion | clips · takes · seconds · cost at list price |
| Made in | hours · the director's choices |

They are production facts — what was made — not audience numbers. Audience numbers only ever come from the ledger.

## Every image

Each image has an id `batch.job.n`: the batch it came from (casting, sheet, plates, a director's cut), the job (one prompt), and which of that prompt's results it is. It carries its prompt word for word, its size, framing, look and set, whether it is a **plate** (a first frame in the finished film), and the judge's or director's verdict. Images that were not picked are kept: they show what the pipeline chose between.

## The record

- **How it was made** — the spark, the stack, the steps, the numbers, what it cost, what failed.
- **Stills** — every image prompt, batch by batch.
- **Motion** — every moving shot: model, window, motion prompt and the measured lip sync.
- **Song** — source, tempo, sections and every line as timed.

## Stills: an artist made of pictures

`python3 -m castpad_mv stills` makes an artist from a canon (the one text every prompt repeats) with
three human choices: **the face** (from four, or one made by hand), **the picks** (a vision model picks
first; a person changes any), and **publish**. On the aliyun engine the chosen face is sent as a
reference image with every shot, and the full-figure reference with every full-length one. It prices
everything before it spends, stops at the canon's cap, and never pays for a job twice. Pictures made
by hand come in through `stills import`, so the two routes mix.

## For agents

Every film is also `/s/<artist>/films/<film>.md`, `/api/shows/<artist>/films/<film>` (JSON with every image) and, through the MCP server, `list_films`, `browse_images`, `search_images`, `get_image` and `get_record`.
