# Qora 视频 API 接口文档 v1.4 ## 快速开始与鉴权 本版为 Qora 视频 API v1.7。使用自己的 Qora 账号创建 API Key,从应用服务端调用。网站、画布和 API 共用账号积分;你的电脑关闭后,已提交的云端任务仍继续。图片生成、AI对话、回调通知目前未开放。上传参考图片不等于调用图片生成。 ```text https://qorastudio.cn/api/v1 Authorization: Bearer YOUR_QORA_API_KEY Content-Type: application/json ``` 在左侧“API 接入”创建密钥。完整密钥只显示一次,可随时撤销;每个账号最多10把有效密钥。不要把密钥放进公开网页、代码仓库或发给其他用户。 请求头 | 是否必填 | 说明 --- | --- | --- Authorization | 所有业务接口必填 | Bearer + 空格 + 本账号 API Key;Cookie 不能替代此鉴权 Content-Type | JSON请求必填 | application/json;素材上传使用文件真实 MIME Idempotency-Key | 报价与生成必填 | 1–128位字母、数字或 . _ : -;同一个订单复用相同值 X-Qora-Source | 素材上传必填 | 文件内容 SHA-256,小写64位十六进制 Content-Length | 素材上传必填 | 文件字节数,curl/常见HTTP客户端可自动设置 特惠官方480p(稳定版)使用参考视频时,先调用 /video/quotes 获取完整 price_credits,再以相同 Idempotency-Key 和素材提交 /video/generations,并传 max_price_credits 确认最高积分;未确认或限额不足返回409,且不扣款。报价会包含参考素材费用。推荐流程:读取模型 → /assets/direct授权 → 文件直传本站OSS → complete确认ready → 用素材id填写references → 提交并保存Qora任务编号 → 查询状态 → 下载。同账号同文件复用未过期id,不重复上传、不延长到期时间。其他无需确认完整报价的请求,可直接提交生成;想先核对预算时再查询报价。服务端仍会核价和检查积分,直接提交不绕过计费。示例编号、时间和链接只展示结构;模型规格与费用以当前接口返回为准。此API采用本站格式,不代表可直接填入任意OpenAI兼容软件。 ## 接口总览 方法 | 路径(相对于BASE URL) | 用途 --- | --- | --- GET | /balance | 查询本账号可用积分及对应人民币计价金额 GET | /video/models | 模型、价格、规格及可用状态 POST | /assets/direct | 默认推荐:文件直传本站OSS、确认后获取素材编号 POST | /assets | 兼容旧接法:二进制上传参考图片、视频或音频 POST | /video/quotes | 估价;不入队、不扣积分 POST | /video/generations | 提交生成;原订单重试去重 GET | /video/generations | 本账号任务列表,最多300条 GET | /video/generations/{id} | 本账号单个任务状态 GET | /video/generations/{id}/content | 本账号成品视频二进制下载 GET | /tasks | 近7天任务日志,支持分页与筛选 GET | /tasks/{kind}/{id} | 完整任务详情、进度与报错 GET | /tasks/{kind}/{id}/content | 下载未过期视频或图片 文档、TXT全文和OpenAPI JSON可公开访问;以上业务接口均需Bearer密钥。暂未提供取消任务、图片生成、对话或Webhook接口。 ## 查询本站账号余额 GET https://qorastudio.cn/api/v1/balance ```bash curl 'https://qorastudio.cn/api/v1/balance' \ -H 'Authorization: Bearer YOUR_QORA_API_KEY' ``` 返回创建该 API Key 的本站账号可用积分,与网页钱包读取同一份数据。多把密钥共享账号余额,不是每把密钥各有一份额度;不能通过传入账号、用户名或密钥编号查询他人余额。查询不扣生成积分,不创建任务。 ```json { "data": { "balance_credits": 712.5, "balance_cny": 71.25, "currency": "CNY", "credits_per_cny": 10, "updated_at": 1792324800000 } } ``` 字段 | 类型 | 说明 --- | --- | --- data.balance_credits | number | 当前可用积分,支持小数 data.balance_cny | number | 按10积分=1元折算的本站服务计价金额 data.currency | string | CNY data.credits_per_cny | number | 10,即1元对应10积分 data.updated_at | integer | null | 钱包最近变动时间,Unix毫秒;没有钱包记录时为null 没有钱包记录时余额返回0,不会为查询创建钱包或充值。响应不缓存;充值、生成预扣和退积分后的查询读取最新余额。余额查询与其他API共用每账号每分钟60次限额,建议60秒刷新一次。401表示密钥缺失、无效或已撤销;429表示请求过于频繁;503表示余额暂时无法读取,请稍后重试。 ## 近7天任务日志、进度与失败原因 GET https://qorastudio.cn/api/v1/tasks 登录创建密钥的账号,在网站左侧「任务日志」查看同一批记录。网页、画布与API提交的视频和图片统一查询;这里只开放图片历史查询,不代表开放图片生成API。任务历史可查7天,文件保存期仍以expires_at为准,不会延长为7天。仅报价未受理的草稿不计为生成任务。 参数 | 说明 --- | --- page / page_size | 页码默认1;每页默认25,最大100 kind | all / video / image status | all / queued / processing / completed / failed / reviewing / delivery_blocked / expired;expired仅筛选成片过期记录 source | all / api / studio / canvas / web / admin / unknown;旧记录未记录来源时为unknown id | 本站完整任务UUID,或至少前4位编号 from / to | 提交时间范围,Unix毫秒时间戳,限近7天 as_of | 翻页时沿用首次返回值,排除之后新增任务;自然超出7天窗口的旧记录仍会退出 ```bash curl "https://qorastudio.cn/api/v1/tasks?source=api&page=1&page_size=100" -H "Authorization: Bearer YOUR_QORA_API_KEY" ``` 返回data、page、page_size、total、pages、has_more、as_of、window和generated_at。每条任务含本站编号、提示词摘要、本站模型编号、来源、提交/开始/结束时间、elapsed_ms、status、stage_name、progress、积分、file_status和下载路径。model为本站展示编号:视频qr-v、图片qr-i。图片编号只用于历史展示,不是创建图片任务的接口参数。 GET /tasks/{kind}/{id}(kind为video或image)返回data,另含完整prompt、parameters、timeline和timing_note。error.message是本站说明,error.suggestion是处理建议;error.specific=false表示现有记录没有具体原因,请保留本站任务编号联系Qora客服核查。不会将不明确的失败解释为版权、人脸或素材问题。 版权相关检查失败会说明应调整角色、场景和作品元素;已确认的图片比例、大小和格式问题会说明相应限制。当前生成资源暂不可用时提示联系Qora客服处理;本账号积分不足会明确提示补足本站积分,两者不同。charged_credits、refunded_credits、net_credits均依据实际积分流水,不以失败状态推断退款。 progress为null表示未提供百分比;百分比只反映已报告阶段,是否成功应看status。completed表示生成已完成,file_status=expired表示文件保存期已结束,历史任务仍为成功。reviewing请保留原任务等待核查;delivery_blocked请联系站长领取,不自动新建生成。elapsed_ms包含排队、生成和文件接收;未记录的时间为null,不填造开始时间。 建议每15—30秒批量查询一页正在处理的任务,避免为每个任务单独高频查询;后台隐藏标签页时停止刷新。所有密钥共用每分钟60次限额,返回429时降低频率,勿创建新订单或新密钥绕过。查询、查看详情及下载不另扣生成积分。 成片就绪后直接 GET 返回的 download_url。OSS 绝对地址无需密钥;仅本站相对路径携带本账号 Bearer 密钥,支持图片与视频以及307临时下载跳转。不要将本站密钥发送给其他域名。只有file_status=ready且路径非空才能下载;到期返回410。 ## 模型列表与能力 GET https://qorastudio.cn/api/v1/video/models ```bash curl 'https://qorastudio.cn/api/v1/video/models' \ -H 'Authorization: Bearer YOUR_QORA_API_KEY' ``` data[].id 用作生成请求的 route_id,不能用显示名称替代。只有 available=true 的方案可报价和生成。available表示平台当前是否开放该方案;实际请求仍受余额、参数和生成资源影响。 字段 | 类型 | 含义 --- | --- | --- data | array | 模型方案列表;包含暂不可用的展示方案 data[].id / model / name | string | 调用方案ID / 模型系列标识 / 显示名称 data[].available | boolean | 是否开放调用;false时不能提交 data[].billing | second | generation | 单价按秒或按条 data[].prices_credits | object | 按清晰度列出的积分单价,例720p:15 data[].price_credits_per_generation | number / 可选 | 固定按条售价的兼容字段;须同时检查prices_credits、resolutions和durations data[].specifications_pending | boolean / 可选 | true表示仍有规格待确认,available=false,不能报价或生成 data[].resolutions / ratios | string[] | 支持的清晰度和比例 data[].durations | integer[] | 支持的整数秒数 data[].duration_ranges | object | null | 按清晰度限制秒数,须同时满足durations data[].modes | string[] | 允许的task_mode,见生成参数 data[].references | object | images/videos/audio为最大数量;min_images/min_audio为最小数量 data[].references.audio_max_total_seconds / audio_requires_image | number / boolean,可选 | 参考音频总时长上限(秒)/使用音频时是否必须同时有图片;原生720为15秒/true data[].prompt_required / prompt_limit | boolean / integer | 是否需要非空提示词 / 提示词长度上限 data[].reference_video_prices_credits | object / 可选 | 参考视频按清晰度的积分秒价,Wan另收此项 data[].reference_video_max_seconds / output_and_reference_max_seconds | number / 可选 | 参考视频总时长上限 / 输出加参考视频时长上限 data[].duration_source | duration | audio_duration | 常规时长或音频驱动时长;请求字段仍叫duration data[].note | string | 方案补充说明 currency / credits_per_cny | string / number | credits;1元=10积分 ```json { "data": [ { "id": "qr-v021", "model": "seedance-mini", "name": "按条特惠", "available": true, "note": "至少1张参考图片;5、10、15秒同价。", "billing": "generation", "prices_credits": { "720p": 15 }, "resolutions": [ "720p" ], "ratios": [ "16:9", "9:16", "1:1", "4:3", "3:4" ], "durations": [ 5, 10, 15 ], "duration_ranges": null, "modes": [ "references" ], "references": { "images": 9, "videos": 0, "audio": 0, "min_images": 1, "min_audio": 0 }, "prompt_required": true, "duration_source": "duration", "prompt_limit": 15000 } ], "currency": "credits", "credits_per_cny": 10 } ``` 不要按名称推断能力,也不要把“暂时不可用”的方案当成已开放。带清晰度分档的方案,必须同时检查该档的时长范围。 ## 当前模型编号与规格清单 API中的Seedance 2.5保留稳定版480p、原生720及满血10图;其他系列以此表为准。只选择当前available=true的方案,已下架方案不能新建任务;原任务仍可查询及下载。各方案的素材与计费规则独立,不套用其他方案的上限。 模型/方案 | route_id | 状态 | 售价 --- | --- | --- | --- Wan 3.0 · 万相3.0 · 按条版 | qr-v043 | 暂时不可用 | 480p:25积分/条(¥2.50/条);720p:25积分/条(¥2.50/条);1080p:25积分/条(¥2.50/条) Seedance 2.5 · 骨折版满血10图 | qr-v042 | 开放调用 | 720p:55积分/条(¥5.50/条);1080p:70积分/条(¥7.00/条) Seedance 2.0 · 满血按条2.0(480p) | qr-v040 | 开放调用 | 30积分/条(¥3.00/条) Seedance 2.0 Fast · 短片特惠 | qr-v035 | 开放调用 | 15积分/条(¥1.50/条) Seedance 2.0 Fast · 按条特惠 | qr-v036 | 开放调用 | 25积分/条(¥2.50/条) Seedance 2.0 · 满血按条2.0 | qr-v037 | 开放调用 | 39积分/条(¥3.90/条) MiniMax H3 · 长视频全能参考 | qr-v038 | 开放调用 | 480p:0.8积分/秒(¥0.08/秒);720p:0.9积分/秒(¥0.09/秒) Seedance 2.5 · 特惠官方480p(稳定版) | qr-v007 | 开放调用 | 480p:3.5积分/秒(¥0.35/秒) Seedance 2.5 · 原生720 | qr-v012 | 开放调用 | 720p:4.5积分/秒(¥0.45/秒) Seedance 2.0 · 竖屏特惠 | qr-v018 | 开放调用 | 720p:2积分/秒(¥0.20/秒) Seedance 2.0 Mini · 竖屏特惠 | qr-v019 | 开放调用 | 720p:1积分/秒(¥0.10/秒) Seedance 2.0 Fast · 竖屏特惠 | qr-v020 | 开放调用 | 720p:1.5积分/秒(¥0.15/秒) MiniMax H3 · 轻映 · 多图参考 | qr-v024 | 开放调用 | 480p:0.4积分/秒(¥0.04/秒);768p:0.9积分/秒(¥0.09/秒);1080p:1.3积分/秒(¥0.13/秒) MiniMax H3 · 述影 · 文本创作 | qr-v025 | 开放调用 | 480p:0.7积分/秒(¥0.07/秒);768p:0.8积分/秒(¥0.08/秒) MiniMax H3 · 镜桥 · 首尾衔接 | qr-v026 | 开放调用 | 480p:0.8积分/秒(¥0.08/秒);768p:1积分/秒(¥0.10/秒) MiniMax H3 · 合拍 · 全能参考 | qr-v027 | 开放调用 | 480p:1积分/秒(¥0.10/秒);768p:1.2积分/秒(¥0.12/秒) MiniMax H3 · 声演 · 音画同步 | qr-v028 | 开放调用 | 480p:1.1积分/秒(¥0.11/秒);768p:1.2积分/秒(¥0.12/秒);1080p:1.4积分/秒(¥0.14/秒) MiniMax H3 · 臻映 · 全能参考 | qr-v032 | 开放调用 | 480p:1.2积分/秒(¥0.12/秒);768p:1.4积分/秒(¥0.14/秒);1088p:1.4积分/秒(¥0.14/秒);1440p:1.5积分/秒(¥0.15/秒) ```text route_id: qr-v043 状态: 暂时不可用 价格: 480p:25积分/条(¥2.50/条);720p:25积分/条(¥2.50/条);1080p:25积分/条(¥2.50/条) 清晰度: 480p / 720p / 1080p 时长: 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17 / 18 / 19 / 20 / 21 / 22 / 23 / 24 / 25 / 26 / 27 / 28 / 29 / 30秒 画面比例: 21:9 / 16:9 / 4:3 / 1:1 / 3:4 / 9:16 task_mode: text / references / first_frame / first_last_frame 参考数量: 图片 0–10;视频 0–5;音频 0–5 提示词: 最多15000字符;必填非空描述 ``` ```text route_id: qr-v042 状态: 开放调用 价格: 720p:55积分/条(¥5.50/条);1080p:70积分/条(¥7.00/条) 清晰度: 720p / 1080p 时长: 固定30秒 画面比例: 16:9 / 9:16 / 1:1 / 4:3 / 3:4 / 21:9 task_mode: text / references 参考数量: 图片 0–10;视频 0–0;音频 0–0 提示词: 最多15000字符;必填非空描述 ``` ```text route_id: qr-v040 状态: 开放调用 价格: 30积分/条(¥3.00/条) 清晰度: 480p 时长: 4 / 5 / 6 / 7 / 8 / 9 / 10 / 11 / 12 / 13 / 14 / 15秒 画面比例: 16:9 / 9:16 / 1:1 / 4:3 / 3:4 task_mode: text / references 参考数量: 图片 0–9;视频 0–3;音频 0–3 提示词: 最多15000字符;必填非空描述 ``` ```text route_id: qr-v035 状态: 开放调用 价格: 15积分/条(¥1.50/条) 清晰度: 720p 时长: 固定10秒 画面比例: 16:9 / 9:16 / 1:1 / 4:3 / 3:4 task_mode: text / references 参考数量: 图片 0–9;视频 0–0;音频 0–0 提示词: 最多15000字符;必填非空描述 ``` ```text route_id: qr-v036 状态: 开放调用 价格: 25积分/条(¥2.50/条) 清晰度: 720p 时长: 5 / 10 / 15秒 画面比例: 16:9 / 9:16 task_mode: text / references 参考数量: 图片 0–9;视频 0–0;音频 0–0 提示词: 最多15000字符;必填非空描述 ``` ```text route_id: qr-v037 状态: 开放调用 价格: 39积分/条(¥3.90/条) 清晰度: 720p 时长: 4 / 5 / 6 / 7 / 8 / 9 / 10 / 11 / 12 / 13 / 14 / 15秒 画面比例: 16:9 / 9:16 / 1:1 / 4:3 / 3:4 task_mode: text / references 参考数量: 图片 0–9;视频 0–9;音频 0–9 提示词: 最多15000字符;必填非空描述 ``` ```text route_id: qr-v038 状态: 开放调用 价格: 480p:0.8积分/秒(¥0.08/秒);720p:0.9积分/秒(¥0.09/秒) 清晰度: 480p / 720p 时长: 4–30秒整数 画面比例: 16:9 / 9:16 task_mode: text / references 参考数量: 图片 0–9;视频 0–1;音频 0–3 提示词: 最多15000字符;必填非空描述 ``` ```text route_id: qr-v007 状态: 开放调用 价格: 480p:3.5积分/秒(¥0.35/秒) 清晰度: 480p 时长: 4–30秒整数 画面比例: 21:9 / 16:9 / 4:3 / 1:1 / 3:4 / 9:16 task_mode: text / first_frame / first_last_frame / references 参考数量: 图片 0–30;视频 0–10;音频 0–10 提示词: 最多15000字符;必填非空描述 ``` ```text route_id: qr-v012 状态: 开放调用 价格: 720p:4.5积分/秒(¥0.45/秒) 清晰度: 720p 时长: 4–30秒整数 画面比例: 16:9 / 9:16 / 4:3 / 3:4 / 1:1 task_mode: text / references 参考数量: 图片 0–30;视频 0–0;音频 0–10;参考音频总时长≤15秒;音频须配图 提示词: 最多10000字符;必填非空描述 ``` ```text route_id: qr-v018 状态: 开放调用 价格: 720p:2积分/秒(¥0.20/秒) 清晰度: 720p 时长: 4–15秒整数 画面比例: 9:16 task_mode: text / first_frame / first_last_frame / references 参考数量: 图片 0–9;视频 0–3;音频 0–3 提示词: 最多15000字符;必填非空描述 ``` ```text route_id: qr-v019 状态: 开放调用 价格: 720p:1积分/秒(¥0.10/秒) 清晰度: 720p 时长: 4–15秒整数 画面比例: 9:16 task_mode: references 参考数量: 图片 0–9;视频 0–3;音频 0–3 提示词: 最多15000字符;必填非空描述 ``` ```text route_id: qr-v020 状态: 开放调用 价格: 720p:1.5积分/秒(¥0.15/秒) 清晰度: 720p 时长: 4–15秒整数 画面比例: 9:16 task_mode: references 参考数量: 图片 0–9;视频 0–3;音频 0–3 提示词: 最多15000字符;必填非空描述 ``` ```text route_id: qr-v024 状态: 开放调用 价格: 480p:0.4积分/秒(¥0.04/秒);768p:0.9积分/秒(¥0.09/秒);1080p:1.3积分/秒(¥0.13/秒) 清晰度: 480p / 768p / 1080p 时长: 480p:1–15秒整数;768p:1–15秒整数;1080p:1–10秒整数 画面比例: 16:9 / 9:16 / 1:1 task_mode: references 参考数量: 图片 1–9;视频 0–0;音频 0–0 提示词: 最多8000字符;必填非空描述 ``` ```text route_id: qr-v025 状态: 开放调用 价格: 480p:0.7积分/秒(¥0.07/秒);768p:0.8积分/秒(¥0.08/秒) 清晰度: 480p / 768p 时长: 480p:1–15秒整数;768p:1–15秒整数 画面比例: 16:9 / 9:16 / 1:1 task_mode: text 参考数量: 图片 0–0;视频 0–0;音频 0–0 提示词: 最多8000字符;必填非空描述 ``` ```text route_id: qr-v026 状态: 开放调用 价格: 480p:0.8积分/秒(¥0.08/秒);768p:1积分/秒(¥0.10/秒) 清晰度: 480p / 768p 时长: 480p:1–15秒整数;768p:1–15秒整数 画面比例: 16:9 / 9:16 / 1:1 task_mode: first_last_frame 参考数量: 图片 2–2;视频 0–0;音频 0–0 提示词: 最多8000字符;必填非空描述 ``` ```text route_id: qr-v027 状态: 开放调用 价格: 480p:1积分/秒(¥0.10/秒);768p:1.2积分/秒(¥0.12/秒) 清晰度: 480p / 768p 时长: 480p:1–15秒整数;768p:1–15秒整数 画面比例: 16:9 / 9:16 / 1:1 task_mode: references 参考数量: 图片 1–9;视频 0–0;音频 0–3 提示词: 最多8000字符;必填非空描述 ``` ```text route_id: qr-v028 状态: 开放调用 价格: 480p:1.1积分/秒(¥0.11/秒);768p:1.2积分/秒(¥0.12/秒);1080p:1.4积分/秒(¥0.14/秒) 清晰度: 480p / 768p / 1080p 时长: 480p:1–15秒整数;768p:1–15秒整数;1080p:1–15秒整数 画面比例: 16:9 / 9:16 task_mode: first_frame 参考数量: 图片 1–1;视频 0–0;音频 1–1 提示词: 最多8000字符;可传空字符串;duration用于音频驱动的生成时长 ``` ```text route_id: qr-v032 状态: 开放调用 价格: 480p:1.2积分/秒(¥0.12/秒);768p:1.4积分/秒(¥0.14/秒);1088p:1.4积分/秒(¥0.14/秒);1440p:1.5积分/秒(¥0.15/秒) 清晰度: 480p / 768p / 1088p / 1440p 时长: 480p:1–15秒整数;768p:1–15秒整数;1088p:1–15秒整数;1440p:1–15秒整数 画面比例: 16:9 / 9:16 task_mode: references 参考数量: 图片 1–6;视频 0–0;音频 1–3 提示词: 最多8000字符;必填非空描述 ``` ## API素材直传(推荐) POST https://qorastudio.cn/api/v1/assets/direct 适用于后端API客户:先用Qora Bearer密钥取得单个文件的短期授权,文件正文直接上传至本站自有OSS,最后回到本站确认。图片不再经过本站服务器中转;生成时仍使用本站素材编号,其他模型和计费规则不变。旧POST /assets继续兼容。不得把本站密钥放进客户端网页或转发到存储域名。 ```json { "action": "authorize", "source": "当前文件内容的SHA256小写十六进制", "size": 1852422, "type": "image/png" } ``` 返回status=uploading时,使用host作为POST目标,将fields中全部字段原样加入multipart/form-data,最后添加file字段(原始文件、真实Content-Type);不要自行设置multipart的Content-Type边界,不要把本站Bearer密钥带到host。授权只允许本账号的一个对象、声明格式和精确字节大小,约15分钟有效。返回status=ready时是同账号相同内容复用,直接使用id,无需再上传。 ```json { "action": "complete", "id": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" } ``` 只有确认响应status=ready才代表本站素材已核验可用。本站核验对象大小、类型、图片文件头和完整SHA-256;上传成功时间、到期时间以响应uploaded_at/expires_at为准。相同内容复用、确认重试和跨设备读取均不延长72小时。确认响应丢失时用同一id重试complete;不要立即整文件重传。若POST未成功且文件不存在,重新authorize原source/size/type后重传整文件。 ```javascript // Node.js 18+:只直传图片,不创建视频,不扣生成积分。 // 设置 QORA_API_KEY、QORA_REFERENCE_FILE,保存为 qora-upload.mjs 后运行。 import fs from 'node:fs/promises'; import path from 'node:path'; import {createHash} from 'node:crypto'; const key=process.env.QORA_API_KEY,file=process.env.QORA_REFERENCE_FILE; if(!key||!file)throw Error('请设置QORA_API_KEY和QORA_REFERENCE_FILE'); const bytes=await fs.readFile(file),type=({'.png':'image/png','.jpg':'image/jpeg','.jpeg':'image/jpeg','.webp':'image/webp'})[path.extname(file).toLowerCase()]; if(!type)throw Error('请使用PNG、JPG或WebP图片'); async function uploadReference(bytes,type,filename){ async function control(body){ for(let attempt=0;;attempt++){ let r; try{r=await fetch('https://qorastudio.cn/api/v1/assets/direct',{method:'POST',redirect:'error',headers:{Authorization:'Bearer '+key,'Content-Type':'application/json'},body:JSON.stringify(body),signal:AbortSignal.timeout(120000)});}catch(error){if(attempt>=2)throw error;await new Promise(r=>setTimeout(r,1000*(attempt+1)));continue;} const d=await r.json();if(r.ok)return d; const retry=[408,429,500,502,503,504].includes(r.status)||r.status===409&&['upload_unconfirmed','upload_in_progress'].includes(d.error?.code); if(!retry||attempt>=2)throw Error(d.error?.message||'上传控制请求未完成'); await new Promise(resolve=>setTimeout(resolve,Math.max(1,Math.min(30,Number(r.headers.get('Retry-After'))||2))*1000)); } } const authorized=await control({action:'authorize',source:createHash('sha256').update(bytes).digest('hex'),size:bytes.length,type}); let ready=authorized; if(authorized.status!=='ready'){ const host=new URL(authorized.host); if(authorized.status!=='uploading'||authorized.upload_mode!=='post_form'||host.origin!=='https://qorastudio.oss-cn-hongkong.aliyuncs.com'||host.username||host.password||host.pathname!=='/'||host.search||host.hash||!authorized.fields)throw Error('直传授权响应异常'); const form=new FormData();for(const [name,value]of Object.entries(authorized.fields))form.append(name,value); form.append('file',new Blob([bytes],{type}),path.basename(filename)); // 文件正文只发到本站OSS;这里不能携带Qora Bearer密钥。 try{const uploaded=await fetch(host,{method:'POST',redirect:'error',body:form,signal:AbortSignal.timeout(600000)});await uploaded.body?.cancel();}catch{} // 上传响应丢失也先确认同一id,避免重复发送整份文件。 try{ready=await control({action:'complete',id:authorized.id});}catch(error){throw Error('素材编号 '+authorized.id+' 尚未确认,请保留编号并重试complete;'+error.message);} } if(ready.status!=='ready'||ready.id!==authorized.id||ready.expired||ready.expires_at!=null&&ready.expires_at<=Date.now())throw Error('素材尚未可用,不能提交生成'); return ready; } const ready=await uploadReference(bytes,type,file); console.log(JSON.stringify(ready,null,2)); // 后续references只使用ready.id;同账号同文件再次authorize会复用未过期素材。 ``` 数量及格式仍按所选模型限制。存储入口图片PNG/JPEG/WebP、视频MP4/WebM单文件最多100MiB,音频MP3/WAV最多20MiB;模型可能更严格。401核对本站Key,409检查文件是否尚未传完或仍有旧上传连接,422修改文件格式/摘要/大小问题后重试。不能把authorize成功、POST开始或素材上传中显示为“视频提交成功”;生成请求受理并拿到本站任务号之后才显示已提交。文件大小本身不要求先压缩,不通过有损缩图来掩盖网络慢的问题。客户端同时上传建议1–3份;旧客户端必须调整上传代码才能采用直传,本站不能替它改变本地网络请求。 ## 参考素材上传 POST https://qorastudio.cn/api/v1/assets 这是兼容中转入口;大文件或慢网络建议使用上一节POST /assets/direct。不要设置45秒整请求总超时;仍应保留合理的连接和连续无数据超时。请求体是文件原始二进制,不是JSON或multipart。先上传,再把返回id填入references。本上传接口不能直接传电脑路径、localhost、网盘页面、外部素材URL或其他账号的素材ID。qr-v042另支持在报价/生成JSON的images字段中直接提供公网图片链接,详见骨折版满血10图章节。 格式 | Content-Type | 单文件存储上限 --- | --- | --- PNG / JPEG / WebP | image/png / image/jpeg / image/webp | 100 MiB(104857600字节) MP4 / WebM | video/mp4 / video/webm | 100 MiB;所选模型可能更严格 MP3 / WAV | audio/mpeg / audio/wav | 20 MiB(20971520字节) 文件头会校验真实类型,PNG/JPEG/WebP均支持。macOS与Windows使用相同接口;HEIC/HEIF/AVIF请先导出为PNG/JPEG/WebP,不要只改扩展名。上传响应type表示保存后的真实类型。每账号最多500个素材、保存空间上限5GiB,平台总空间另有限制。X-Qora-Source须由当前文件内容计算;不要给不同文件复用同一摘要。同账号相同摘要会复用已有素材。 ```text # PowerShell (Get-FileHash -LiteralPath .\reference.png -Algorithm SHA256).Hash.ToLower() # macOS / Linux shasum -a 256 reference.png ``` ```bash curl 'https://qorastudio.cn/api/v1/assets' \ -H 'Authorization: Bearer YOUR_QORA_API_KEY' \ -H 'Content-Type: image/png' \ -H 'X-Qora-Source: FILE_SHA256' \ --data-binary @reference.png ``` ```json { "id": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", "type": "image/png" } ``` 上传成功只代表素材保存成功,不代表所有模型都允许使用它。图片、视频、音频数量和组合仍按所选模型校验。 ## 生成请求参数与参考角色 JSON字段 | 类型 / 默认值 | 必填 | 说明 --- | --- | --- | --- prompt | string | 是 | 普通方案必须非空;prompt_required=false时可传空字符串,但字段仍须存在 route_id | string / qr-v007 | 否 | 使用模型列表中的id;Mini按条方案请显式传qr-v021 duration | integer / 4 | 否 | 视频秒数,通用范围1–30,实际须符合所选方案。Mini按条仅5/10/15 resolution | string / 按方案 | 否 | 骨折官方480p和特惠官方480p(稳定版)默认480p,其他方案保留默认720p;仅可使用所选模型返回的清晰度 ratio | string / 16:9 | 否 | 候选21:9、16:9、4:3、1:1、3:4、9:16;按模型限制 task_mode | string / text | 否 | text、first_frame、first_last_frame、references,须在模型modes中 images | string[] / 省略 | 否 | 仅qr-v042支持,1–10个HTTPS图片直链,单图最多30MB;与references互斥,默认使用references生成模式 references | array / 省略 | 否 | 最多50个对象,模型上限可能更低;每项仅含id和role,不可重复素材ID task_mode | 用途 | references要求 --- | --- | --- text | 文生视频 | 省略或空数组 first_frame | 首帧图生视频 | 普通Seedance:1张first_frame;H3声演:1张first_frame与1个reference_audio first_last_frame | 首尾帧 | 按顺序提供first_frame、last_frame两张图片 references | 全能参考 | 使用reference_image、reference_video、reference_audio;数量、组合和最小参考数按模型限制 references[].字段/角色 | 类型 / 含义 | 要求 --- | --- | --- id | string UUID | 本账号上传返回的素材id role | string | 必须和文件类型及task_mode相符 reference_image | 图片参考 | 用于references模式 reference_video | 视频参考 | 仅支持视频参考的方案可用 reference_audio | 音频参考 | 部分方案要求同时有图片或视频 first_frame | 首帧图片 | 用于首帧或首尾帧模式 last_frame | 尾帧图片 | 用于首尾帧模式,排在首帧之后 ```json { "route_id": "qr-v007", "prompt": "纸船缓缓漂过水面,镜头保持平稳。", "duration": 4, "resolution": "480p", "ratio": "16:9", "task_mode": "text" } ``` ```json { "route_id": "qr-v021", "prompt": "参考图中的小船缓缓驶过石桥,水面自然泛起涟漪。", "duration": 15, "resolution": "720p", "ratio": "16:9", "task_mode": "references", "references": [ { "id": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", "role": "reference_image" } ] } ``` ```json { "route_id": "qr-v028", "prompt": "", "duration": 5, "resolution": "480p", "ratio": "16:9", "task_mode": "first_frame", "references": [ { "id": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", "role": "first_frame" }, { "id": "cccccccc-cccc-4ccc-8ccc-cccccccccccc", "role": "reference_audio" } ] } ``` 请求对象和references子对象采用严格字段校验。不要套用其他平台的model、modelVersion、imageUrls、videoUrls、audioUrls、size等字段;当前也不接受generate_audio开关或自定义Webhook。 ## 图片、视频、音频编号与示例 以下@编号示例用于支持相应参考类型的Seedance全能参考方案。API不会读取网页或画布中的素材选择,使用素材编号时必须先上传文件,再显式传入references;qr-v042也可以使用images直链数组,按数组顺序引用参考图1、参考图2;只在prompt写@音频1而不上传、不传reference_audio,不会附带音频。 按图片、视频、音频分组组织references,同类素材保持固定顺序。每类独立从1编号:图片为@图1、@图2;视频为@视频1、@视频2;音频为@音频1、@音频2。编号对应请求中该类素材的顺序,不是文件名或UUID。调整顺序、删除素材后须同时修改提示词;不能引用不存在的编号。 ```json { "route_id": "qr-v007", "prompt": "人物参考@图1,动作参考@视频1,声音参考@音频1。人物面向镜头自然说话。", "duration": 4, "resolution": "480p", "ratio": "16:9", "task_mode": "references", "references": [ { "id": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", "role": "reference_image" }, { "id": "cccccccc-cccc-4ccc-8ccc-cccccccccccc", "role": "reference_video" }, { "id": "dddddddd-dddd-4ddd-8ddd-dddddddddddd", "role": "reference_audio" } ] } ``` 素材能力按route_id区分,不能只看“Seedance 2.5”这个名称。qr-v007为特惠官方480p(稳定版),4–30秒,同样支持30图/10视频/10音频,提示词最多15000字;本站图片JPG/PNG/WebP每张最多20MiB、MP4视频每个最多100MiB、MP3/WAV音频每个最多15MiB;视频和音频每段1.8–30秒,两类各自合计最多30秒;使用参考视频须先报价并传max_price_credits确认。上传成功不代表当前方案允许使用这种参考类型。 这些UUID仅用于展示结构,须替换成本账号实际上传得到的id。不同任务用不同Idempotency-Key;同一订单报价、提交和重试须复用原订单号、原素材id与完全相同的参数。H3按对应方案的参考角色和能力接入,不直接套用Seedance的提示词格式。 ## 万相3.0 · 按条版 本站编号qr-v043,480p、720p、1080p均为每条25积分(¥2.50),2–30秒整数时长;参考图片、视频、音频不另外加价。批量排队处理,等待时间不固定;没有真实进度时返回null。请保存本站任务编号查询,不要重复提交。 支持文生、全能参考、首帧和首尾帧;首尾帧不能和全能参考混用。最多10张图片、5段视频、5段音频。图片单张20MB、每边240–8000px、长短边不超过8:1,PNG不能含透明通道;视频单段100MB、每段1–15秒且合计不超过15秒,每边240–4096px、帧率至少16fps;音频单段15MB、每段1–15秒且合计不超过15秒。本站目前接入JPG/PNG/WebP、MP4、MP3/WAV,BMP/MOV请先转换。 素材须先上传本账号且仍有效;不接受外部URL、卡密、其他账号的素材或任务编号。报价不扣积分,正式受理时预扣25积分;失败仅退回本任务实际扣分一次。成片保存到本站后才提供预览和下载,新OSS文件以实际上传成功时间起保存72小时。 ```json { "route_id": "qr-v043", "prompt": "参考@视频1的动作节奏,镜头平稳推进。", "duration": 10, "resolution": "720p", "ratio": "16:9", "task_mode": "references", "references": [ { "id": "cccccccc-cccc-4ccc-8ccc-cccccccccccc", "role": "reference_video" } ] } ``` ## 查询本次报价 POST https://qorastudio.cn/api/v1/video/quotes 此步骤可选:可直接POST /video/generations,服务端会核价。需要预先确认预算时再调用本接口。请求JSON与生成接口相同,Idempotency-Key必填。报价请求会快速返回草稿;status=estimating、quote_ready=false表示后台正在准备素材和核验费用,不进入生成队列、不扣积分。按retry_after_seconds使用相同订单号和参数再次查询,直到quote_ready=true;关闭页面也不会自动提交生成。报价最长有效60秒,quote_ready=false时不要当作可生成或免费生成。 ```bash curl 'https://qorastudio.cn/api/v1/video/quotes' \ -H 'Authorization: Bearer YOUR_QORA_API_KEY' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: your-order-001' \ --data '{"route_id":"qr-v021","prompt":"参考图中的小船缓缓驶过石桥,水面自然泛起涟漪。","duration":15,"resolution":"720p","ratio":"16:9","task_mode":"references","references":[{"id":"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb","role":"reference_image"}]}' ``` ```json { "data": { "id": "aaaaaaaa-aaaa-5aaa-8aaa-aaaaaaaaaaaa", "model": "qr-v021", "status": "quoted", "progress": null, "price_credits": 15, "duration": 15, "resolution": "720p", "ratio": "16:9", "created_at": 1792324800000, "completed_at": null, "expires_at": null, "error": null, "download_url": null, "quote_ready": true, "quote_expires_at": 1792324860000 } } ``` 报价响应字段 | 含义 --- | --- data | 报价任务对象;注意此接口有data包装 data.id | 本站任务UUID,后续查询使用此值 data.price_credits | 本次整条视频的积分价格,不是每秒单价 data.quote_ready | true才代表报价已就绪;已有进行中/完成任务时也可能为false data.quote_expires_at | 毫秒时间戳;到期需重新核价 data.error | 错误说明或null;不能只凭HTTP200判断可生成 稳定版480p无参考视频时每秒3.5积分(¥0.35);含参考视频须先核对完整报价并用max_price_credits确认上限。满血10图按30秒整条计费,720p为55积分,1080p为70积分;原生720无参考视频为4.5积分/秒(¥0.45),含参考视频的价格以完整报价为准。所有提交均遵守调用方提供的max_price_credits上限。 报价与后续生成应使用同一订单号、完全相同的参数。过期报价在提交时会重新核价;报价本身不锁定无限期价格。 ## 提交视频生成任务 POST https://qorastudio.cn/api/v1/video/generations 支持直接提交,无需先查报价。若已查报价,仍使用相同Idempotency-Key与相同请求参数提交。报价接口只生成草稿,不会自动转为生成任务。 ```bash curl 'https://qorastudio.cn/api/v1/video/generations' \ -H 'Authorization: Bearer YOUR_QORA_API_KEY' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: your-order-001' \ --data '{"route_id":"qr-v021","prompt":"参考图中的小船缓缓驶过石桥,水面自然泛起涟漪。","duration":15,"resolution":"720p","ratio":"16:9","task_mode":"references","references":[{"id":"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb","role":"reference_image"}]}' ``` ```json { "id": "aaaaaaaa-aaaa-5aaa-8aaa-aaaaaaaaaaaa", "model": "qr-v021", "status": "queued", "progress": null, "price_credits": 15, "duration": 15, "resolution": "720p", "ratio": "16:9", "created_at": 1792324800000, "completed_at": null, "expires_at": null, "error": null, "download_url": null } ``` 请立即保存id。queued表示已入队,202不代表视频已生成。后台会自动处理和保存成品;查询接口不需要替用户触发生成。余额不足返回402。 同账号+同Idempotency-Key+相同参数重试,复用原任务,不重复预扣。相同订单号改参数会返回409。不同任务必须使用不同订单号;网络超时后保留原订单与参数,不要换新订单盲目重发。 同订单报价仍在处理时,提交生成会返回429和Retry-After;此时尚未入队、未扣积分。等待后用原订单、原参数重试原提交。quoted也只表示草稿,不能仅轮询草稿而从未提交。失败或过期任务不会因同订单重试自动成为新任务。 ## 查询单个任务与任务列表 GET https://qorastudio.cn/api/v1/video/generations/{id} 路径参数 | 类型 | 说明 --- | --- | --- id | UUID字符串 | 使用提交或报价返回的本站任务id,不是订单号或模型id ```bash curl 'https://qorastudio.cn/api/v1/video/generations/aaaaaaaa-aaaa-5aaa-8aaa-aaaaaaaaaaaa' \ -H 'Authorization: Bearer YOUR_QORA_API_KEY' ``` ```json { "data": { "id": "aaaaaaaa-aaaa-5aaa-8aaa-aaaaaaaaaaaa", "model": "qr-v021", "status": "completed", "progress": 100, "price_credits": 15, "duration": 15, "resolution": "720p", "ratio": "16:9", "created_at": 1792324800000, "completed_at": 1792325160000, "expires_at": 1792584360000, "error": null, "download_url": "/api/v1/video/generations/aaaaaaaa-aaaa-5aaa-8aaa-aaaaaaaaaaaa/content" } } ``` ```bash curl 'https://qorastudio.cn/api/v1/video/generations' \ -H 'Authorization: Bearer YOUR_QORA_API_KEY' ``` ```json { "data": [ { "id": "aaaaaaaa-aaaa-5aaa-8aaa-aaaaaaaaaaaa", "model": "qr-v021", "status": "queued", "progress": null, "price_credits": 15, "duration": 15, "resolution": "720p", "ratio": "16:9", "created_at": 1792324800000, "completed_at": null, "expires_at": null, "error": null, "download_url": null } ] } ``` 任务字段 | 类型 | 说明 --- | --- | --- id / model | string | 本站任务UUID / 调用方案ID status | string | 任务状态,见下表;HTTP200不代表成功完成 progress | number | null | 百分比;null表示该任务未提供进度 price_credits | number | 该任务记录的整条售价(积分) duration / resolution / ratio | integer / string / string | 本次生成参数 created_at | integer | 创建时间,Unix毫秒 completed_at / expires_at | integer | null | 完成/文件到期时间,Unix毫秒 error | object | null | code与message;进行中也可能出现临时整理错误,不等于最终失败 download_url | string | null | 新视频返回公开 OSS 下载地址,无需密钥;旧文件可能返回需鉴权的本站相对路径 建议每30秒查询一次;批量任务优先查询列表,避免所有任务逐条高频轮询。404表示任务不存在或不属于密钥所属账号。更换同一账号下的另一把有效Key,也可以继续查询该账号已有任务。 ## 状态判断、扣费与重试 status | 含义 | 调用方处理 --- | --- | --- estimating | 正在估价 | 保留订单与参数,稍后重试原提交;未入队 quoted | 已形成报价草稿 | 确认报价后提交生成;草稿本身不会自动生成 queued | 已入队等待处理 | 继续查询;已预扣积分 preparing | 准备任务或参考素材 | 继续查询 dispatching | 正在发送生成请求 | 继续查询,不创建新订单 submitted / polling | 已提交生成 / 正在查询 | 继续查询 downloading | 成品正在整理保存 | 继续查询;即使progress=100也不要重生成 delivery_blocked | 成片超过250MiB自动接收上限 | 停止轮询,联系站长单独领取;原任务保留,不自动退款,不重复生成 uncertain | 提交结果仍在核对 | 保留任务号联系平台;不要换订单重复生成 completed | 成品已保存 | 使用download_url下载 failed | 已确认失败 | 停止轮询;任务失败的已扣积分自动退回账户 expired | 成品保存期已结束 | 下载返回410,不会自动重新生成 积分规则:1元=10积分。billing=second按“所选清晰度积分单价×秒数”计算;billing=generation按条计费。Mini按条15积分,5/10/15秒同价。参考视频是否影响费用以当前方案说明为准;报价返回本次完整费用。最终生成请求应以price_credits为准。 报价不扣积分,正式入队时预扣;相同订单不重复扣,余额不足不入队。退款是退回站内积分。生成失败与结果尚未确认不同,不会仅因等待较长就盲目重发或退款。撤销Key不取消已经入队的任务。 ## 下载生成成品与断点续传 GET https://qorastudio.cn/api/v1/video/generations/{id}/content 仅在completed后下载。直接请求任务返回的 download_url。公开 OSS 地址无需密钥;仅旧版本站路径携带同账号 Bearer 密钥。支持307跳转至本站自有存储;客户端需跟随跳转,但不能把Authorization转发给其他域名。不要长期保存最终临时签名地址。 ```bash curl -fL -C - --connect-timeout 20 --max-time 600 \ --retry 8 --retry-delay 5 --retry-max-time 1800 --retry-all-errors \ 'https://qorastudio.cn/api/v1/video/generations/aaaaaaaa-aaaa-5aaa-8aaa-aaaaaaaaaaaa/content' \ -H 'Authorization: Bearer YOUR_QORA_API_KEY' \ -o qora-video.mp4.part ``` 使用较新版curl;Windows PowerShell请用curl.exe。保留.part文件,再运行同一命令即可续传;确认命令成功结束后再重命名为.mp4或.webm。不要使用--location-trusted。此命令仅下载已有成片,不提交生成、不扣生成积分。 HTTP状态/响应头 | 处理方式 --- | --- 200 | 完整文件;若本地已有部分内容,须清空临时文件后重新写入,不能直接追加 206 + Content-Range | 续传成功;起始字节必须等于本地已保存长度,总长度须一致 307 | 跟随本站自有存储跳转;跨域不转发本站密钥 416 | 先核对本地长度是否等于完整长度;不能把错误响应追加到视频 409 | 尚未完成,继续查询原任务 410 | 文件已过期,停止重试;以expires_at为准 404 / 401 | 核对任务归属或密钥,不盲目重试 429 / 5xx / 连接中断 | 保留已有字节,按Retry-After或退避重试原下载地址 自建客户端:连接超时建议20秒,连续无数据超时建议90秒,单次总时限至少10分钟;不要将生成查询的短超时套用到整个文件下载。先从2个并行下载开始,按实测带宽调整。保存临时文件与已下载长度;下一次发送Range: bytes=N-,有强ETag时配合If-Range,并核对206、Content-Range、Content-Length与ETag。遇到200或文件标识变化时重新下载,不能拼接不同版本。大文件按块写磁盘,不要一次性读入内存。 新OSS文件保留72小时,旧文件沿用原规则,以expires_at为准。下载速度受双方网络影响;超时并不表示视频生成失败。下载失败只重试原任务下载,严禁因此重新提交生成。保存前校验HTTP状态、Content-Type、完整长度及视频文件头,不能把JSON/HTML错误页当视频。Node/Python简例展示基础流程,生产批量接入应补齐本节的持久化续传和退避。 ## 满血480p按条方案 本站编号qr-v040,4–15秒,每条30积分(¥3.00)。支持文生视频或参考素材,实际规格以当前模型清单为准。 ## 骨折2.5:图片素材接入 默认推荐:先按API素材直传步骤将图片传至本站OSS,确认status=ready后,把返回id填入references;最多10张,顺序对应参考图1、参考图2。此方式省去本站从外部图床反复取图的步骤。生成方案仍可能需要后端素材转存,不能保证所有准备都瞬间完成。 ```json { "route_id": "qr-v042", "prompt": "参考图1作为人物参考,镜头平稳推进。", "duration": 30, "resolution": "720p", "ratio": "16:9", "task_mode": "references", "references": [ { "id": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", "role": "reference_image" } ] } ``` 兼容旧接法:以下images结构仍支持已有客户。外部图床的速度和稳定性会影响整图读取及准备时间。 填写你有权使用的公网图片直链;私有OSS请使用有效签名链接。最多10张、单图30MB、PNG/JPEG/WebP。不能与references混用;省略task_mode时自动使用references模式。两个接口均须携带自己的Qora Key和同一个订单的Idempotency-Key;不要在请求中使用任何其他服务的密钥。 ```json { "route_id": "qr-v042", "prompt": "参考图1作为人物参考,镜头平稳推进。", "duration": 30, "resolution": "720p", "ratio": "16:9", "images": [ "https://your-bucket.oss-cn-hongkong.aliyuncs.com/reference.png" ] } ``` ## 骨折版满血10图 本站编号qr-v042。按条计费:720p为55积分(¥5.50),1080p为70积分(¥7.00);固定30秒。画幅支持16:9、9:16、1:1、4:3、3:4、21:9,所选ratio按原值提交;实际成片尺寸以文件为准。支持纯文生或最多10张参考图片,不支持参考音频、视频。本站兼容JPG/PNG/WebP、单图最多30MB,提示词本站上限15000字。图片尺寸与宽高比未公布的范围不套用其他模型。默认使用本账号OSS直传并确认后的有效素材编号;旧接法也兼容通过images传公网HTTPS图片直链(包括有效的私有OSS签名链接);两种方式不能混用。images最多10张,每个URL最多2048字符,不能依赖登录、Cookie、Referer或跳转;链接须保持有效直至生成完成。本站检查访问权限、文件长度、声明格式及图片文件头,整图下载仍可能受网络影响。按references或images中图片顺序用@图1、@图2或参考图1、参考图2引用;未绑定的@名称会在提交前拦截。原片可能为H.265,部分浏览器需下载后使用兼容播放器播放。 请明确填写duration与resolution,先核对本次报价再提交。images方式在 /video/quotes 和 /video/generations 中均适用,使用相同Idempotency-Key和完全相同的URL数组重试,不要改变数组顺序。查询仅返回本站任务编号和规范化失败原因;进度无真实依据时返回null。成片保存至本站后才提供预览和下载。任务失败退回本任务实际扣除的积分,重复查询或重试不会重复扣退积分。 ## Fast短片、满血按条2.0与H3长视频 四个新方案均使用本站编号,可用于文生视频或全能参考;仅使用本账号上传的有效素材。生成前检查价格与素材要求,失败原因由本站解释,任务编号和下载内容均由本站交付。 本站编号 | 方案 | 规格 | 售价 | 参考上限:图/视频/音频 --- | --- | --- | --- | --- qr-v035 | Seedance 2.0 Fast · 短片特惠 | 720p,固定10秒 | 每条15积分(¥1.50) | 9/0/0 qr-v036 | Seedance 2.0 Fast · 按条特惠 | 720p,5/10/15秒 | 每条25积分(¥2.50) | 9/0/0 qr-v037 | Seedance 2.0 · 满血按条2.0 | 720p,4–15秒整数 | 每条39积分(¥3.90) | 9/9/9 qr-v038 | H3 · 长视频全能参考 | 480p/720p,4–30秒整数 | 480p每秒0.8积分;720p每秒0.9积分 | 9/1/3 Fast短片支持16:9、9:16、1:1、4:3、3:4;Fast按条仅16:9、9:16。两条Fast只接受图片,单张本站限制20MiB、最多9张,提示词本站上限15000字;Fast按条的20MiB为本站保守兼容上限。图片尺寸和宽高比的未公布边界不套用其他方案。 满血按条2.0支持16:9、9:16、1:1、4:3、3:4;图片单张20MiB、视频仅MP4且本站限制100MiB、音频MP3/WAV单段15MiB,素材总数最多27份。未公布的参考时长边界不作虚构限制。 H3长视频仅16:9、9:16,不开放1080p;图片单张30MiB、视频仅MP4且本站限制100MiB、参考视频最长15秒,音频MP3/WAV单段15MiB且本站兼容限制合计15秒。按成片duration计费,参考视频不加价;30秒480p为24积分(¥2.40),720p为27积分(¥2.70)。模型列表及素材要求提供时长边界,报价和任务pricing给出本次单价与成片秒数。 ```json { "route_id": "qr-v038", "prompt": "纸船缓缓漂过水面,镜头保持平稳。", "duration": 30, "resolution": "720p", "ratio": "16:9", "task_mode": "text" } ``` ## 错误码、频率与容量限制 查询任务时,error.reference_errors 在能准确对应素材时提供:kind 为素材类型,index 为该类型从1开始的编号,reference_id 为本站素材ID,message 为问题说明,suggestion 为修改建议。不会猜测具体敏感区域或违规句子。无法对应时仅返回已确认的问题类型,不随意指认素材。error.message 是本站失败说明;reason_code 是本站原因分类,suggestion 是处理建议,specific 表示是否有已确认的具体原因,problem_id 为本站问题编号。原有 error.code 保持兼容。specific=false 时不要猜测失败原因,请携带本站任务编号和问题编号联系 Qora 客服。结果核对中或成片接收中请继续查询原任务,不要重复提交;退款金额以积分流水为准。 ```json { "error": { "code": "insufficient_credits", "message": "积分余额不足,请先兑换卡密" } } ``` HTTP | error.code | 说明与处理 --- | --- | --- 400 | invalid_request | 参数、JSON、模式或规格组合无效;JSON请求体最多64000字节 400 | invalid_idempotency_key | 缺失或不合法的订单号 401 | invalid_api_key | 密钥缺失、无效或已撤销 402 | insufficient_credits | 积分余额不足 404 | not_found | 任务或成品不存在/不属于本账号 409 | idempotency_conflict | 同订单号修改了参数 409 | video_unavailable / generation_unavailable | 方案暂停、参考素材或当前条件不可生成,读取message 409 | estimate_unavailable | 报价未就绪或过期,重查原订单报价 409 | not_ready | 成品还未保存完成 410 | content_expired | 文件保存期已结束 400 / 409 / 411 / 413 | upload_rejected | 素材格式、空间、长度或大小不符;411缺有效Content-Length 429 | capacity_wait | 本次尚未扣积分,按Retry-After等待后用原订单和相同参数重试 429 | rate_limit_exceeded | 请求过于频繁,降低频率 503 | service_unavailable / video_unavailable | 服务暂不可用,保留原订单/任务号稍后重试 限制 | 当前规则 --- | --- API Key | 每账号最多10把有效Key 请求频率 | 同账号所有Key共享每分钟60次;上传、报价、查询和下载均计入 视频排队 | 每账号最多100条待处理任务、最多30条同时运行;平台全局容量另有限制 任务列表 | 最多返回300条,无分页参数 文件保留 | 新OSS文件上传成功后72小时,以expires_at为准 参考素材 | 每账号最多500个文件,保存空间5GiB;模型规则另行校验 报价繁忙时,报价响应会返回quote_ready=false和retry_after_seconds,请等待后使用原订单号与相同参数重新查询。生成接口若返回429 capacity_wait,表示尚未扣积分,按Retry-After重试;收到202和queued后只查询原任务,系统会自动补位,不要反复提交。 429、5xx和网络超时:查询可稍后重试。提交只能保留原订单号和完全相同参数重试,不要换订单。HTTP200/202都必须结合status读取,error非空也须结合任务状态判断。 ## Node.js完整调用示例 Node.js 18+,不依赖第三方SDK。示例针对Mini按条方案,使用PNG参考图,报价不超过15积分时才提交。固定订单号用于防止重跑时重复扣费。不要把生产密钥写进源代码。 ```powershell $env:QORA_API_KEY='替换为自己的Key' $env:QORA_ORDER_ID='my-order-20261018-001' $env:QORA_REFERENCE_FILE='C:\素材\reference.png' node .\qora-mini.mjs # 已有任务续查时,只需Key和已保存的任务号,不再次生成 $env:QORA_JOB_ID='aaaaaaaa-aaaa-5aaa-8aaa-aaaaaaaaaaaa' node .\qora-mini.mjs ``` ```javascript // Node.js 18+,保存为 qora-mini.mjs。首次运行可能消耗15积分。 // 必填:QORA_API_KEY、QORA_ORDER_ID、QORA_REFERENCE_FILE(PNG)。 // 续查已有任务:只需 QORA_API_KEY、QORA_JOB_ID,不会再次提交生成。 import fs from 'node:fs/promises'; import path from 'node:path'; import {createHash} from 'node:crypto'; import {createWriteStream} from 'node:fs'; import {Readable} from 'node:stream'; import {pipeline} from 'node:stream/promises'; const base='https://qorastudio.cn/api/v1'; const key=process.env.QORA_API_KEY; if(!key)throw Error('请设置 QORA_API_KEY'); const auth={Authorization:'Bearer '+key}; const sleep=ms=>new Promise(resolve=>setTimeout(resolve,ms)); async function json(path,options={}){ for(let attempt=0;;attempt++){ const r=await fetch(base+path,{...options,headers:{...auth,...options.headers},signal:AbortSignal.timeout(90000)}); const d=await r.json(); if(r.status===429&&attempt<40){await sleep(Math.max(1,Math.min(60,Number(r.headers.get('Retry-After'))||15))*1000);continue;} if(!r.ok)throw Error(d.error?.message||'HTTP '+r.status); return d; } } async function uploadReference(bytes,type,filename){ async function control(body){ for(let attempt=0;;attempt++){ let r; try{r=await fetch('https://qorastudio.cn/api/v1/assets/direct',{method:'POST',redirect:'error',headers:{Authorization:'Bearer '+key,'Content-Type':'application/json'},body:JSON.stringify(body),signal:AbortSignal.timeout(120000)});}catch(error){if(attempt>=2)throw error;await new Promise(r=>setTimeout(r,1000*(attempt+1)));continue;} const d=await r.json();if(r.ok)return d; const retry=[408,429,500,502,503,504].includes(r.status)||r.status===409&&['upload_unconfirmed','upload_in_progress'].includes(d.error?.code); if(!retry||attempt>=2)throw Error(d.error?.message||'上传控制请求未完成'); await new Promise(resolve=>setTimeout(resolve,Math.max(1,Math.min(30,Number(r.headers.get('Retry-After'))||2))*1000)); } } const authorized=await control({action:'authorize',source:createHash('sha256').update(bytes).digest('hex'),size:bytes.length,type}); let ready=authorized; if(authorized.status!=='ready'){ const host=new URL(authorized.host); if(authorized.status!=='uploading'||authorized.upload_mode!=='post_form'||host.origin!=='https://qorastudio.oss-cn-hongkong.aliyuncs.com'||host.username||host.password||host.pathname!=='/'||host.search||host.hash||!authorized.fields)throw Error('直传授权响应异常'); const form=new FormData();for(const [name,value]of Object.entries(authorized.fields))form.append(name,value); form.append('file',new Blob([bytes],{type}),path.basename(filename)); // 文件正文只发到本站OSS;这里不能携带Qora Bearer密钥。 try{const uploaded=await fetch(host,{method:'POST',redirect:'error',body:form,signal:AbortSignal.timeout(600000)});await uploaded.body?.cancel();}catch{} // 上传响应丢失也先确认同一id,避免重复发送整份文件。 try{ready=await control({action:'complete',id:authorized.id});}catch(error){throw Error('素材编号 '+authorized.id+' 尚未确认,请保留编号并重试complete;'+error.message);} } if(ready.status!=='ready'||ready.id!==authorized.id||ready.expired||ready.expires_at!=null&&ready.expires_at<=Date.now())throw Error('素材尚未可用,不能提交生成'); return ready; } let id=process.env.QORA_JOB_ID; if(!id){ const order=process.env.QORA_ORDER_ID,filename=process.env.QORA_REFERENCE_FILE; if(!order||!filename)throw Error('首次生成须设置固定订单号和PNG参考图路径'); const bytes=await fs.readFile(filename); const asset=await uploadReference(bytes,'image/png',filename); const body={route_id:'qr-v021',prompt:'参考图中的小船缓缓驶过石桥,水面自然泛起涟漪。',duration:15,resolution:'720p',ratio:'16:9',task_mode:'references',references:[{id:asset.id,role:'reference_image'}]}; const options={method:'POST',headers:{'Content-Type':'application/json','Idempotency-Key':order},body:JSON.stringify(body)}; let {data:q}=await json('/video/quotes',options); const quoteDeadline=Date.now()+300000; for(;q.retry_after_seconds&&Date.now()15)throw Error('报价未就绪或超过本示例15积分预算,未提交'); const job=await json('/video/generations',options);id=job.id; }else{id=q.id;} await fs.writeFile('qora-job.json',JSON.stringify({id,order},null,2)); } if(!/^[0-9a-f-]{36}$/i.test(id))throw Error('任务号格式无效'); console.log('请保存任务号:'+id+';中断后可设置 QORA_JOB_ID 续查'); for(let attempt=0;attempt<120;attempt++){ let r; try{r=await fetch(base+'/video/generations/'+id,{headers:auth,signal:AbortSignal.timeout(90000)});}catch{await sleep(30000);continue;} if(r.status===408||r.status===429||r.status>=500){await sleep(30000);continue;} const d=await r.json();if(!r.ok)throw Error(JSON.stringify(d));const job=d.data; if(job.status==='failed'||job.status==='expired'||job.status==='delivery_blocked')throw Error(JSON.stringify(job.error||job)); if(job.status==='uncertain')throw Error('任务仍在核对,请保留任务号,不要更换订单重新生成'); if(job.status==='quoted'||job.status==='estimating')throw Error('尚未入队,请保留原订单号和参数,稍后重试原提交'); if(job.status==='completed'){ const expected='/api/v1/video/generations/'+id+'/content'; const direct=job.download_url?.startsWith('https://qorastudio.oss-cn-hongkong.aliyuncs.com/qora/'); if(!direct&&job.download_url!==expected)throw Error('下载地址异常'); const file=await fetch(direct?job.download_url:'https://qorastudio.cn'+expected,{headers:direct?{}:auth,signal:AbortSignal.timeout(1800000)}); if(!file.ok||!file.headers.get('content-type')?.startsWith('video/'))throw Error('下载未完成,请用同任务号续查,勿重复生成'); const extension=file.headers.get('content-type').startsWith('video/webm')?'webm':'mp4'; const output='qora-video.'+extension; await pipeline(Readable.fromWeb(file.body),createWriteStream(output+'.part')); const stored=await fs.open(output+'.part','r'); try{const head=Buffer.alloc(12),{bytesRead}=await stored.read(head,0,12,0),size=(await stored.stat()).size,expected=file.headers.get('content-length'); if(bytesRead<12||(extension==='mp4'?head.subarray(4,8).toString()!=='ftyp':head.subarray(0,4).toString('hex')!=='1a45dfa3')||expected!==null&&Number(expected)!==size)throw Error('文件不完整或视频格式不符,请保留任务号重新下载'); }finally{await stored.close();} await fs.rename(output+'.part',output);console.log('已保存 '+output);process.exit(0); } console.log(job.status,job.progress??'');await sleep(30000); } throw Error('本轮等待结束,请保存任务号并续查,不要创建新订单'); ``` ## Python查询与下载示例 下面只操作已保存的任务号,不创建新视频、不预扣生成积分。查询中断后可以用相同任务号继续运行。 ```python # Python 3 标准库,无需安装第三方包。仅查询/下载已有任务,不提交生成。 # 设置环境变量 QORA_API_KEY、QORA_JOB_ID 后运行。 import os,json,time,urllib.request,urllib.error,shutil key=os.environ['QORA_API_KEY'];job_id=os.environ['QORA_JOB_ID'] base='https://qorastudio.cn';headers={'Authorization':'Bearer '+key} for attempt in range(120): req=urllib.request.Request(base+'/api/v1/video/generations/'+job_id,headers=headers) try: with urllib.request.urlopen(req,timeout=90) as response: job=json.load(response)['data'] except urllib.error.HTTPError as error: if error.code in (408,429) or error.code>=500: time.sleep(30);continue raise except urllib.error.URLError: time.sleep(30);continue state=job['status'] if state in ('failed','expired','delivery_blocked','uncertain','quoted','estimating'): raise RuntimeError('请保留任务号处理当前状态,不要创建新订单:'+json.dumps(job,ensure_ascii=False)) if state=='completed': expected='/api/v1/video/generations/'+job_id+'/content' link=job.get('download_url') or '' direct=link.startswith('https://qorastudio.oss-cn-hongkong.aliyuncs.com/qora/') if not direct and link!=expected:raise RuntimeError('下载地址异常') req=urllib.request.Request(link if direct else base+expected,headers={} if direct else headers) with urllib.request.urlopen(req,timeout=120) as response: mime=response.headers.get('Content-Type','').split(';')[0] if mime not in ('video/mp4','video/webm'):raise RuntimeError('返回内容不是视频') head=response.read(12) valid=head[4:8]==b'ftyp' if mime=='video/mp4' else head[:4]==bytes([26,69,223,163]) if not valid:raise RuntimeError('视频文件头无效') filename='qora-video.'+('webm' if mime=='video/webm' else 'mp4') with open(filename,'wb') as output: output.write(head);shutil.copyfileobj(response,output) print('已保存',filename);break print(state,job.get('progress'));time.sleep(30) else: raise RuntimeError('本轮等待结束,请用相同任务号续查,不要重新生成') ``` ## 给Agent的接入检查清单 先读取当前模型清单,只选择available=true的route_id;同时核对该方案的时长、清晰度、参考类型、数量和价格。不要把网站支持的图片生成或AI对话推断成已开放API。 密钥只由调用方保存在服务端或本地私有环境变量,不写进公开网页。先上传真实文件,保存返回id;订单号在首次提交前生成并持久化,重试沿用原参数;提交返回id后立即保存。 报价是可选的预算检查。queued/preparing/dispatching/submitted/polling/downloading表示已进入处理流程,继续查询原任务;排队不是失败。返回429 capacity_wait时,尚未接受入队,按Retry-After重试原提交。uncertain保留任务号等待核查,不自动新建订单。不要承诺固定完成时间。 批量生成时限制提交和查询频率,所有Key共用每分钟60次限额;不要为绕过排队不停创建新Key或新订单。完成后通过本站content接口带Bearer鉴权下载,在expires_at指定的有效期内保存到调用方存储。 网站和API共用密钥所属账号积分,1元=10积分。提交入队时预扣,失败退款规则见任务状态说明;不得把HTTP200/202或某个固定进度当成成品完成。 接入遇到问题,可回网站左侧点击“联系客服”,微信号mhnsqgs。提供本站任务id、订单号、发生时间和错误码即可,不要提供完整API Key。 ## 文档格式与接入边界 可复制本页完整正文(含当前模型清单),或下载UTF-8 TXT交给接入人员。OpenAPI JSON提供结构化参数、响应和鉴权说明,便于导入支持OpenAPI的开发工具。 只调用本页列出的Qora地址和字段。不要填入其他平台的接口地址或凭据;也不要把本密钥当作其他平台通用密钥。当前未开放的图片生成、AI对话、Webhook与其他兼容格式,不能仅凭有密钥就调用。