Instructions to use Viggle/Meridian with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use Viggle/Meridian with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("Viggle/Meridian", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
| # Local studio API | |
| [← Meridian](../README.md) · [Studio and deployment](studio.md) · [Method](method.md) | |
| The FastAPI service exposes the same preparation and rendering operations used by the studio. | |
| This is a development API for a trusted, single-GPU deployment—not an authenticated multi-user | |
| service. Requests are plain JSON except for multipart upload. All source indices refer to the | |
| **normalized 24 fps clip**, not the original upload's timestamps. | |
| ## Request flow | |
| ```text | |
| /upload or /sample → /prepare → /warp → inspect → /render → /job/{job} → /take/{job}/{name} | |
| ``` | |
| `/prepare` must populate the source-span cache before `/warp` or `/render`. Keep the same `clip`, | |
| `start`, and `span_end` across those calls. If that cache entry is evicted or the service restarts, | |
| prepare again. Do not change requests while assuming a previously inspected preview still applies. | |
| ## Shared fields | |
| | Field | Meaning | | |
| |---|---| | |
| | `clip` | ID returned by `/upload` or `/sample`. | | |
| | `start` | First source frame of the prepared span, inclusive. | | |
| | `span_end` | Last source frame of that span, inclusive. Must satisfy `0 <= start < span_end < clip.frames`. | | |
| | `frames` | Output length. Use one of `73, 90, 107, 124, 141, 158, 175, 243` for generation. | | |
| | `pivot` | Optional `[u, v]` in normalized source-image fractions; default `[0.5, 0.5]`. Sets the depth-scale neighborhood. | | |
| | `pivot_frame` | Source frame at which to measure pivot depth; set it explicitly, normally to `start`. | | |
| | `seed` | Generation seed, default `1234`. | | |
| | `path` | List of at least two camera keys. | | |
| The current API's per-endpoint validation is limited; unsupported output lengths may fail only when | |
| loading conditioning assets. Validate requests before submitting expensive GPU work. Choose a | |
| continuous source span: the browser avoids detected cuts, but the API does not enforce that policy. | |
| ### Camera keys | |
| | Field | Meaning | | |
| |---|---| | |
| | `pos` | `[x, y, z]` position in the coordinate frame of the source camera at `start`, in units of `zm`. | | |
| | `look` | Look-at point in the same frame and units. | | |
| | `src` | Absolute source-frame index, within the prepared span. | | |
| | `t` | Output-frame index. First key is `0`, last is `frames - 1`; intermediate values strictly increase. | | |
| | `ease` | Optional boolean, default `false`. Eases camera position/look-at motion in the segment leaving this key. | | |
| | `focal` | Optional positive focal multiplier, default `1`, relative to that source frame's estimated lens. | | |
| Axes are **x right, y down, z forward**. Source indices must be non-decreasing. Position and look-at | |
| points follow slope-limited cubic Hermite/Catmull-Rom interpolation; source indices and focal | |
| multipliers interpolate linearly. Source indices are rounded to integers. Orientation is derived | |
| from the look-at direction with zero roll. Equal adjacent `src` values create a hold. | |
| ## Minimal walkthrough | |
| Start the [service](studio.md#start-the-service), then upload a continuous clip containing at least | |
| 73 normalized frames: | |
| ```bash | |
| curl -sS -F 'file=@clip.mp4' http://127.0.0.1:8412/upload | |
| ``` | |
| Copy the response's `clip` value into the following JSON and save it as `take.json`. This example | |
| slides the camera right by `0.15 zm` while looking toward a point one depth unit ahead of the initial | |
| camera. For subject-specific framing, use the `piv` returned by `/prepare` as your look-at reference. | |
| ```json | |
| { | |
| "clip": "CLIP_ID_FROM_UPLOAD", | |
| "start": 0, | |
| "span_end": 72, | |
| "frames": 73, | |
| "pivot": [0.5, 0.5], | |
| "pivot_frame": 0, | |
| "seed": 1234, | |
| "path": [ | |
| {"pos": [0, 0, 0], "look": [0, 0, 1], "src": 0, "t": 0, "ease": true, "focal": 1}, | |
| {"pos": [0.15, 0, 0], "look": [0, 0, 1], "src": 72, "t": 72, "ease": false, "focal": 1} | |
| ] | |
| } | |
| ``` | |
| Prepare the geometry, then produce a preview. `/prepare` ignores the extra path fields: | |
| ```bash | |
| curl -sS -H 'Content-Type: application/json' --data-binary @take.json \ | |
| http://127.0.0.1:8412/prepare | |
| curl -sS -H 'Content-Type: application/json' --data-binary @take.json \ | |
| http://127.0.0.1:8412/warp | |
| ``` | |
| Open the returned `truth` and `holes` URLs relative to the service origin, and inspect `ahead`, | |
| `moved`, and `speed`. Generation is a separate, expensive step: | |
| ```bash | |
| curl -sS -H 'Content-Type: application/json' --data-binary @take.json \ | |
| http://127.0.0.1:8412/render | |
| ``` | |
| Copy the returned job ID into the commands below. Poll until `done` is true, and check that there is | |
| **no `error`** before downloading; failed jobs also set `done: true`. | |
| ```bash | |
| curl -sS http://127.0.0.1:8412/job/JOB_ID_FROM_RENDER | |
| curl -f -o out.mp4 http://127.0.0.1:8412/take/JOB_ID_FROM_RENDER/out.mp4 | |
| ``` | |
| `/render` does not enforce the browser's clearance or camera-change gates and does not require that | |
| `/warp` was called first. This walkthrough includes preview inspection intentionally. A returned job | |
| ID means the background task was started, not that input validation or generation succeeded. | |
| ## Endpoints | |
| Paths below are relative to the service origin. “Shared fields” refers to the table above; not every | |
| endpoint consumes every field. | |
| | Endpoint | Request | Response | | |
| |---|---|---| | |
| | `GET /` | — | Studio HTML. | | |
| | `GET /samples` | — | Array of available sample MP4 filenames. | | |
| | `POST /upload` | Multipart `file`. | `{clip, frames, w, h, name, cuts, seconds, lengths}`. | | |
| | `POST /sample` | `{name}` from `/samples`. | Same clip metadata as upload. | | |
| | `POST /prepare` | `clip, start, span_end`; optional `pivot, pivot_frame`. | `{box, canvas, cond_canvas, ms, src_poses, piv, zm}`. | | |
| | `POST /cloud` | Shared fields plus absolute source `frame`, optional `stride` (default `5`). | `{n, zm, pts, rgb}`; flattened triples in path coordinates. | | |
| | `POST /warp1` | Shared fields plus `src, pos, look`; optional `focal`. | One geometry-reference JPEG at conditioning resolution. | | |
| | `POST /warp` | Shared fields plus `path`; optional `lite`. | Gauges, cameras, source mapping, and preview URLs. `lite: true` omits the hole/sketch previews. | | |
| | `POST /render` | Shared fields plus `path`. | `{job}`; rendering continues in a background thread. | | |
| | `GET /job/{job}` | — | Status including `stage, pct, done, payload`; `t`, `error`, or `gauges` when available. | | |
| | `GET /frame/{clip}/{i}.jpg` | Source index in the URL. | JPEG of the normalized source frame. | | |
| | `GET /warpfile/{clip}/{name}` | Use a URL returned by `/warp`. | Preview file. | | |
| | `GET /take/{job}/{name}` | Completed job ID and filename. | `out.mp4`, `source.mp4`, `render.mp4`, `grid.mp4`, or `last.png`. | | |
| `lengths` in upload metadata is the studio's four-option length menu, not an exhaustive list of | |
| asset-supported lengths. `src_poses[i]` in `/prepare` corresponds to absolute source frame | |
| `start + i`; each entry includes `pos`, `look`, `roll`, and normalized lens values `k`. | |
| Job `t` is elapsed time **since submission, including queue wait**. It first appears when processing | |
| starts and updates at stage transitions, not continuously on polling. It is not a pure render-time | |
| measurement. | |
| ### Warp response | |
| - **`truth`**: grey-hole reference MP4 at conditioning resolution. | |
| - **`holes`**: magenta-hole diagnostic MP4, unless `lite` is true. | |
| - **`sketch`**: output-resolution geometric rasterization, unless `lite` is true; not the final | |
| conditioning-resolution reference. | |
| - **`canvas`, `cond_canvas`**: `[width, height]` for the target and references. | |
| - **`tmap`**: selected source index for every output frame. | |
| - **`cams`**: per-output-frame position/look-at description; `piv` and `zm` describe the pivot/scale. | |
| - **`speed`**: source-frame rate per key segment; zero is a hold, one preserves the input pace. | |
| - **`coverage`**: mean geometric coverage at the rasterization resolution, not a calibrated quality score. | |
| - **`ahead`, `near`, `behind`, `coll`, `moved`**: geometric diagnostics. See [Preview checks](studio.md#preview-checks). | |
| - **`ms`**: elapsed time for the warp endpoint, including preview encoding. | |
| `turned` and `zoomed` are computed by the browser from keys; they are not fields returned by `/warp`. | |
| ## Operational boundaries | |
| One process serializes GPU work through a lock. The API has no cancellation, durable queue, session | |
| restoration, authentication, or automatic file retention policy. Clip and geometry caches can evict | |
| entries while files remain on disk. Do not assume an old ID remains usable after a restart or eviction. | |
| Assertions and runtime failures may surface as HTTP errors rather than structured validation | |
| responses. Render failures can arrive asynchronously through `/job/{job}`. The automatically served | |
| FastAPI schema does not describe these JSON payloads fully because the handlers read request bodies | |
| directly; use this guide alongside [`service/app.py`](../service/app.py). | |
| For service flags, cache behavior, and deployment precautions, see [Studio](studio.md#memory-and-lifecycle). | |