Skip to content

Video

Clips of 2 to 10 seconds with a generated soundtrack, from a prompt or a first frame, on ltx-2.3.

Access: Keys with the media:read or media:generate scope, on an account with media access granted by Albastar Corp.

A video job makes one clip of 2 to 10 seconds with a generated soundtrack on ltx-2.3, from a prompt or from an image and a prompt, with POST /v1/media/jobs and kind video.

Make a video

POST /v1/media/jobs with kind video, model ltx-2.3 and params.prompt queues one video. The prompt describes the action over time and the sounds. The example asks for 5 seconds at 720p with ?wait=85, then reads the job with GET /v1/media/jobs/{id}?wait=85 until the job settles.

curl

JOB=$(curl -s "https://api.albastov.com/v1/media/jobs?wait=85" \
  -H "Authorization: Bearer $ALBASTAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "kind": "video",
  "model": "ltx-2.3",
  "params": {
    "prompt": "rain on a harbour at night, neon reflections, distant thunder",
    "duration_s": 5,
    "resolution": "720p",
    "seed": 13
  }
}' | python3 -c 'import json, sys; print(json.load(sys.stdin)["id"])')

until curl -s "https://api.albastov.com/v1/media/jobs/$JOB?wait=85" \
  -H "Authorization: Bearer $ALBASTAR_API_KEY" -o job.json \
  -w '%{http_code}' | grep -q 200; do :; done
cat job.json

Python

import json
import os
import urllib.request

BASE = "https://api.albastov.com/v1"
HEADERS = {
    "User-Agent": "my-app/1.0",
    "Authorization": f"Bearer {os.environ['ALBASTAR_API_KEY']}",
    "Content-Type": "application/json",
}


def call(path, body=None):
    data = json.dumps(body).encode() if body is not None else None
    req = urllib.request.Request(BASE + path, data=data, headers=HEADERS)
    with urllib.request.urlopen(req, timeout=120) as res:
        return json.load(res)


job = call("/media/jobs?wait=85", {
    "kind": "video",
    "model": "ltx-2.3",
    "params": {
        "prompt": "rain on a harbour at night, neon reflections, "
                  "distant thunder",
        "duration_s": 5,
        "resolution": "720p",
        "seed": 13,
    },
})
while job["state"] in ("queued", "waiting_device", "running"):
    job = call(f"/media/jobs/{job['id']}?wait=85")
print(job["state"], [r["url"] for r in job["results"]])

JavaScript

const base = "https://api.albastov.com/v1";
const headers = {
  Authorization: `Bearer ${process.env.ALBASTAR_API_KEY}`,
  "Content-Type": "application/json",
};

async function call(path, body) {
  const res = await fetch(base + path, {
    method: body ? "POST" : "GET",
    headers,
    body: body ? JSON.stringify(body) : undefined,
  });
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
  return res.json();
}

let job = await call("/media/jobs?wait=85", {
  kind: "video",
  model: "ltx-2.3",
  params: {
    prompt: "rain on a harbour at night, neon reflections, distant thunder",
    duration_s: 5,
    resolution: "720p",
    seed: 13,
  },
});
while (["queued", "waiting_device", "running"].includes(job.state)) {
  job = await call(`/media/jobs/${job.id}?wait=85`);
}
console.log(job.state, job.results.map((r) => r.url));

The response is the settled job, with one MP4 result of 5.042 seconds at 1280 by 720 pixels:

JSON
{
  "id": "mj_BHxQnx8Q688dnTPB8qTGDV",
  "kind": "video",
  "model": "ltx-2.3",
  "state": "done",
  "waiting": null,
  "position": null,
  "priority": "batch",
  "params": {
    "aspect": "16:9",
    "audio": true,
    "cfg": 1,
    "duration_s": 5,
    "fps": 24,
    "negative_prompt": "pc game, console game, video game, …",
    "prompt": "rain on a harbour at night, neon reflections, distant thunder",
    "resolution": "720p",
    "seed": 13
  },
  "results": [
    {
      "index": 0,
      "url": "…/v1/media/files/mj_BHxQnx8Q688dnTPB8qTGDV/0.mp4",
      "content_type": "video/mp4",
      "bytes": 1474233,
      "width": 1280,
      "height": 720,
      "seed": 13,
      "duration_s": 5.042,
      "fps": 24,
      "audio": true,
      "thumb_url": null,
      "poster_url": null,
      "preview_url": null
    }
  ],
  "error": null,
  "created_at": "2026-10-21T23:48:13.671Z",
  "started_at": "2026-10-21T23:49:03.785Z",
  "finished_at": "2026-10-21T23:51:33.702Z",
  "queue_timeout_s": null
}

The response above shortens url to its path and the default negative_prompt with …, and leaves out label and fields beyond the job object table.

