Try LTX 2.3 Extend in the Workbench
Run this model interactively, tune parameters, and compare outputs.
ltx-2-3-extend
LTX 2.3 Extend continues an existing clip, adding 2 to 20 seconds of new footage at its start or end, served directly by Lightricks’ LTX API on the Pro tier. The prompt describes what happens in the added portion, and audio is generated for it when the input video has audio.
The input video keeps its resolution and supports 16:9 and 9:16 clips up to 4K; the extension plus the context it draws on is capped at about 21 seconds at 24 FPS.
Example request
Use the Workbench as a request builder: configure parameters for this model in the UI, then open the API tab to copy the exact cURL or Python call.
- Sync
- Async
- Async with SSE
This blocks until the video is ready (typically 5-15 minutes). Prefer Async or Async with SSE for anything beyond quick experimentation.See the video generation reference for more details.
- Minimal
- All parameters
curl -X POST https://hub.oxen.ai/api/ai/videos/generate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4"
}'
import os
import requests
response = requests.post(
"https://hub.oxen.ai/api/ai/videos/generate",
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['OXEN_API_KEY']}",
},
json={
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4"
},
)
response.raise_for_status()
print(response.json())
curl -X POST https://hub.oxen.ai/api/ai/videos/generate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4",
"duration": 6,
"extend_mode": "end"
}'
import os
import requests
response = requests.post(
"https://hub.oxen.ai/api/ai/videos/generate",
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['OXEN_API_KEY']}",
},
json={
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4",
"duration": 6,
"extend_mode": "end"
},
)
response.raise_for_status()
print(response.json())
See the async queue reference for more details.
- Minimal
- All parameters
# Enqueue, capture the generation id.
GEN_ID=$(curl -s -X POST https://hub.oxen.ai/api/ai/queue \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4"
}' | jq -r '.generations[0].generation_id')
# Poll until the generation reaches a terminal status.
while true; do
STATUS=$(curl -s -H "Authorization: Bearer $OXEN_API_KEY" \
"https://hub.oxen.ai/api/ai/queue/$GEN_ID" | jq -r '.status')
echo "Status: $STATUS"
case $STATUS in succeeded|failed|cancelled) break;; esac
sleep 5
done
# Print the result.
curl -s -H "Authorization: Bearer $OXEN_API_KEY" \
"https://hub.oxen.ai/api/ai/queue/$GEN_ID" | jq .
import os
import time
import requests
HEADERS = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['OXEN_API_KEY']}",
}
enqueue = requests.post(
"https://hub.oxen.ai/api/ai/queue",
headers=HEADERS,
json={
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4"
},
)
enqueue.raise_for_status()
generation_id = enqueue.json()["generations"][0]["generation_id"]
while True:
data = requests.get(
f"https://hub.oxen.ai/api/ai/queue/{generation_id}",
headers=HEADERS,
).json()
if data["status"] in {"succeeded", "failed", "cancelled"}:
break
time.sleep(5)
if data["status"] == "succeeded":
print(f"Result: {data['result_url']}")
else:
print(f"Generation {data['status']}: {data.get('error_message')}")
# Enqueue, capture the generation id.
GEN_ID=$(curl -s -X POST https://hub.oxen.ai/api/ai/queue \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4",
"duration": 6,
"extend_mode": "end"
}' | jq -r '.generations[0].generation_id')
# Poll until the generation reaches a terminal status.
while true; do
STATUS=$(curl -s -H "Authorization: Bearer $OXEN_API_KEY" \
"https://hub.oxen.ai/api/ai/queue/$GEN_ID" | jq -r '.status')
echo "Status: $STATUS"
case $STATUS in succeeded|failed|cancelled) break;; esac
sleep 5
done
# Print the result.
curl -s -H "Authorization: Bearer $OXEN_API_KEY" \
"https://hub.oxen.ai/api/ai/queue/$GEN_ID" | jq .
import os
import time
import requests
HEADERS = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['OXEN_API_KEY']}",
}
enqueue = requests.post(
"https://hub.oxen.ai/api/ai/queue",
headers=HEADERS,
json={
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4",
"duration": 6,
"extend_mode": "end"
},
)
enqueue.raise_for_status()
generation_id = enqueue.json()["generations"][0]["generation_id"]
while True:
data = requests.get(
f"https://hub.oxen.ai/api/ai/queue/{generation_id}",
headers=HEADERS,
).json()
if data["status"] in {"succeeded", "failed", "cancelled"}:
break
time.sleep(5)
if data["status"] == "succeeded":
print(f"Result: {data['result_url']}")
else:
print(f"Generation {data['status']}: {data.get('error_message')}")
See the async queue reference for more details.
- Minimal
- All parameters
# Enqueue, capture the generation id.
GEN_ID=$(curl -s -X POST https://hub.oxen.ai/api/ai/queue \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4"
}' | jq -r '.generations[0].generation_id')
# Stream the SSE channel, grab the data line that follows a
# media_generation_completed event for our id, and pretty-print it.
curl -sN -H "Authorization: Bearer $OXEN_API_KEY" https://hub.oxen.ai/api/events \
| awk -v id="$GEN_ID" '
/^event: media_generation_completed$/ { expect=1; next }
/^data: / && expect {
payload = substr($0, 7)
if (index(payload, "\"generation_id\":\"" id "\"")) { print payload; exit }
expect = 0
}
' | jq .
import json
import os
import requests
API_KEY = os.environ["OXEN_API_KEY"]
AUTH = {"Authorization": f"Bearer {API_KEY}"}
enqueue = requests.post(
"https://hub.oxen.ai/api/ai/queue",
headers={**AUTH, "Content-Type": "application/json"},
json={
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4"
},
)
enqueue.raise_for_status()
generation_id = enqueue.json()["generations"][0]["generation_id"]
with requests.get(
"https://hub.oxen.ai/api/events",
headers=AUTH,
stream=True,
) as stream:
event_name = None
for line in stream.iter_lines(decode_unicode=True):
if line.startswith("event: "):
event_name = line.removeprefix("event: ")
elif line.startswith("data: ") and event_name == "media_generation_completed":
payload = json.loads(line.removeprefix("data: "))
if payload.get("generation_id") == generation_id:
print(payload)
break
# Enqueue, capture the generation id.
GEN_ID=$(curl -s -X POST https://hub.oxen.ai/api/ai/queue \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4",
"duration": 6,
"extend_mode": "end"
}' | jq -r '.generations[0].generation_id')
# Stream the SSE channel, grab the data line that follows a
# media_generation_completed event for our id, and pretty-print it.
curl -sN -H "Authorization: Bearer $OXEN_API_KEY" https://hub.oxen.ai/api/events \
| awk -v id="$GEN_ID" '
/^event: media_generation_completed$/ { expect=1; next }
/^data: / && expect {
payload = substr($0, 7)
if (index(payload, "\"generation_id\":\"" id "\"")) { print payload; exit }
expect = 0
}
' | jq .
import json
import os
import requests
API_KEY = os.environ["OXEN_API_KEY"]
AUTH = {"Authorization": f"Bearer {API_KEY}"}
enqueue = requests.post(
"https://hub.oxen.ai/api/ai/queue",
headers={**AUTH, "Content-Type": "application/json"},
json={
"model": "ltx-2-3-extend",
"input_video": "https://hub.oxen.ai/api/repos/ox/Oxen-AI-Assets/file/main/images/winter_summer_ox.mp4",
"duration": 6,
"extend_mode": "end"
},
)
enqueue.raise_for_status()
generation_id = enqueue.json()["generations"][0]["generation_id"]
with requests.get(
"https://hub.oxen.ai/api/events",
headers=AUTH,
stream=True,
) as stream:
event_name = None
for line in stream.iter_lines(decode_unicode=True):
if line.startswith("event: "):
event_name = line.removeprefix("event: ")
elif line.startswith("data: ") and event_name == "media_generation_completed":
payload = json.loads(line.removeprefix("data: "))
if payload.get("generation_id") == generation_id:
print(payload)
break
Fetch model details
The models endpoint returns the full model object, including itsjson_request_schema.
curl -H "Authorization: Bearer $OXEN_API_KEY" https://hub.oxen.ai/api/ai/models/ltx-2-3-extend
Request parameters
Required parameters
| Field | Type | Default | Description |
|---|---|---|---|
input_video | string | — | The clip to extend. 16:9 or 9:16, up to 4K, at least 3 seconds. Format: uri. |
Optional parameters
| Field | Type | Default | Description |
|---|---|---|---|
prompt | string | — | Optional description of what happens in the added footage. |
duration | integer | 6 | Seconds of new footage to add, 2 to 20. Range: 2 – 20. |
extend_mode | string | "end" | Add the new footage at the start or the end of the clip. One of: start, end. |
context | number | — | Seconds of the input video to use as context, up to 20. Defaults to 5 (less for long extensions). Context seconds are billed with the extension. Range: 1 – 20. |