Skip to content
Guides · 媒体上传

媒体上传

通过预签名直传把本地图片、视频、音频送进 AllToken。


概述

视频生成与图生图都会用到媒体素材 —— 参考图、参考视频与音频、源图、蒙版。怎么送进来只有一条判据:

  • 素材已在公网(你的 CDN / 对象存储)—— 直接填它的 http(s) URL,零上传开销。仅视频参考素材支持。
  • 素材在本地 —— 先用预签名直传上传,再用返回的 upload_id 引用。这是本地文件唯一的通路,也是图生图(源图与蒙版)唯一的通路。

警告

视频参考素材的 data: base64 内联通路已于 2026-08-06 下线,与图生图侧对齐(图生图的历史 multipart 上传更早已下线)。本地素材现在一律走预签名直传。

上传端点是 POST https://api.alltoken.ai/v1/uploads/presign(复数 uploads)。别和账户服务的 /upload/presign 搞混,后者是站内头像等用途,只收图片 MIME。

选哪条通路

你的场景通路理由
视频参考素材已在你的 CDN / OSS 上url完全不用上传 —— 字节不经过我方网关与存储
视频参考素材在本地(图 / 视频 / 音频)预签名直传本地文件唯一通路
图生图(/images/edits/images/variations)的源图与蒙版预签名直传唯一入口,无论文件多大

三步直传

文件不经过我方网关。你先换一个一次性直传地址,把原始字节 PUT 到对象存储,再用返回的 upload_id 创建任务。网关只搬运一个几十字节的 ID。视频参考素材与图生图共用这套机制,区别只在 purpose 和引用它的字段。

第 1 步 —— 申请直传地址:

申请直传
$POST https://api.alltoken.ai/v1/uploads/presign

请求体:purpose(决定允许的 MIME 与体积,见下)、content_type(文件 MIME,小写)、content_length(精确字节数)、content_md5checksum_sha256

警告

两个摘要的编码方式不同content_md5base64checksum_sha256hex。写反了会在 presign 阶段就被 400 拦下。

响应返回 upload_idupl_ 开头)、upload_url(预签名 PUT 地址)、required_headers(第 2 步原样回填)、expires_in(URL 有效期,300 秒)、claim_expires_atupload_id 有效期,2 小时)、max_content_length

第 2 步 —— 把原始字节 PUT 到 upload_url,并把 required_headers 里的头原样回填。body 是原始文件字节 —— 不是 base64、不是 multipart:

直传对象存储
1PUT <upload_url>
2Content-Type: video/mp4
3Content-MD5: N0xUuLBP5C0uKJ2i0fA1kA==
4
5<原始字节>

警告

少带或改写任何一个必需头,对象存储会直接返 403 —— 预签名把这些头也签进去了。不要自己加 Content-Encoding、不要 gzip、不要走 multipart。

第 3 步 —— 用 upload_id 创建任务。视频在 content[].upload_id 里用它;图生图用 image_upload_id / mask_upload_id 顶层字段。网关会校验字节数与 ETag、把对象转入与该任务绑定的正式区、换成上游可访问地址提交 —— 全程对你透明,你只看到 202 + task_id

三条必须记住的规则:

  • 同一项里 upload_id 与 URL 字段互斥 —— 两个都填返 400 upload_url_conflict
  • presign 与创建任务必须用同一把 API Key —— 归属按(用户 + API Key + purpose)校验,换 Key 返 404 upload_not_found
  • purpose 必须与用途对应,用错也返 404 upload_not_found

完整的请求 / 响应字段表见 图像 API视频 API 参考。

purpose 对照

每个 purpose 固定了允许的 MIME 与单文件体积上限。

purpose用在允许的 MIME单文件上限
video_input_image视频参考图 / 首尾帧image/pngimage/jpegimage/webpimage/gif20 MiB
video_input_video视频参考视频video/mp4video/quicktimevideo/webm100 MiB
video_input_audio视频参考音频audio/wavaudio/mpegaudio/mp4audio/aacaudio/ogg20 MiB
image_edit_source图生图源图image/pngimage/jpegimage/webp25 MiB
image_edit_mask图生图蒙版image/pngimage/webp不收 jpeg25 MiB
image_variation_source图生图变体源图image/pngimage/jpegimage/webp25 MiB

蒙版不收 image/jpeg,是因为需要 alpha 通道表达「改哪里」,而 jpeg 没有透明通道。

时间窗与配额

时间窗长度过期后
upload_url(直传地址)5 分钟PUT 返 403 —— 重新 presign
upload_id(素材凭据)2 小时创建任务返 409 upload_expired

也就是说:拿到地址就传,但传完之后有两小时从容组装并提交生成请求。

一个 upload_id绑定一次任务,重复使用返 409 upload_already_used。这是防重复计费的设计 —— 一份素材、一次任务、一条账单。任务创建失败时,临时对象会被自动回收。

限制阈值超出返回
同时未使用的 upload_id100 个429 quota_exceeded
每自然日(UTC)直传总字节2 GiB429 quota_exceeded

正常「传完就用」的节奏不会碰到这两条。大批量图生图请注意日上限:25 MiB × 约 80 张就到 2 GiB。

上传错误码

上传阶段(presign):

HTTPcode含义
400invalid_purposepurpose 拼错或不支持
400invalid_content_typeMIME 不在该 purpose 白名单内(蒙版传 jpeg 会中这条)
400invalid_content_md5MD5 不是合法 base64(别写成 hex)
400invalid_checksumSHA-256 不是 64 位小写 hex(别写成 base64)
413payload_too_largecontent_length 超过该 purpose 上限
429quota_exceededpending 超 100 个,或当日超 2 GiB
503storage_unavailable存储暂不可用 —— 稍后重试

绑定阶段(创建任务时):

HTTPcode含义
404upload_not_foundupload_id 不存在、换了 API Key,或 purpose 不匹配
409upload_already_used已绑过任务 —— 重新 presign
409upload_expired超过 2 小时 —— 重新 presign
400upload_object_missing只 presign 没 PUT 就来创建任务
400upload_size_mismatch实际字节数与 content_length 不符
409upload_modified上传后对象被改动(ETag 不符)
400upload_url_conflict同一项里 upload_id 与 URL 字段同时填了