GET /v1/media/models?kind=video returns the parameters of ltx-2.3 with their ranges and defaults:

Shell
curl "https://api.albastov.com/v1/media/models?kind=video" \
  -H "Authorization: Bearer $ALBASTAR_API_KEY"
paramsTypeValues
prompt requiredstringThe action over time and the sounds; 4,000 characters at most
duration_snumber2 to 10 seconds in steps of 0.5; default 5
aspectstring16:9 (default), 9:16, 1:1 or 4:5
resolutionstring720p (default) or 1080p
fpsinteger24 (default), 25 or 30
seedinteger0 to 9007199254740991; without seed, a random seed, returned in params and on the result
cfgnumber1 to 5 in steps of 0.1; default 1
audiobooleantrue (default) keeps the generated soundtrack; false returns a video without sound
negative_promptstringWhat the video leaves out, 2,000 characters at most; default pc game, console game, video game, cartoon, childish, ugly, text, watermark
first_framestringAn image the video starts from: an upload up_…, a job result job:<id>/<i> or an https:// URL
first_frame_strengthnumber0.1 to 1 in steps of 0.05, default 0.7: how strongly first_frame holds the start of the video; with first_frame only

Start from an image

first_frame names the image the video starts from: an upload up_…, a result of an earlier job of the account as job:<id>/<i>, or an https:// URL. With first_frame, the job runs image to video. The size of the video follows aspect and resolution, not the size of the image. first_frame_strength without first_frame fails with 400 bad-param.

The example starts a 4:5 video from the first image of an earlier image job.

curl

curl "https://api.albastov.com/v1/media/jobs?wait=85" \
  -H "Authorization: Bearer $ALBASTAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "kind": "video",
  "model": "ltx-2.3",
  "params": {
    "prompt": "a timelapse of the canyon lake rising",
    "first_frame": "job:mj_bLuDshhr9LrHsJMFBgWesW/0",
    "aspect": "4:5",
    "seed": 4017539827
  }
}'

The settled job's results, from an image of 832 by 1248 pixels, with a poster and a preview:

JSON
[
  {
    "index": 0,
    "url": "…/v1/media/files/mj_9NmNoASRC2iLJcdZDuAsGV/0.mp4",
    "content_type": "video/mp4",
    "bytes": 854952,
    "width": 720,
    "height": 900,
    "seed": 4017539827,
    "duration_s": 5.042,
    "fps": 24,
    "audio": true,
    "thumb_url": null,
    "poster_url": "…/v1/media/files/mj_9NmNoASRC2iLJcdZDuAsGV/0.poster.webp",
    "preview_url": "…/v1/media/files/mj_9NmNoASRC2iLJcdZDuAsGV/0.preview.mp4"
  }
]

The response above shortens each URL to its path; every URL starts with https://api.albastov.com.

Result

A done video job has one result, index 0:

FieldValue
urlThe MP4 file: H.264 video, with an AAC soundtrack when audio is true
content_typevideo/mp4
bytesThe size of the MP4 file
width, heightThe size in pixels, from aspect and resolution: 1280 by 720 at 16:9 and 720p, 720 by 900 at 4:5 and 720p
duration_sThe length in seconds, such as 5.042 for duration_s 5
fpsFrames per second
audiotrue when the file carries the soundtrack
seedThe seed the video ran with
poster_urlA WebP still at the size of the video; null when the job has none
preview_urlA 3-second MP4 at 480 pixels tall, without sound; null when the job has none

url, poster_url and preview_url fetch the file without a key. thumb_url is null on a video.

Waits and limits

Typical time
GET /v1/media/models?kind=video reports typical_s 300 for ltx-2.3: a video takes about 5 minutes once the job starts, plus the time the job waits in the queue.
Waiting
?wait holds a request 85 s at most from its arrival, so a video job outlasts one hold. Read the job again with GET /v1/media/jobs/{id}?wait=85 until state is done, failed, cancelled or expired.
Queue
A video job without priority runs as batch and waits in the queue as long as it takes; queue_timeout_s is null.
One video per job
ltx-2.3 takes no count. Each video is 2 to 10 seconds; a duration_s outside the range fails with 400 bad-param and param duration_s.
Processing time
A member account has 600 s of media processing time a UTC day by default. Queuing a video sets aside 300 s, and the done job counts the time the video took. Past the limit, POST /v1/media/jobs fails with 429 budget-exhausted.

Reference

Media jobs reference

The job object, the parameters of a video job, ?wait, the job list by kind and the model list.

Uploads reference

A PNG, JPEG or WebP image stored as up_…, to start a video from.

Image & video

Image jobs, image to image and the GenAI app.

Rate limits

The daily processing time of a member account.

Video · Albastar API docs