图像、视频与语音生成 API

管理入口 · OpenAPI 规格

基础地址:https://api.douchengjiu.com。所有业务请求携带 Authorization: Bearer YOUR_API_KEY。API Key 放在调用程序的服务端,不嵌入公开网页。

调用流程

上传参考素材(可选) → 提交生成任务(返回 202) → 每 5–10 秒查询状态 → 完成后凭相同 API Key 下载结果。

方法与路径说明
GET /v1/models模型和工作流版本
POST /v1/files?filename=reference.png上传原始文件字节,返回 file_id。不是 multipart 表单。
POST /v1/images/generations千问生图
POST /v1/videos/generationsH3 文生视频 / 多参考视频 / 无缝长视频分段
POST /v1/audio/generations固定双音色(真空照1 / 真源空1)的 CPU 按需语音生成
GET /v1/tasks/{id}任务状态、实际参数、结果链接
GET /v1/tasks当前调用方最近 100 个任务
GET /v1/files/{id}/content下载参考文件或生成结果,需要鉴权
POST /v1/tasks/{id}/cancel仅取消尚未领取的排队任务
GET /v1/status算力机在线状态和全局排队数量

千问生图

{
  "model": "qwen-image-2512-bf16",
  "prompt": "清晨的竹林,一只白色陶瓷茶杯放在石桌上,写实摄影",
  "width": 1024, "height": 1024,
  "steps": 50, "cfg": 4, "seed": 12345
}

H3 文生视频

{
  "model": "minimax-h3-t2v",
  "prompt": "A ceramic cup on a wooden table. Morning light, slow camera move. Gentle birdsong, no dialogue or text.",
  "width": 768, "height": 512, "duration": 5,
  "steps": 20, "sage_attention": "auto"
}

H3 完整 BF16 多参考

{
  "model": "minimax-h3-ref2va-bf16",
  "prompt": "The character in <Picture 1> follows the movement in <Video 1>. Natural movement, stable identity, no text.",
  "reference_images": ["file_上传图片返回的编号"],
  "reference_videos": ["file_上传视频返回的编号"],
  "reference_audios": [],
  "include_reference_video_audio": false,
  "width": 768, "height": 512, "duration": 5,
  "steps": 20, "ref_image_size": "max", "sage_attention": "auto"
}

最多 9 张图片、3 段参考视频、3 段音频。参考视频为 2–15 秒,自动取 24fps,最大 4K;独立参考音频最多 30 秒。需要参考视频原声时启用 include_reference_video_audio,素材必须含音轨。ref_image_size=max 保留原完整 BF16 工作流设置,速度较慢;match 可减少参考图处理量。T2V 使用现有 INT8 模型及 NVFP4 文本编码器,Ref2VA 使用完整 BF16 主模型和文本编码器。SageAttention 适用于视频接口。

H3 无缝长视频(存档槽位·逐段续写)

用 minimax-h3-ref2va-slot-bf16 把多段短视频首尾相接成一条长视频,衔接处画面与声音都连续,而不是每段重新起头。它和上面多参考模型的参数完全一致,另加四个:

参数说明
clip_index本段是第几段,从 1 开始,最大 9999
chain_id这条链的名字,字母数字下划线连字符,1–40 字符。不同链、不同调用方互相隔离
prev_task_id上一段的任务 id;第 1 段不要传,第 2 段起必填
context_length从上一段末尾带入多少帧,默认 22。有效值只有 1/5/22/39,其他会向下吸附

一次请求只生成一段,由调用方按顺序逐段提交:第 1 段成功后再提交第 2 段,以此类推。每段返回的 MP4 已经把衔接处重复的头部剪掉,直接按顺序拼接就是成品。

服务端会校验顺序:上一段必须已经 succeeded、必须属于同一个 API Key、clip_index 必须正好接上。跳段、乱序或借用别人的任务都会返回 409 或 400,不会静默生成一条接错的片子。第 1 段请单独起一个 chain_id,同一条链上不要复用旧链的名字。

{
  "model": "minimax-h3-ref2va-slot-bf16",
  "prompt": "The character in <Picture 1> keeps walking, same direction and speed, no text.",
  "reference_images": ["file_上传图片返回的编号"],
  "clip_index": 2,
  "chain_id": "story-2026-09",
  "prev_task_id": "task_上一段返回的编号",
  "width": 512, "height": 768, "duration": 5,
  "steps": 20, "context_length": 22
}

