---
title: Live video
description: An endless video that keeps going while you watch — POST /v1/videos/live streams ~5 s chunks, each carrying on from the one before, and you change what happens next at any moment. Events, steering, pricing and limits.
---

`POST /v1/videos/live` starts a live video: a stream of server-sent events that delivers a new ~5 s mp4 chunk every few seconds. Each chunk carries on from the last second of the one before — the motion included, not just a still — so played back to back they make one continuous shot — and it follows whatever prompt is current, which you can change while it runs. Give it a first frame to start from, and a **director** — a chat model that writes every next shot and takes your directions while it plays. Try it without code in the [playground](/app/playground?mode=live), where an image model can also draw the first frame.

## Models {#models}

| Model | Price | What it makes |
| --- | --- | --- |
| `ltx-live` | $0.019 per second of video made, at least $0.42 per session | LTX-2.5, 704×384 landscape or 384×704 portrait, 24 fps, with sound. Renders faster than real time: a 5 s chunk takes about 3 s. Keeps the people and the place of the first frame for the whole stream. |

It runs on our own GPUs in the `creative-hosted` [channel group](/docs/models/channel-groups) and is under the [LTX terms](/docs/models/ltx-license): every request sets `consent: true`, accepting them and the responsibility for following them.

## Start a stream {#start}

```bash title="cURL"
curl -N https://lovelyrouter.com/v1/videos/live \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -H "content-type: application/json" \
  -d '{"model": "ltx-live", "prompt": "A fox trots through fresh snow at dusk, the camera tracking beside it", "seconds": 120, "consent": true}'
```

```python title="Python"
import json
import os
import requests

H = {"Authorization": f"Bearer {os.environ['LOVELY_API_KEY']}"}
body = {
    "model": "ltx-live",
    "prompt": "A fox trots through fresh snow at dusk, the camera tracking beside it",
    "seconds": 120,
    "consent": True,
}

with requests.post("https://lovelyrouter.com/v1/videos/live", headers=H, json=body, stream=True) as r:
    event = None
    for line in r.iter_lines(decode_unicode=True):
        if line.startswith("event: "):
            event = line[7:]
        elif line.startswith("data: "):
            data = json.loads(line[6:])
            if event == "chunk":
                print(data["index"], data["url"])  # play these one after another
            elif event == "end":
                print("ended:", data["reason"], data["seconds"], "s", "$", data["charge_usd"])
```

:::params Body (JSON, or multipart with `image` as a file)
- `model` string, required
  `ltx-live`.
- `prompt` string, required
  What is on screen and what happens: subject, action, place, light, camera. Up to 1,000 characters; short prompts render fastest.
- `seconds` number, default `60`
  The most video to make, 5–600. The stream ends there, or earlier when you stop it or close the connection.
- `size` string, default `704x384`
  `704x384` (landscape) or `384x704` (portrait).
- `image` file or string
  The first frame to start from: a file, an `http(s)` URL or a `data:` URL. PNG, JPEG or WebP, up to 15 MB; cropped to `size` from the center. Make one with any [image model](/docs/models/images) and pass its file. It also stays the stream's reference: faces, clothes and the room are kept as they are in it, however long it runs (without one, the first chunk is).
- `director` string or object
  A chat model that writes every next chunk's prompt: its id, or `{"model": "…", "instructions": "…"}` with notes on style and story (up to 2,000 characters). See [The director](#director).
- `voice` file or string
  The speaker's voice: an audio clip (WAV, MP3, M4A, Ogg, FLAC or WebM, up to 15 MB) as a file, an `http(s)` URL or a `data:` URL. Its first ~5 seconds of speech are used; every chunk speaks in it. See [Voice](#voice).
- `keep_voice` boolean, default `true`
  Without `voice`: the voice heard in the first chunk with speech is kept for every later chunk. `false`: each chunk makes its own.
