Appearance
ComfyUI LTX-2 文生视频 API 调用手册
本手册说明如何通过公网网关调用 LTX-2 19B 模型做文生视频。 网关通用说明(鉴权、限流、错误码)见 AI API Gateway — API 调用手册。
网关地址:
https://ai.ospreyai.cn(公网) 模型:ltx-2-19b-dev-fp8.safetensors+ltx-2-19b-distilled-lora-384.safetensors(加速) 无需后端 Bearer Token
一、概述
LTX-2 19B 是 Lightricks 的视频生成模型。本工作流采用两阶段采样管线:先用低分辨率(输出尺寸的 1/2)快速打底 20 步,再空间放大 2× 精修 4 步,输出带空音轨的 mp4 静音视频。
- 网关地址:
https://ai.ospreyai.cn - 鉴权:
Authorization: Bearer sk-xxx(网关 new-api 的 key) - 模型:
ltx-2-19b-dev-fp8.safetensors+ltx-2-19b-distilled-lora-384.safetensors(加速)
bash
export GW="https://ai.ospreyai.cn"
export API_KEY="sk-your-api-key"二、接口清单
| 用途 | 方法 | 路径 |
|---|---|---|
| 提交视频任务 | POST | /api/v1/ai/video/generate |
| 查询任务状态 | GET | /api/v1/ai/tasks/{prompt_id} |
| 下载结果文件 | GET | /api/v1/ai/image/view/ |
| 查询队列 | GET | /api/v1/ai/queue |
提交任务后异步生成,需轮询
tasks/{prompt_id}直到status.completed=true,再下载。
三、提交视频生成任务
POST /api/v1/ai/video/generate
Content-Type: application/json
Authorization: Bearer sk-xxx请求体为 ComfyUI 工作流 JSON,prompt 字段内为节点定义(连接用 ["node_id", slot] 格式)。
bash
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/ai/video/generate" \
-H "Content-Type: application/json" \
-d '{
"prompt": {
"75": {"inputs": {"filename_prefix": "video/LTX-2", "format": "mp4", "codec": "auto", "video": ["122", 0]}, "class_type": "SaveVideo"},
"98": {"inputs": {"steps": 20, "max_shift": 2.05, "base_shift": 0.95, "stretch": true, "terminal": 0.1, "latent": ["109", 0]}, "class_type": "LTXVScheduler"},
"99": {"inputs": {"text_encoder": "gemma_3_12B_it_fp4_mixed.safetensors", "ckpt_name": "ltx-2-19b-dev-fp8.safetensors", "device": "default"}, "class_type": "LTXAVTextEncoderLoader"},
"100": {"inputs": {"sigmas": "0.909375, 0.725, 0.421875, 0.0"}, "class_type": "ManualSigmas"},
"101": {"inputs": {"model_name": "ltx-2-spatial-upscaler-x2-1.0.safetensors"}, "class_type": "LatentUpscaleModelLoader"},
"102": {"inputs": {"positive": ["107", 0], "negative": ["107", 1], "latent": ["116", 0]}, "class_type": "LTXVCropGuides"},
"103": {"inputs": {"cfg": 1, "model": ["132", 0], "positive": ["102", 0], "negative": ["102", 1]}, "class_type": "CFGGuider"},
"104": {"inputs": {"upscale_method": "lanczos", "scale_by": 0.5, "image": ["111", 0]}, "class_type": "ImageScaleBy"},
"105": {"inputs": {"image": ["104", 0]}, "class_type": "GetImageSize"},
"106": {"inputs": {"frames_number": ["112", 0], "frame_rate": ["130", 0], "batch_size": 1, "audio_vae": ["123", 0]}, "class_type": "LTXVEmptyLatentAudio"},
"107": {"inputs": {"frame_rate": ["129", 0], "positive": ["121", 0], "negative": ["110", 0]}, "class_type": "LTXVConditioning"},
"108": {"inputs": {"width": ["105", 0], "height": ["105", 1], "length": ["112", 0], "batch_size": 1}, "class_type": "EmptyLTXVLatentVideo"},
"109": {"inputs": {"video_latent": ["108", 0], "audio_latent": ["106", 0]}, "class_type": "LTXVConcatAVLatent"},
"110": {"inputs": {"text": "blurry, low quality, still frame, frames, watermark, overlay, titles, has blurbox, has subtitles", "clip": ["99", 0]}, "class_type": "CLIPTextEncode"},
"111": {"inputs": {"width": 1280, "height": 720, "batch_size": 1, "color": 0}, "class_type": "EmptyImage"},
"112": {"inputs": {"value": 121}, "class_type": "PrimitiveInt"},
"113": {"inputs": {"noise": ["115", 0], "guider": ["128", 0], "sampler": ["135", 0], "sigmas": ["98", 0], "latent_image": ["109", 0]}, "class_type": "SamplerCustomAdvanced"},
"114": {"inputs": {"noise_seed": 0}, "class_type": "RandomNoise"},
"115": {"inputs": {"noise_seed": 12345}, "class_type": "RandomNoise"},
"116": {"inputs": {"av_latent": ["113", 0]}, "class_type": "LTXVSeparateAVLatent"},
"117": {"inputs": {"video_latent": ["118", 0], "audio_latent": ["116", 1]}, "class_type": "LTXVConcatAVLatent"},
"118": {"inputs": {"samples": ["102", 2], "upscale_model": ["101", 0], "vae": ["138", 2]}, "class_type": "LTXVLatentUpsampler"},
"119": {"inputs": {"noise": ["114", 0], "guider": ["103", 0], "sampler": ["136", 0], "sigmas": ["100", 0], "latent_image": ["117", 0]}, "class_type": "SamplerCustomAdvanced"},
"121": {"inputs": {"text": "A cheerful girl puppet singing in the rain, close-up, soft lighting, photorealistic", "clip": ["99", 0]}, "class_type": "CLIPTextEncode"},
"122": {"inputs": {"fps": ["129", 0], "images": ["126", 0], "audio": ["127", 0]}, "class_type": "CreateVideo"},
"123": {"inputs": {"ckpt_name": "ltx-2-19b-dev-fp8.safetensors"}, "class_type": "LTXVAudioVAELoader"},
"124": {"inputs": {"av_latent": ["119", 1]}, "class_type": "LTXVSeparateAVLatent"},
"126": {"inputs": {"tile_size": 512, "overlap": 64, "temporal_size": 4096, "temporal_overlap": 8, "samples": ["124", 0], "vae": ["138", 2]}, "class_type": "VAEDecodeTiled"},
"127": {"inputs": {"samples": ["124", 1], "audio_vae": ["123", 0]}, "class_type": "LTXVAudioVAEDecode"},
"128": {"inputs": {"cfg": 4, "model": ["138", 0], "positive": ["107", 0], "negative": ["107", 1]}, "class_type": "CFGGuider"},
"129": {"inputs": {"value": 24}, "class_type": "PrimitiveFloat"},
"130": {"inputs": {"value": 24}, "class_type": "PrimitiveInt"},
"132": {"inputs": {"lora_name": "ltx-2-19b-distilled-lora-384.safetensors", "strength_model": 1, "model": ["138", 0]}, "class_type": "LoraLoaderModelOnly"},
"135": {"inputs": {"sampler_name": "euler_ancestral"}, "class_type": "KSamplerSelect"},
"136": {"inputs": {"sampler_name": "euler_ancestral"}, "class_type": "KSamplerSelect"},
"138": {"inputs": {"ckpt_name": "ltx-2-19b-dev-fp8.safetensors"}, "class_type": "CheckpointLoaderSimple"}
},
"extra_data": {}
}'响应:
json
{"prompt_id": "5af01c46-eeba-4978-9bbd-71d763c770d4", "number": 6, "node_errors": {}}完整工作流节点说明
| 节点 ID | class_type | 作用 |
|---|---|---|
| 121 | CLIPTextEncode | 正向提示词(英文动作描述) |
| 110 | CLIPTextEncode | 负向提示词(内置:模糊/低质/静态/水印等) |
| 111 | EmptyImage | 输出尺寸(如 1280×720),低清阶段会 ×0.5 |
| 112 | PrimitiveInt | 帧数(默认 121,24fps≈5s) |
| 129 / 130 | PrimitiveFloat / PrimitiveInt | 帧率(两处必须同步,默认 24) |
| 115 | RandomNoise | 低清阶段随机种子 |
| 99 | LTXAVTextEncoderLoader | 加载 Gemma-3 文本/音频编码器 |
| 138 | CheckpointLoaderSimple | 主模型 ltx-2-19b-dev-fp8.safetensors |
| 132 | LoraLoaderModelOnly | 加速 LoRA ltx-2-19b-distilled-lora-384(strength=1) |
| 98 | LTXVScheduler | 低清调度器(steps=20) |
| 113 | SamplerCustomAdvanced | 低清采样(20 步) |
| 118 | LTXVLatentUpsampler | 空间放大 ×2(用 ltx-2-spatial-upscaler-x2-1.0) |
| 100 | ManualSigmas | 精修 sigma 序列(4 步) |
| 119 | SamplerCustomAdvanced | 精修采样(4 步) |
| 126 | VAEDecodeTiled | 视频解码(tile_size=512) |
| 127 | LTXVAudioVAEDecode | 空音轨解码 |
| 122 | CreateVideo | 合成视频(fps 来自 129) |
| 75 | SaveVideo | 输出前缀(默认 video/LTX-2,mp4) |
关键参数
| 节点 | 字段 | 说明 | 推荐值 |
|---|---|---|---|
| 121 | text | 正向提示词(英文) | — |
| 111 | width / height | 输出分辨率(需被 32 整除) | 1280 × 720 |
| 112 | value | 帧数 | 121(≈5s@24fps) |
| 129 / 130 | value | 帧率(两处同步) | 24 |
| 115 | noise_seed | 随机种子 | 任意整数 |
| 75 | filename_prefix | 输出文件名前缀(可含子目录) | video/LTX-2 |
提示词技巧
- 英文优先(文本编码器基于 Gemma-3)
- 动作 + 镜头 + 光影 + 质感四要素:
A close-up of a cheerful girl puppet, singing with joy, rain falls gently around her, the camera holds steady, rain sparkles against the soft lighting. - 运镜:
camera dolly out/slow pan/close-up
两阶段参数含义
| 阶段 | 节点 | 步数 | 分辨率 |
|---|---|---|---|
| 低清打底 | 98 + 113 | 20 步(LTXVScheduler) | 输出 ×0.5 |
| 精修 | 100 + 119 | 4 步(ManualSigmas) | 输出全尺寸 |
四、查询任务状态
GET /api/v1/ai/tasks/{prompt_id}
Authorization: Bearer sk-xxxbash
curl -H "Authorization: Bearer $API_KEY" "$GW/api/v1/ai/tasks/5af01c46-eeba-4978-9bbd-71d763c770d4"进行中:
json
{
"5af01c46-...": {
"outputs": {},
"status": { "status_str": "success", "completed": false }
}
}已完成:
json
{
"5af01c46-...": {
"status": { "status_str": "success", "completed": true },
"outputs": {
"75": {
"images": [
{ "filename": "LTX-2_00001_.mp4", "subfolder": "video", "type": "output" }
],
"animated": [true]
}
}
}
}视频输出在
outputs的images字段(文件名是 .mp4),同节点有animated布尔列表标记是动图/视频——不是gifs字段。
缓存坑:若提交的工作流与某次历史完全相同(尤其 seed 相同),ComfyUI 会命中
execution_cached直接返回缓存结果,此时outputs可能为空。提交时给个随机 seed 可避免。
五、下载结果
GET /api/v1/ai/image/view/?filename={filename}&type={type}&subfolder={subfolder}
Authorization: Bearer sk-xxx参数值来自任务状态响应的 outputs[].images[]。
bash
# 注意 subfolder=video 必须带上
curl -H "Authorization: Bearer $API_KEY" \
"$GW/api/v1/ai/image/view/?filename=LTX-2_00001_.mp4&type=output&subfolder=video" \
-o result.mp4输出: MP4 静音视频,1280×720, 121帧, 24fps, 约5秒(实测约 30s 出片,mp4 约 3MB)。
六、Python 调用示例
手动调用(不依赖脚本)
python
import json, time, urllib.request
GW = "https://ai.ospreyai.cn"
API_KEY = "sk-your-api-key"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
# 工作流节点定义(完整见上文 curl 示例)
nodes = {
"75": {"inputs": {"filename_prefix": "video/LTX-2", "format": "mp4", "codec": "auto", "video": ["122", 0]}, "class_type": "SaveVideo"},
# ...其余节点...
}
# 参数化
nodes["121"]["inputs"]["text"] = "A cheerful girl puppet singing in the rain"
nodes["112"]["inputs"]["value"] = 121 # 帧数
nodes["129"]["inputs"]["value"] = 24.0 # fps (float)
nodes["130"]["inputs"]["value"] = 24 # fps (int)
nodes["111"]["inputs"]["width"] = 1280
nodes["111"]["inputs"]["height"] = 720
nodes["115"]["inputs"]["noise_seed"] = 12345 # 种子,避免缓存命中
nodes["75"]["inputs"]["filename_prefix"] = "video/LTX-2"
# 提交
req = urllib.request.Request(
f"{GW}/api/v1/ai/video/generate",
data=json.dumps({"prompt": nodes, "extra_data": {}}).encode(),
headers=HEADERS, method="POST",
)
prompt_id = json.loads(urllib.request.urlopen(req, timeout=30).read())["prompt_id"]
# 轮询
while True:
r = urllib.request.Request(f"{GW}/api/v1/ai/tasks/{prompt_id}", headers=HEADERS)
task = json.loads(urllib.request.urlopen(r, timeout=15).read())[prompt_id]
if task["status"].get("completed"):
break
time.sleep(5)
# 下载(视频在 outputs 的 images 字段,文件名 .mp4,subfolder=video)
for out in task["outputs"].values():
for g in out.get("images", []):
if not g["filename"].endswith(".mp4"):
continue
url = f"{GW}/api/v1/ai/image/view/?filename={g['filename']}&type=output&subfolder={g.get('subfolder','')}"
req = urllib.request.Request(url, headers=HEADERS)
open(g["filename"], "wb").write(urllib.request.urlopen(req, timeout=120).read())封装脚本(如有)
技能目录提供封装脚本 comfyui-ltx2-text-to-video/scripts/text_to_video.py,自动完成提交 → 轮询 → 下载(实测通过,1280×720 / 121 帧 / 24fps,约 30s 出片,mp4 约 3MB):
bash
# 默认 5 秒 1280×720 视频到当前目录
python comfyui-ltx2-text-to-video/scripts/text_to_video.py \
--prompt "A cheerful girl puppet singing in the rain"
# 自定义参数
python comfyui-ltx2-text-to-video/scripts/text_to_video.py \
--prompt "A bird spreading its wings and flying away" \
--length 97 --fps 24 --seed 42 \
--output_prefix video/my_clip --output my_clip.mp4脚本参数:
| 参数 | 说明 | 默认 |
|---|---|---|
--prompt | 英文正向提示词(必须) | — |
--negative | 负向提示词 | 工作流内置 |
--length | 帧数 | 121 |
--fps | 帧率 | 24 |
--width / --height | 输出分辨率 | 1280 × 720 |
--seed | 随机种子 | 时间戳随机(避免命中缓存) |
--output_prefix | 输出前缀(可含子目录) | video/LTX-2 |
--output | 本地保存路径 | 当前目录/服务端名 |
--timeout | 轮询超时秒数 | 600 |
脚本原理:读取同目录
workflow.json,按命令行参数替换正/负提示词、帧数、帧率、分辨率、种子、输出前缀,提交后轮询,从outputs[].images中按 .mp4 扩展名取视频并下载。未指定 seed 时自动用时间戳随机,避免 ComfyUI 缓存命中导致 outputs 为空。改 ComfyUI 画布后导出新 JSON 覆盖workflow.json即可同步。
七、常见问题
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 401 Unauthorized | API Key 错误/未传 | 检查 Authorization: Bearer sk-xxx |
| 500 on generate | 工作流 JSON 格式错 | 用 {"prompt": {...}, "extra_data": {}},节点连接用 ["id", slot] |
node_errors 非空 | 分辨率不被 32 整除 / 模型缺失 | 宽高对齐到 32 的倍数;看 node_errors 详情 |
任务 success 但 outputs 为空 | 命中 ComfyUI 缓存(execution_cached) | 提交时换个随机 seed,避免工作流完全相同 |
| 轮询一直不完成 | 排队或首帧加载慢 | 首次约 30s 加载;增大 --timeout,用 prompt_id 手动重查 |
| 下载 404 | 没带 subfolder=video | 视频在 output 的 video/ 子目录,URL 必须带 subfolder=video |
| outputs 里找不到视频 | 找错字段 | 视频在 outputs[].images(文件名 .mp4 + animated 标记),不是 gifs |
| 视频无声 | 工作流设计为空音轨 | 本工作流输出静音视频;需带真实音频用 LTX 2.3 图音生视频 |
更新日志
| 版本 | 日期 | 更新内容 |
|---|---|---|
| v0.1.1 | 2026.07.24 | 修正:视频输出在 outputs[].images 字段(非 gifs);补充缓存命中导致 outputs 为空的说明;脚本未指定 seed 时自动随机;实测通过 |
| v0.1.0 | 2026.07.24 | 初始版本:LTX-2 19B 文生视频,两阶段管线,输出静音 mp4 |