ドキュメントファイルのアップロード
ファイルのアップロード
95MBまでは1リクエストで送れます。2GBまでは分割して送れ、通信が途切れても途中から再開できます。
手元の音声・動画ファイルをアップロードすると、AIが音声を文字起こしします。sourceに指定できるのはautoとsttだけです。言語と話者分離の指定にはlanguageとdiarizeを使います。詳しくは対応リンクと文字起こしの設定を確認してください。
使えるファイルとサイズ上限
ファイル名の拡張子をmp3、wav、m4a、flac、ogg、opus、mp4、mov、webm、mkvのいずれかにしてください。それ以外の拡張子には422 unsupported_mediaを返します。対応する拡張子でも、音声トラックがなければunsupported_mediaで失敗します。
| 送信方法・制限項目 | 上限 |
|---|---|
1リクエストで送信(multipart/form-data) | 95MB |
| 分割アップロード | 2GB(2,000,000,000バイト)です。プランによっては上限が下がります。 |
| チームで同時に保持できる未完了の分割アップロード | 20件 |
サイズ上限を超えると413 media_too_largeを返します。エラーのmax_bytesで、適用される上限を確認できます。
95MBまでのファイルを送る
POST /v1/transcriptionsへ、multipart/form-dataで送ります。ファイルはfileという名前のパートに入れてください。95MBまでなら、このリクエストだけで送信できます。
フォームには任意でlanguage、diarize(trueまたはfalse)、source(autoまたはstt)、webhook_urlも指定できます。
curl -X POST "https://api.transcript1.com/v1/transcriptions?wait=60" \
-H "Authorization: Bearer $TRANSCRIPT1_API_KEY" \
-F [email protected] \
-F language=en \
-F diarize=trueレスポンスは文字起こしオブジェクトで、source.platformの値はuploadです。動画リンクと同じく、HTTPステータスは処理中なら202、最終ステータスに達していれば200になります。空のファイルを送ると422 invalid_requestを返します。
大きなファイルを分割して送る
大きなファイルはチャンクに分けて送ります。中断しても、届いていないチャンクだけを再送できます。次の4つの手順で実装します。
1. アップロード先を用意する
まず、ファイル名とサイズをJSONで指定します。mime_typeは省略できます。Idempotency-Keyヘッダーも付けてください。作成リクエストを再送するときの重複を防げます。
curl -X POST "https://api.transcript1.com/v1/transcriptions" \
-H "Authorization: Bearer $TRANSCRIPT1_API_KEY" \
-H "Idempotency-Key: interview-2026-10-13" \
-H "Content-Type: application/json" \
-d '{"upload":{"filename":"interview.m4a","size":48210334,"mime_type":"audio/mp4"},"language":"auto","diarize":true}'HTTPステータスは201です。文字起こしのステータスはawaiting_uploadになり、送信に使う情報をuploadに返します。
{
"id": "tr_8fK2Lm0PqRsTuVwXyZaBcD",
"object": "transcription",
"status": "awaiting_upload",
"upload": {
"chunk_url_template": "https://api.transcript1.com/v1/transcriptions/tr_8fK2Lm0PqRsTuVwXyZaBcD/upload/chunks/{index}",
"headers": { "X-Upload-Token": "t1u_..." },
"expires_at": "2026-10-13T10:30:00.000Z",
"chunks": [
{ "index": 0, "offset": 0, "size": 8388608 },
{ "index": 1, "offset": 8388608, "size": 8388608 }
]
}
}チャンクの分け方はサーバーが決めます。約8MiB(8,388,608バイト)ずつの一覧をchunksに返します。上の例は一覧の一部を省略しています。
X-Upload-Tokenは、このアップロードだけに使えるシークレットです。有効期間は1時間で、expires_atに期限が入ります。
2. チャンクをPUTで送る
送信先はchunk_url_templateの{index}を、そのチャンクのindexで置き換えたURLです。ファイルのoffsetの位置からsizeバイトを読み取り、PUTのボディにapplication/octet-streamとして送ります。送るバイト数は、指定されたsizeと完全に一致させてください。
認証にはX-Upload-Tokenヘッダーを使います。Authorizationヘッダーは付ける必要がありません。
curl -X PUT "https://api.transcript1.com/v1/transcriptions/tr_8fK2Lm0PqRsTuVwXyZaBcD/upload/chunks/0" \
-H "X-Upload-Token: t1u_..." \
-H "Content-Type: application/octet-stream" \
--data-binary @chunk-0.binチャンクを受け取ると、{ "object": "upload_chunk", "index": 0, "size": 8388608 }が返ります。同じチャンクを再送すると、前の内容を上書きします。
バイト数が違う場合や、一覧にないインデックスを指定した場合は422 invalid_requestです。トークンを付けていない場合や期限が切れている場合は401 unauthorizedを返します。
3. 送信済みチャンクを確認して再開する
中断したら、GET /v1/transcriptions/:id/uploadでサーバーが受け取ったチャンクの一覧を取得します。
{
"object": "upload",
"status": "awaiting_upload",
"total_bytes": 48210334,
"uploaded_bytes": 16777216,
"received_chunks": [0, 1],
"chunks": [ { "index": 0, "offset": 0, "size": 8388608 } ],
"expires_at": "2026-10-13T10:30:00.000Z"
}received_chunksに入っていないチャンクだけを送ってください。トークンの期限が切れていたら、手順1の作成リクエストを、同じIdempotency-Keyと同じパラメーターで送り直します。同じ文字起こしに対して、新しいアップロードトークンを取得できます。
4. アップロードを確定する
curl -X POST "https://api.transcript1.com/v1/transcriptions/tr_8fK2Lm0PqRsTuVwXyZaBcD/upload/complete" \
-H "Authorization: Bearer $TRANSCRIPT1_API_KEY"POST /v1/transcriptions/:id/upload/completeを呼び出すと、サーバーが全チャンクの到着とサイズを検証します。問題がなければファイルを結合し、文字起こしをキューに入れます。レスポンスは202と文字起こしオブジェクトです。
- チャンクが足りない場合:
409 upload_incompleteを返します。missing_chunksに入っているインデックスのチャンクを再送してください。 - すでにアップロードを完了・キャンセルしている場合:
409 invalid_stateを返します。
以降はGET /v1/transcriptions/:id?wait=60でポーリングするか、Webhookで通知を受け取ります。
Pythonで一通り実行する
import os
import requests
API = "https://api.transcript1.com"
auth = {"Authorization": f"Bearer {os.environ['TRANSCRIPT1_API_KEY']}"}
path = "interview.m4a"
created = requests.post(
f"{API}/v1/transcriptions",
headers={**auth, "Idempotency-Key": "interview-2026-10-13"},
json={"upload": {"filename": os.path.basename(path), "size": os.path.getsize(path)}},
)
created.raise_for_status()
transcription = created.json()
upload = transcription["upload"]
with open(path, "rb") as file:
for chunk in upload["chunks"]:
file.seek(chunk["offset"])
url = upload["chunk_url_template"].replace("{index}", str(chunk["index"]))
response = requests.put(
url,
data=file.read(chunk["size"]),
headers={**upload["headers"], "Content-Type": "application/octet-stream"},
)
response.raise_for_status()
done = requests.post(f"{API}/v1/transcriptions/{transcription['id']}/upload/complete", headers=auth)
done.raise_for_status()
print(done.json()["status"])アップロードの上限と保存期間
- チーム内で同時にアップロード待ち(
awaiting_upload)にできるのは20件までです。超過すると429 too_many_active_jobsとRetry-Afterヘッダーを返します。 - 作成から24時間以内にアップロードを完了しなければ、キャンセルしてチャンクを削除します。
- メディアファイルは、文字起こしが
completed、failed、canceledのいずれかになってから24時間後に削除します。文字起こしテキストは残り、DELETE /v1/transcriptions/:idで削除するまで保持します。 - 失敗した場合やキャンセルした場合は課金しません。ファイルの長さがわかった時点で、メディアの分数を切り上げて課金します。計算方法は料金と制限で確認できます。
最終更新 2026年10月14日