第 1 段把 clip_index 设为 1 并且不要传 prev_task_id。提示词每段都要重述一次人物与动作,续写靠的是画面和声音的衔接,不会自动记住上一段的文字描述。链越长,总耗时约等于段数乘以单段耗时;中途插入其他任务会触发模型卸载重载,建议一条链连着跑完。

Python 示例

import os, time, requests
BASE = "https://api.douchengjiu.com"
headers = {"Authorization": "Bearer " + os.environ["DCJ_API_KEY"]}
r = requests.post(BASE + "/v1/images/generations",
    headers={**headers, "Idempotency-Key": "your-unique-request-id"},
    json={"prompt": "一只白色陶瓷茶杯,写实摄影"}, timeout=30)
r.raise_for_status()
task_id = r.json()["id"]
while True:
    r = requests.get(BASE + "/v1/tasks/" + task_id, headers=headers, timeout=30)
    r.raise_for_status()
    task = r.json()
    if task["status"] in ("succeeded", "failed", "cancelled", "needs_attention"):
        break
    time.sleep(5)
if task["status"] != "succeeded":
    raise RuntimeError(task.get("error") or task["status"])
with requests.get(task["outputs"][0]["download_url"], headers=headers,
                  stream=True, timeout=120) as result:
    result.raise_for_status()
    with open("result.png", "wb") as file:
        for chunk in result.iter_content(1024 * 1024):
            file.write(chunk)

# 参考素材上传:
# with open("reference.png", "rb") as file:
#     r = requests.post(BASE + "/v1/files", params={"filename": "reference.png"},
#                       headers=headers, data=file, timeout=120)
#     r.raise_for_status()#     file_id = r.json()["id"]

# 无缝长视频:按顺序逐段提交,前一段成功后再提交下一段
def generate_chain(prompt, reference_image, segments=3, chain_id="story-1"):
    previous = None
    for clip in range(1, segments + 1):
        body = {"model": "minimax-h3-ref2va-slot-bf16", "prompt": prompt,
                "reference_images": [reference_image],
                "clip_index": clip, "chain_id": chain_id,
                "width": 512, "height": 768, "duration": 5, "steps": 20}
        if previous:
            body["prev_task_id"] = previous
        r = requests.post(BASE + "/v1/videos/generations", headers=headers, json=body, timeout=30)
        r.raise_for_status()
        previous = r.json()["id"]
        while True:
            task = requests.get(BASE + "/v1/tasks/" + previous, headers=headers, timeout=30).json()
            if task["status"] in ("succeeded", "failed", "cancelled", "needs_attention"):
                break
            time.sleep(10)
        if task["status"] != "succeeded":
            raise RuntimeError("第 %d 段失败:%s" % (clip, task.get("error") or task["status"]))
        with requests.get(task["outputs"][0]["download_url"], headers=headers,
                          stream=True, timeout=120) as result:
            with open("clip_%02d.mp4" % clip, "wb") as file:
                for chunk in result.iter_content(1024 * 1024):
                    file.write(chunk)
    # 各段已剪掉衔接处的重复头,用同一套编码参数直接拼接即可
    # ffmpeg -f concat -safe 0 -i list.txt -c copy long.mp4

固定音色 CPU 按需语音

{
  "model": "cosyvoice-3",
  "voice": "真空照1音色",
  "input": "你好,这是语音生成测试。",
  "speed": 1,
  "response_format": "mp3"
}

voice 可填 真空照1音色 或 真源空1音色;省略时仍默认原来的真空照1音色。真源空1音色采用 A 版的原始参考片段,不接受调用方指定参考文件。

接口返回 202 异步任务。单次最多 1000 个 Unicode 字符,输出格式仅 mp3 或 wav,语速范围 0.5–2、默认 1。当前不开放任意克隆音频上传和情绪参数。语音任务按需在 CPU 加载模型,空闲时不占用 GPU;H3 换模或 WSL 可用内存低于 15 GiB 时自动等待,必要时中止本次配音计算并重试。首次加载会增加等待时间。

参数与运行约定