この API は完成済みの音声ファイルをキュー内のジョブとして文字起こしします。ファイルを送信したら、返されたジョブ ID を保存し、処理が終わるまでジョブを取得してください。すべてのリクエストは HTTPS で送信し、アカウントの認証情報を使用します。例に示す HTTP Basic 認証情報、または API トークンを使用できます。詳しくは認証をご覧ください。認証情報はご自身のサーバーに保管してください。
エンドポイント
二つの API ホスト、https://api.multi.telと互換ホストのhttps://api.multitel.netは、同じアカウント内のジョブ、冪等性キー、制限、課金を共有します。アップロードのエンコード方式とレスポンスのエンベロープが異なるため、対応するパーサーを使い、一貫して同じホストを利用してください。
| 操作 | メソッドとパス |
|---|---|
| サービス情報 | GET /v3/speech_to_text |
| ジョブの送信 | POST /v3/speech_to_text |
| ジョブを作成せずに料金を見積もる | POST /v3/speech_to_text/estimate |
| ジョブの取得 | GET /v3/speech_to_text/JOB_ID |
| 支払い待ちジョブの精算 | POST /v3/speech_to_text/JOB_ID/settle |
| 利用量 | GET /v3/speech_to_text/usage |
ホストがapi.multi.telの場合、すべてのパスではプレフィックス/v1/speech-to-textを/v3/speech_to_textの代わりに使用することもできます。例:POST /v1/speech-to-text/estimate。ホストがapi.multitel.netの場合は、/v3/speech_to_textのパスを使用してください。
サービス情報のレスポンスには、mode(batch)、realtime(false)、paidEnabled(新規の有料送信を現在受け付けているか)、pricePerMinuteUsd(0.005)、billingUnit(audio_second)、maxAudioSeconds(7200)、maxUploadBytes(26214400)、および短いdescriptionが含まれます。取得は無料で、有料送信が無効でも取得できます。サービス全体が利用できない場合に限り、503 transcription_unavailableを返します。
音声ファイルの準備
サイズが最大 25 MiB(26,214,400 バイト)、長さが最大 2 時間(7,200 秒)の完成済み音声ファイルを使用してください。送信時に、音声ストリームを含む MP3、WAV、Ogg、FLAC、MOV、Matroska のいずれかのメディアとして認識され、メタデータ上の長さがゼロより大きく 7,200 秒以下である必要があります。認識されてもこれらの検証に合格しないファイルは拒否され、422 unsupported_audioを返します。これらの形式として読み取れないファイルは、現状では代わりにサーバーエラー(500)で拒否される場合があります。そのようなファイルを変更せずに再送信しないでください。拡張子だけでは互換性を判断できません。
これらの検証に合格しても、音声をデコードできるとは限りません。音声は一つまたは二つのチャンネルとして処理されます。二つを超える音声チャンネルを持つファイル、デコード後の音声が 2 時間を超えるファイル、その他処理中にデコードに失敗したファイルは、最終的にfailedジョブとなり、通常はdecode_failedが設定され、課金されません。送信前にマルチチャンネル音声をモノラルまたはステレオに変換してください。
任意の言語ヒントには、話されている言語を示す小文字二文字または三文字のコードを使用します。例:en。ヒントを指定しない場合はフィールドを省略してください。api.multi.telは空文字列を拒否します。ヒントは処理の参考に使われますが、対応言語リストとの照合は行われないため、話されている言語の有効なコードを指定してください。
文字起こしジョブの送信
JSON を、Content-Type: application/jsonを指定してPOST https://api.multi.tel/v3/speech_to_textに送信してください。リクエスト本文は最大 35 MiB で、最大サイズのファイルを base64 エンコードしたものを格納できます。これを超える本文は 413 で拒否されます。
| フィールド | 意味 |
|---|---|
audioBase64 | 必須。ファイル全体を標準 base64(A–Z, a–z, 0–9, +, /)で表し、必要に応じて=でパディングします。data-URL プレフィックス、改行、空白は追加せず、URL セーフな文字セットも使わないでください。値をデコードしたサイズは 1 バイト以上 25 MiB 以下で、再エンコードした文字列が元の文字列と完全に一致する必要があります。 |
language | 任意の言語ヒント。上記の説明を参照してください。 |
これ以外の JSON プロパティ(idempotency_keyを含む)は拒否され、400 invalid_transcription_requestを返します。キーはヘッダーで送信してください。
冪等性キー
各送信には、Idempotency-Keyヘッダーが必要です。長さは 1 文字以上 190 文字以下とし、ASCII の英字、数字、-, _, .、:を使用し、先頭と末尾に空白を付けないでください。互換ホストは前後の空白を除去し、キーをバイト数で計測するため、その他の文字はホストによって数え方が異なる場合があります。キーがない場合、または 191 文字以上の場合は 400 で拒否されます。
キーは、両ホストとアカウントのすべての認証情報にわたり、そのアカウントの音声文字起こしに対して有効です。同じキー、同じファイル、同じ言語で再送信すると、既存のジョブと HTTP 200、およびduplicate: trueが返されます。ジョブの状態や、ジョブ作成後に処理方式が更新されたかどうかに関係なく、追加の課金はありません。同じキーを異なるファイルや言語で再使用すると、409 idempotency_conflictを返します。新しいキーでは、同一ファイルでも新しいジョブが作成され、処理が正常に完了すると別途課金されます。
API_USER="your-api-username"
API_PASSWORD="your-api-password"
node -e 'process.stdout.write(JSON.stringify({audioBase64:require("node:fs").readFileSync("completed-call.mp3").toString("base64"),language:"en"}))' > completed-call.json
curl --fail-with-body --silent --show-error --user "$API_USER:$API_PASSWORD" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: speech-call-001" \
--data-binary @completed-call.json \
-o speech-job.json \
https://api.multi.tel/v3/speech_to_text
node -p 'JSON.parse(require("node:fs").readFileSync("speech-job.json","utf8")).data.id'新しいジョブは HTTP 202 と下記のフィールドを返し、再送信では HTTP 200 と「文字起こし結果の取得」で説明する完全なジョブオブジェクトを返します。ジョブ ID(UUID)はdata.idから取得してください。新しいジョブのレスポンスは次の形式です(識別子と値は例です)。
{
"status": "success",
"data": {
"id": "3f6c1b2e-8a4d-4e7f-9c21-5b0d7e4a9f13",
"status": "queued",
"mode": "batch",
"realtime": false,
"source": "api",
"durationSeconds": 90.5,
"billedSeconds": 91,
"costUsd": "0.007583334",
"pricePerMinuteUsd": "0.005"
}
}ジョブがキュー内または実行中の間、durationSeconds, billedSeconds、costUsdはファイルのメタデータから得た推定値です。最終的な料金にはデコード後の長さが使われます。
送信時には、プリペイド残高でそのジョブと他の未精算ジョブを賄えない場合の 402 insufficient_balance、アカウントまたはサービスに未完了ジョブが多すぎる場合の 429 transcription_queue_full、ファイル検証の処理能力に達している場合の 429 audio_validation_busy、有料文字起こしが無効な場合の 503 paid_transcription_not_enabledも返されます。429 および 503 の場合は、同じキーで時間を置いて再試行してください。
ジョブを作成せずに料金を見積もる
同じ JSON 本文をPOST https://api.multi.tel/v3/speech_to_text/estimateに送信してください。冪等性キーは不要です。見積もりではファイルを検証して長さを計測しますが、文字起こし、ジョブ作成、資金の確保、残高確認、課金は行いません。languageヒントは受け付けますが、見積もりには影響しません。
見積もりに成功すると HTTP 200 を返し、estimate: true, charged: false, mode, realtime, durationSeconds, billedSeconds, pricePerMinuteUsd、costUsdがdataに含まれます。見積もりにはメタデータ上の長さを使いますが、完了したジョブにはデコード後の長さで課金するため、両者が異なることがあります。見積もりでは送信と同じファイル検証を行います。有料文字起こしが有効な場合にのみ利用できます(無効の場合は 503 paid_transcription_not_enabled)。ファイル検証の処理能力に達している場合は、429 audio_validation_busyが返ることがあります。少し待ってから再試行してください。
文字起こし結果の取得
次のパスをポーリングしてください:GET /v3/speech_to_text/JOB_ID。手順は「ジョブのワークフローガイド」を参照してください。ジョブオブジェクトには以下のフィールドが含まれます。
| フィールド | 意味 |
|---|---|
id | ジョブの UUID。 |
status | queued, running, completed, failed、またはawaiting_payment。 |
progress | 実行中は、取得可能な場合に 0 から 99 のパーセント値。完了時は 100。それ以外はnull。 |
durationSeconds, billedSeconds | 音声の長さと、請求対象の整数秒数。ジョブがキュー内または実行中の間はメタデータによる推定値で、完了後または支払い待ちではデコード後の長さを使います。 |
costUsd, costIsEstimate | 米ドル建ての料金。小数点以下九桁の十進文字列です。costIsEstimateは、ジョブがキュー内または実行中の間はtrueです。失敗したジョブは、costUsdに見積もりが残っていても課金されません。 |
pricePerMinuteUsd | 0.005は API ジョブ、0.000は無料の Hosted PBX 録音ジョブに適用されます。 |
failureCode | 失敗したジョブでは、decode_failed(音声をデコードできなかった。例:二つを超えるチャンネルがある、またはデコード後に 2 時間を超える)、inference_timeout(処理時間が長すぎた)、service_error、またはworker_lease_lost(処理が中断された)です。コードunsupported_audioとquality_check_failedも定義されています。支払い待ちジョブはinsufficient_balanceを示し、精算後も残る場合があります。 |
source, modelVersion, createdAt | sourceは、API 送信ではapi、アカウントの Hosted PBX 録音ジョブではhpbxです。modelVersionは内部構造を解釈せずに扱う処理バージョン文字列です。createdAtは送信時刻です。 |
duplicate | trueは既存のジョブを返すレスポンスで設定されます。 |
result | 次の条件の場合のみ存在します:statusがcompleted。 |
| 結果のフィールド | 意味 |
|---|---|
text | 文字起こし全体。全セグメントのテキストをセグメント順に改行で連結したものです。 |
segments | 開始時刻順のセグメント配列。各セグメントは最大約 29 秒の音声区間を表します。startとend(音声の先頭からの秒数)は個々の単語や文ではなくその区間を示し、連続する区間は最大 1 秒重なる場合があります。各セグメントには、text、language(言語コード。空の場合もあります)、さらに二チャンネルの結果ではchannelも含まれます。 |
channelCount | 1 または 2。現在の結果には含まれますが、古い結果では省略される場合があります。 |
audioDurationMs | デコード後の長さ(ミリ秒)。課金時には秒単位に切り上げます。 |
qualityFlags | 空、またはreview_recommendedとともにrepetition_detected(区間内で同じフレーズが異常に多く繰り返される)、no_speech(文字起こしされた音声がない)、もしくはその両方が含まれます。 |
pipelineVersion | 含まれる場合があります。内部構造を解釈せずに扱う処理識別子です。 |
文字起こし、タイムスタンプ、言語ラベル、チャンネルラベルは自動生成され、正確性は保証されません。品質フラグがあれば結果を確認し、重要な名前、数字、約束の内容を元の音声と照合してください。長い無音や非常に小さい音の区間はスキップされ、セグメントは生成されません。個々の話者の識別は行いません。結果のchannelCountが 2 の場合、各セグメントのchannelはA(第一、つまり左チャンネル)またはB(第二、つまり右チャンネル)です。話者を分けられるのは、各話者が別のチャンネルに録音されていた場合のみです。二チャンネル音声は経過時間に対して一度課金され、チャンネルごとの課金にはなりません。モノラルの結果にはチャンネルラベルがありません。
api.multitel.net の利用
互換エンドポイントPOST https://api.multitel.net/v3/speech_to_textは、multipart/form-dataを受け付けます。audioファイルパートと任意のlanguageフィールドを使用し、JSON のaudioBase64は使用しません。空のlanguageはヒントなしとして扱います。同じIdempotency-Keyヘッダーを送信してください。ヘッダーがない場合、このホストはidempotency_keyフォームフィールドも受け付けます。次の名前のフィールド:source, free, billing_source, realtime、streamは拒否され、400 unsupported_transcription_optionを返します。その他のフォームフィールドは無視します。このホストは以下のエラーも返します。
- 400
idempotency_key_required:キーがない、または長すぎる場合。 - 400
audio_upload_required:アップロードがない、または完全に受信できなかった場合。 - 400
invalid_language:言語が無効な場合。 - 413
invalid_audio_size:ファイルが空、または大きすぎる場合。 - 400
invalid_job:ジョブ ID の形式が不正な場合。
このホストの音声文字起こしサービスは、レスポンスにエンベロープ{"status":{"code":HTTP_STATUS},"response":{...}}を使います。statusは文字列ではなくオブジェクトです。成功時、responseにはプライマリホストのdataと同じオブジェクトが格納されるため、ジョブ ID はresponse.idです。エラー時は、response.codeにエラーコードが格納され、メッセージやリクエスト ID は含まれません。認証失敗(401)はホスト共通のサインイン検証が返すため、本文が異なる場合があります。解析前に HTTP ステータスを確認してください。ホスト間でアップロードのエンコード方式やレスポンスパーサーを混用しないでください。
このホストで見積もる場合は、同じ multipart フィールドを/v3/speech_to_text/estimateに POST してください。冪等性キーは不要で、見積もりはresponseに格納されます。
API_USER="your-api-username"
API_PASSWORD="your-api-password"
curl --fail-with-body --silent --show-error --user "$API_USER:$API_PASSWORD" \
-H "Idempotency-Key: speech-call-001" \
-F "audio=@completed-call.mp3" -F "language=en" \
-o speech-job.json \
https://api.multitel.net/v3/speech_to_text
node -p 'JSON.parse(require("node:fs").readFileSync("speech-job.json","utf8")).response.id'