メディアアップロード
presigned direct-to-R2 アップロードで、ローカルの画像・動画・音声を AllToken に送信します。
概要
動画生成と画像編集はどちらもメディア素材を扱います — 参照画像、参照動画と音声、ソース画像、マスクです。それらの送り方のルールはただ 1 つです:
- 素材がすでに公開インターネット上にある場合(あなたの CDN / オブジェクトストレージ) — その
http(s)URL を直接渡すだけで、アップロードのオーバーヘッドはゼロです。動画の参照素材のみ。 - 素材がローカルにある場合 — まず presigned direct-to-R2 アップロードでアップロードし、返された
upload_idを参照します。これはローカルファイルにとって唯一の経路であり、画像編集(ソースとマスク)にとっても唯一の経路です。
警告
動画の参照素材における data: base64 インラインパスは 2026-08-06 に削除されました。これは画像側(レガシーの multipart アップロードはより早く削除済み)に合わせたものです。ローカルメディアは現在、常に presigned アップロードを経由します。
エンドポイントは POST https://api.alltoken.ai/v1/uploads/presign(複数形の uploads)です。アカウントサービスの /upload/presign と混同しないでください。後者はサイト内アバターなどの用途で、画像 MIME タイプのみを受け付けます。
経路を選ぶ
| あなたの状況 | 経路 | 理由 |
|---|---|---|
| 動画の参照素材がすでにあなたの CDN / OSS 上にある | url を渡す | アップロードは一切不要 — バイトが当社のゲートウェイやストレージに触れることはありません |
| 動画の参照素材がローカルにある(画像 / 動画 / 音声) | presigned アップロード | ローカルファイルにとって唯一の経路 |
画像編集(/images/edits、/images/variations)のソースとマスク | presigned アップロード | ファイルサイズに関わらず唯一の入口 |
3 ステップのアップロード
ファイルが当社のゲートウェイを通過することはありません。一度きりの直接アップロード URL を取得し、生のバイトをオブジェクトストレージへ直接 PUT し、タスク作成時に返された upload_id を参照します。ゲートウェイが運ぶのは数十バイトの ID だけです。同じ仕組みが動画の参照素材と画像編集の両方に使われ、異なるのは purpose とそれを参照するフィールドだけです。
ステップ 1 — 直接アップロード URL をリクエストする:
$POST https://api.alltoken.ai/v1/uploads/presignボディ:purpose(許可される MIME とサイズを決定 — 下記参照)、content_type(ファイルの MIME、小文字)、content_length(正確なバイト数)、content_md5、checksum_sha256。
警告
2 つのダイジェストは異なるエンコーディングを使います:content_md5 は base64、checksum_sha256 は hex です。入れ替えると presign 段階で 400 として拒否されます。
レスポンスは upload_id(upl_ で始まる)、upload_url(presigned PUT の宛先)、required_headers(ステップ 2 でそのまま再送)、expires_in(URL の有効期間、300 秒)、claim_expires_at(upload_id の有効期間、2 時間)、max_content_length を返します。
ステップ 2 — 生のバイトを upload_url へ PUTし、required_headers 内のすべてのヘッダーを正確に再送します。ボディは生のファイルバイトです — base64 でも multipart でもありません:
| 1 | PUT <upload_url> |
| 2 | Content-Type: video/mp4 |
| 3 | Content-MD5: N0xUuLBP5C0uKJ2i0fA1kA== |
| 4 | |
| 5 | <raw bytes> |
警告
必須ヘッダーを省略または書き換えると、オブジェクトストレージは 403 を返します — presigned URL はそれらのヘッダーも署名しているためです。Content-Encoding を追加したり、gzip したり、multipart を使ったりしないでください。
ステップ 3 — upload_id を参照してタスクを作成します。動画は content[].upload_id に入れ、画像編集は image_upload_id / mask_upload_id のトップレベルフィールドを使います。ゲートウェイはバイト数と ETag を検証し、オブジェクトをそのタスク専用の恒久領域へ移し、上流からアクセス可能なアドレスとして提出します — すべてあなたには透過的で、あなたは 202 + task_id を受け取るだけです。
覚えておくべき 3 つのルール:
- 1 つの項目内で
upload_idと URL フィールドは相互排他です — 両方を埋めると 400upload_url_conflictを返します。 - presign とタスク作成は同じ API Key を使う必要があります — 所有権は(ユーザー + API Key + purpose)として検証され、Key を切り替えると 404
upload_not_foundを返します。 purposeは実際の用途と一致している必要があり、一致しない場合も 404upload_not_foundになります。
purpose リファレンス
各 purpose は、許可される MIME タイプと 1 ファイルあたりのサイズ上限を固定します。
purpose | 用途 | 許可される MIME | 1 ファイル上限 |
|---|---|---|---|
video_input_image | 動画の参照画像 / 先頭・末尾フレーム | image/png、image/jpeg、image/webp、image/gif | 20 MiB |
video_input_video | 動画の参照動画 | video/mp4、video/quicktime、video/webm | 100 MiB |
video_input_audio | 動画の参照音声 | audio/wav、audio/mpeg、audio/mp4、audio/aac、audio/ogg | 20 MiB |
image_edit_source | 画像編集のソース | image/png、image/jpeg、image/webp | 25 MiB |
image_edit_mask | 画像編集のマスク | image/png、image/webp(jpeg 不可) | 25 MiB |
image_variation_source | 画像バリエーションのソース | image/png、image/jpeg、image/webp | 25 MiB |
マスクが image/jpeg を拒否するのは、alpha チャンネルで「どこを変更するか」を表現する必要があり、jpeg には透明度がないためです。
時間枠とクォータ
| 時間枠 | 長さ | 期限切れ後 |
|---|---|---|
upload_url(PUT の宛先) | 5 分 | PUT が 403 を返す — 再度 presign |
upload_id(素材の引き換え権) | 2 時間 | タスク作成が 409 upload_expired を返す |
つまり:URL を取得したらすぐにアップロードしてください。ただしその後、生成リクエストを組み立てて送信するまでに 2 時間の猶予があります。
upload_id はちょうど 1 つのタスクにバインドされ、再利用すると 409 upload_already_used を返します。これは意図的な設計です — 1 素材、1 タスク、1 請求。タスク作成に失敗した場合、一時オブジェクトは自動的に回収されます。
| クォータ | しきい値 | 超過時 |
|---|---|---|
同時に未使用の upload_id | 100 | 429 quota_exceeded |
| UTC の 1 日あたりの総アップロードバイト数 | 2 GiB | 429 quota_exceeded |
通常の「アップロードしてすぐ使う」ペースでこれらに達することはありません。大量の画像編集バッチでは日次上限に注意してください:25 MiB × 約 80 ファイルで 2 GiB に達します。
アップロードエラーコード
presign 段階:
| HTTP | code | 意味 |
|---|---|---|
| 400 | invalid_purpose | purpose のスペルミス、または非対応 |
| 400 | invalid_content_type | MIME が purpose のホワイトリストにない(jpeg として送られたマスクはここに該当) |
| 400 | invalid_content_md5 | MD5 が有効な base64 でない(hex を送らないこと) |
| 400 | invalid_checksum | SHA-256 が 64 文字の小文字 hex でない(base64 を送らないこと) |
| 413 | payload_too_large | content_length が purpose の上限を超過 |
| 429 | quota_exceeded | pending が 100 超、または本日 2 GiB 超 |
| 503 | storage_unavailable | ストレージが一時的に停止中 — リトライ |
バインド段階(タスク作成時):
| HTTP | code | 意味 |
|---|---|---|
| 404 | upload_not_found | 不明な upload_id、誤った API Key、または purpose の不一致 |
| 409 | upload_already_used | すでにタスクにバインド済み — 再度 presign |
| 409 | upload_expired | 2 時間より古い — 再度 presign |
| 400 | upload_object_missing | presign したが、タスク作成前に PUT していない |
| 400 | upload_size_mismatch | 実際のバイト数が content_length と異なる |
| 409 | upload_modified | アップロード後にオブジェクトが変更された(ETag 不一致) |
| 400 | upload_url_conflict | 1 つの項目に upload_id と URL フィールドの両方が設定されている |