- `camera` string, default `free`
  `fixed` for one locked-off shot: the camera never moves or cuts and the place stays the same. See [Fixed camera](#fixed-camera).
- `seed` integer
  Repeatable chunks: chunk *n* uses `seed + n`.
- `consent` boolean, required
  `true`: you accept the [LTX terms](/docs/models/ltx-license).
:::

## Events {#events}

| Event | When | Data |
| --- | --- | --- |
| `session` | first | the [session object](#session), plus `seconds_per_chunk`, `price_per_second` and `price_min` (the least a session pays) |
| `status` | every ~10 s while a GPU starts (`state: "starting"`), the director writes (`"directing"`) or a chunk takes long (`"rendering"`); once if the director fails (`"director_error"`, the video keeps the last prompt) | `state`, `chunk`, `waiting_s`, `error` |
| `next` | when the director has written a coming chunk's prompt | `index`, `prompt`, `by` |
| `chunk` | one per ~5 s of video | `index`, `url` (the mp4), `prompt` (what it followed), `by` (`director` or `you`), `seconds`, `total_seconds`, `render_s`, `charge_usd` (so far) |
| `end` | last | `reason` (`max_seconds`, `stopped`, `client_left`, `insufficient_quota`, `error`), `error`, `seconds`, `charge_usd` |

The first chunk takes longer when no GPU is warm: up to about a minute while one starts, with `status` events meanwhile. After that, chunks arrive a little faster than they play. Buffer two before you start playback and play each one as the previous ends — two `<video>` elements, swapping, play it gaplessly.

Chunk URLs need no API key (each has its own unguessable path) and are kept for 7 days.

## The director {#director}

With `director`, a chat model writes the prompt of every chunk: while one chunk renders, it writes the next as if told "continue": from your `prompt` (the story), the video so far (up to its last 15 shots, your directions where you gave them) and anything you said since — keeping the same people, place and look, and moving the action on a little each shot. Each prompt says what is on screen, what happens, what the camera does and what we hear — the model makes the sound too. Spoken lines go in quotes with who says them, about 10 words per chunk (that is what ~5 s holds); a longer speech carries on over the next chunks from where the last line stopped. Its calls go through your key like any [chat call](/docs/models/openai): billed at that model's price and listed in your [logs](/app/logs). A fast, cheap model is plenty. It writes two shots per call and has about 10 seconds (two chunks) for each call, or the video pauses until it is done — `claude-haiku-5.5` takes about 6 s. It writes a few chunks ahead: while a finished chunk waits to play, the next call waits until that chunk starts, and a new direction has the shots not filmed yet written again at once — so your directions show within seconds.

```bash title="cURL"
curl -N https://lovelyrouter.com/v1/videos/live \
  -H "Authorization: Bearer $LOVELY_API_KEY" -H "content-type: application/json" \
  -d '{"model": "ltx-live", "prompt": "A woman walks home through a rainy city at night", "seconds": 300,
       "director": {"model": "claude-haiku-5.5", "instructions": "Slow, moody, film noir"}, "consent": true}'
```

Tell it what should happen while it plays:

```bash title="cURL"
curl https://lovelyrouter.com/v1/videos/live/LIVE_ID/direct \
  -H "Authorization: Bearer $LOVELY_API_KEY" -H "content-type: application/json" \
  -d '{"message": "A stray dog starts following her"}'
```

A direction is worked into the next prompt it writes. After that it stays in the video so far where you gave it, so what it changes keeps applying (a new place, mood or language) and an event happens once. A direction that arrives after a prompt was written gets that prompt rewritten before its chunk starts. A session takes up to 100 directions; they are listed in the [session object](#session).

## Fixed camera {#fixed-camera}

With `"camera": "fixed"` the whole stream is one locked-off shot — for a person talking to the camera, a room, a window. The director is told the camera never moves or cuts and the place never changes, whatever the story or your directions say, and only the people move. Every prompt sent to the model ends with "Static camera, locked-off shot." unless it already says so — the director's and your own (`POST …/prompt`). The `chunk` events report the prompt as sent.

A long fixed shot would slowly lose its background: every chunk starts where the one before ended, so small losses add up. With a fixed camera, the room each chunk starts from is cleaned — the person and anything that changed are kept, the rest comes from a clean copy of the room taken at the start. The video itself is not touched, so the room keeps its own small movements. If the framing changes, the clean copy is taken again.

## Voice {#voice}

Each chunk makes its own sound, so a person talking would get a new voice every few seconds. By default the voice heard in the first chunk with speech is kept: every later chunk is given that clip as the speaker's voice. Send `voice` to choose it yourself — about 5 seconds of clear speech, one speaker. `"keep_voice": false` turns this off.

## Change what happens next {#steer}

```bash title="cURL"
curl https://lovelyrouter.com/v1/videos/live/LIVE_ID/prompt \
  -H "Authorization: Bearer $LOVELY_API_KEY" -H "content-type: application/json" \
  -d '{"prompt": "It starts to snow harder; the fox stops and looks up"}'
```

The next chunk to start follows the new prompt word for word (the one rendering now keeps its own); with a director, it then continues from there. `LIVE_ID` is the `id` from the `session` event or the `x-lovely-request-id` header.

`POST /v1/videos/live/LIVE_ID/stop` ends the session after the chunk in progress. Closing the connection ends it too.

## The session {#session}

`GET /v1/videos/live/LIVE_ID` returns the session object: `id`, `object: "video.live"`, `model`, `status` (`live`, `stopping`, `ended`), `prompt`, `size`, `seconds` (made so far), `max_seconds`, `chunks` (every chunk URL so far), `camera`, `voice` (`keep`, `upload` or `off`), `director`, `directions`, `end_reason`, `error`, `charge_usd` (once ended).

## Pricing {#pricing}

You pay per second of video made, at least a minimum per session ($0.42 for `ltx-live`, about 22 seconds of video: starting a GPU and keeping it ready costs us that much). The director's calls are billed separately, as chat calls. When the session starts, the most it can cost is held from your balance — `seconds` × the price (at least the minimum), or less when your balance is lower, in which case the stream ends with `insufficient_quota` when the held amount is used. The hold is released when the session ends and the seconds made are billed as one call in your [logs](/app/logs). A session that ends on our error pays only for the video it made, without the minimum.

## Limits {#limits}

- One open session per account. A second one is refused with `429` until the first ends.
- A small number of GPUs serve each model; when all are streaming, a new session gets `503` with `retry-after`.
- Sessions run up to 600 s. Start another to keep going — pass the last chunk's final frame as `image` to continue the same shot.
