OpenRouter、音声文字起こし API を提供開始
OpenRouter は、Chat Completions と同じ API キーとプラットフォームを使用して音声認識(Transcription)機能を追加し、開発者が Whisper や他の STT モデルを SDK の追加なしに利用可能にした。
キーポイント
単一 API エンドポイントによる統合
OpenRouter は /api/v1/audio/transcriptions エンドポイントを新設し、Chat Completions と同じ Bearer キーで音声ファイルを転送・処理できるようにした。これにより、別々の SDK やサービスの追加が不要となった。
自動ロードバランシングとマルチプロバイダー対応
Whisper などのモデルは複数のプロバイダにホストされており、リクエストごとに自動的に負荷分散される。ただし、チャット機能で使われる詳細なルーティング制御(order, fallbacks など)はこのエンドポイントでは適用されない。
仕様と制限の明確化
音声入力は Base64 文字列または multipart ファイル形式のみ対応し、最大 25MB、アップストリームタイムアウトは 60 秒である。SRT/VTT 出力には非対応だが、詳細なタイムスタンプが必要な場合は verbose_json 形式で取得可能。
透明性のある価格設定と使用量計測
料金はモデルに応じて時間ベースまたはトークンベースで計算され、プロバイダによるマージンは加算されない。レスポンスに含まれる usage.cost フィールドにより、実際の請求額をリアルタイムで追跡できる。
OpenAI互換性とファイル形式
既存のOpenAIクライアントをそのまま使用可能で、25MB以下のファイルはmultipart/form-data、それ以上はbase64 JSON経由で処理されます。
詳細なレスポンスとコスト管理
JSONレスポンスにはテキストに加え、音声秒数やトークン数、ドル建ての正確なコストが含まれ、請求管理に利用できます。
用途によるエンドポイントの使い分け
単純な文字起こしには「transcription」エンドポイントを、音声の内容を推論・分析したい場合はチャット機能の「audio input」を使用します。
重要な引用
You don't need a new SDK or a separate service.
Because transcription runs on the same platform as your chat traffic, a model hosted by several providers is load-balanced across them automatically instead of being pinned to a single vendor.
Pricing is duration-based or token-based depending on the model, with no provider markup.
If you already have a client built for OpenAI's /v1/audio/transcriptions, you can point its base URL at https://openrouter.ai/api/v1 and it works unchanged.
Use /audio/transcriptions when you want audio turned into text, and audio input on chat when you want a model to reason about the audio.
"The provider block on this endpoint carries provider-specific options instead:"
影響分析・編集コメントを表示
影響分析
この機能追加により、開発者は音声認識機能を組み込むためのインフラ構築コストと複雑さを大幅に削減でき、マルチプロバイダー環境での柔軟性と信頼性が向上します。特に、チャット処理と音声処理を単一の統合基盤で管理できる点は、システムアーキテクチャの簡素化と運用効率の向上に寄与する重要な進展です。
編集コメント
OpenRouter は、音声認識機能を既存のチャット API と完全に統合することで、開発者のワークフローを劇的に簡素化しました。特に、複数のプロバイダ間での自動負荷分散と透明な価格設定は、実運用における信頼性とコスト管理の面で大きなメリットをもたらします。
40 分間の営業通話の録音、ボイスメモのフォルダ、あるいはユーザーがマイクボタンを押しっぱなしにしている状況で、テキストへの書き起こしが必要になることがあります。一般的な対応策としては、既存のチャット処理とは別に Whisper サーバーを立てたり、音声からテキストへの変換(STT)専用の SDK を追加したりすることが挙げられます。
しかし OpenRouter では、POST /api/v1/audio/transcriptions エンドポイントにオーディオを送信するだけで、チャット完了と同じ API キーと認証情報を使用して、書き起こされたテキストと使用量情報が含まれた JSON を受け取ることができます。新しい SDK の導入や別サービスの用意は不要です。
書き起こし処理もチャットトラフィックと同じプラットフォーム上で実行されるため、複数のプロバイダがホストするモデルは特定のベンダーに固定されず、自動的にロードバランシングされます。
Tl;dr
- base64 符号化されたオーディオを POST /api/v1/audio/transcriptions に送信し、レスポンスから JSON 形式のテキストと使用量オブジェクトを読み取ることで書き起こしが可能です。使用する Bearer キーはチャット完了と同じものです。
- Whisper クラスのモデル(スラッグ名:openai/whisper-1)が利用できます。また、トークン課金制の新しい音声からテキストへの変換(STT)モデルも存在します。これらはデフォルトのカタログではなく、?output_modalities=transcription を指定することで発見できます。
複数のプロバイダーがトランスクリプションモデルをホストしている場合、OpenRouter は自動的に負荷分散を行います。ただし、チャット機能で利用可能なリクエストごとのルーティング制御(順序指定、フォールバックの許可、データ収集、ソートなど)は、このエンドポイントでは現在適用されていません。ここではプロバイダーブロックに設定できるのは、各プロバイダー固有のオプションのみです。
Bring-your-own-key (BYOK) 機能を利用すると、プラットフォーム利用料のみを支払うことで、自社のプロバイダーキーを直接経由させることが可能です。
設計時に考慮すべき制限は以下の通りです。まず、アップストリームのタイムアウトは最大 60 秒です。また、音声 URL の指定はできません。代わりに、Base64 でエンコードされた JSON データか、OpenAI 形式の multipart ファイル(最大 25 MB)を送信する必要があります。さらに、SRT や VTT 形式での出力もサポートされていません。
ただし、OpenAI 互換のプロバイダーを利用し、response_format を "verbose_json" に設定すれば、単語レベルおよびセグメントごとのタイムスタンプを取得できます。
料金はモデルによって「音声の長さ」または「トークン数」に基づいて計算され、プロバイダーによる上乗せ手数料は発生しません。usage.cost フィールドには、実際のリクエストコストが返されるため、利用状況の管理や予算制御に活用可能です。
OpenRouter で音声をトランスクリプションするには?
POST /api/v1/audio/transcriptions エンドポイントへ Base64 符号化された音声データを送信し、JSON レスポンス内の text フィールドからテキストを取得します。OpenRouter API キーは、チャット呼び出し時と同様に Bearer トークンとして渡す必要があります。また、使用するモデルを指定して、音声データを引数として手渡してください。
レスポンスは JSON 形式で返され、トランスクリプト本文を含む text フィールドと、利用状況を示す usage オブジェクトが含まれます。usage オブジェクトには、音声の秒数、トークン数、およびリクエストにかかるドル単価が記録されます。
この API は 1 リクエストで完結するため、ポーリングやジョブ ID の追跡は不要です。レスポンスボディに即座にトランスクリプト結果が返ってきます。

リクエストボディには、モデル名と入力音声オブジェクト(input_audio)を含めます。input_audio 内では、ファイルを Base64 データとして格納し、フォーマットを文字列で指定します。必要に応じて、言語のヒントや温度パラメータ、プロバイダーブロックを追加することも可能です。以下に、一連の流れを示します。
ファイルを Base64 にエンコードして POST 送信する
AUDIO_B64=$(base64 -i meeting.mp3 | tr -d '\n')
curl https://openrouter.ai/api/v1/audio/transcriptions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/whisper-1",
"input_audio": { "data": "'"$AUDIO_B64"'", "format": "mp3" },
"language": "en"
}'
import base64
import os
import requests
with open("meeting.mp3", "rb") as f:
audio_b64 = base64.b64encode(f.read()).decode("utf-8")
api_key = os.environ["OPENROUTER_API_KEY"]
response = requests.post(
"https://openrouter.ai/api/v1/audio/transcriptions",
headers={"Authorization": f"Bearer {api_key}"},
json={
"model": "openai/whisper-1",
"input_audio": {"data": audio_b64, "format": "mp3"},
"language": "en",
},
)
print(response.json()["text"])
import { OpenRouter } from '@openrouter/sdk';
import { readFileSync } from 'fs';
const openRouter = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });
const audioB64 = readFileSync('meeting.mp3').toString('base64');
必ず JSON 形式で返してください。translation フィールドのみ。他のフィールドは一切追加しないこと — 余計なフィールドを書こうとして本文がトークン上限で打ち切られる事故を防ぐため:
{"translation": "リライト全文"}
const result = await openRouter.stt.createTranscription({
sttRequest: {
model: 'openai/whisper-1',
inputAudio: { data: audioB64, format: 'mp3' },
language: 'en',
},
});
console.log(result.text);
利用可能な音声認識モデルについて
利用可能なモデルは大きく分けて2つのファミリーから選べます。openai/whisper-1 に代表される Whisper クラスのモデルは、音声の秒数に応じて課金されます。一方、比較的新しい音声認識モデルはトークン単位の課金となります。
どちらを選ぶべきかは、求められる精度、対応する言語の種類、そして予算によって決まります。
音声認識(STT)モデルの ID は、デフォルトの /api/v1/models カタログには表示されません。これは当然のことです。なぜなら、トランスクリプションは出力モダリティの一つであり、それをフィルタリングして検索する必要があるからです。
curl "https://openrouter.ai/api/v1/models?output_modalities=transcription" \
-H "Authorization: Bearer $OPENROUTER_API_KEY"
このコマンドを実行すると、利用可能な音声認識モデルとその現在の単価一覧が取得できます。同様のリストは Speech-to-Text collection ページでも確認可能ですし、model catalog では最新の単価情報をリアルタイムで閲覧できます。
実際に接続する前にモデルを試したい場合は、OpenRouter Playground を利用しましょう。ブラウザ上でファイルをアップロードしてトランスクリプションを実行できるため、手軽に動作確認が可能です。
項目ごとのリクエスト仕様
一連の処理フローは、以下の 3 ステップで構成されます。まずファイルを base64 エンコードし、モデルとフォーマットを指定して POST リクエストを送信します。その後、レスポンスからテキストデータと使用量情報を取得すれば完了です。
注意すべき点として、data フィールドには生データの base64 バイト列を渡す必要があります。"data:audio/mp3;base64," というプレフィックスは付与しないでください。また、format フィールドは必須であり、これがアップストリームのモデルに対してバイト列のデコード方法を指示します。
各パラメータの詳細は以下の通りです。
- model(必須): STT モデルのスラッグ名。例:openai/whisper-1
- input_audio.data(必須): base64 形式の音声データ(生バイト列)。"data:" URI は使用不可
- input_audio.format(必須): 対応フォーマットのいずれか。wav、mp3、flac、m4a、ogg、webm、aac のいずれかを指定
- language(任意): ISO-639-1 コード(例:en, es)。省略すると自動検出されます
- temperature(任意): サンプリング温度。0 から 1 の範囲で設定
- response_format(任意): json(デフォルト)または verbose_json。verbose_json を指定すると、タスク、言語、持続時間、セグメントのタイムスタンプが含まれます(OpenAI 互換プロバイダーのみ対応)
- timestamp_granularities(任意): verbose_json の場合、["segment"] または ["word"] を指定可能。["word"] を選んだ場合、words アレイ内に単語レベルのタイムスタンプが追加されます
- provider(任意): プロバイダー固有のオプションをパススルー(例:Groq のプロンプト)。このエンドポイントではリクエストごとのルーティング制御は適用されません。
本エンドポイントは、OpenAI 仕様の multipart/form-data アップロード(ファイルとモデルのセット)も受け付けます。ただしサイズ制限は 25 MB です。すでに OpenAI の /v1/audio/transcriptions エンドポイント向けにクライアントを構築している場合、ベース URL を https://openrouter.ai/api/v1 に変更するだけで、追加の変更なしで動作します。
ファイルサイズが 25 MB を超える場合は、base64 経由の JSON パスを使用してください。
言語指定はオプションです。指定しなくてもモデルが自動検出しますが、短くノイズの多い音声クリップでは曖昧さを減らすために明示的に設定すると安心です。
一部のプロバイダーは独自の追加パラメータを provider 経由で受け付けます。例えば Groq では、期待する語彙を指定するためのプロンプトを provider.options.groq.prompt で渡せます。これにより、モデルが誤って変換しやすい固有名詞や専門用語の扱いを改善できます。
レスポンスと利用量の計上
レスポンスは JSON 形式で、テキスト文字列と利用状況を示すオブジェクトを含みます。この usage オブジェクトによって、推定ではなく各リクエストごとの実際の使用量を正確に把握・管理できます。
{
"text": "Thanks everyone for joining. Let's start with the Q3 numbers.",
"usage": {
"seconds": 9.2,
"total_tokens": 113,
"input_tokens": 83,
"output_tokens": 30,
"cost": 0.000508
}
}
このコスト値はドキュメントの例であり、実際の料金はモデルの種類や音声の長さによって異なります。usage オブジェクトには、音声の秒数(再生時間)、トークン数(総数・入力・出力別)、そしてドル建てのコストが報告されます。
また、レスポンスには X-Generation-Id ヘッダーが含まれており、特定の要求を追跡したり後でデバッグしたりする際に利用できます。
文字起こしと音声入力の使い分け
音声をテキストに変換したい場合は /audio/transcriptions エンドポイントを使用します。一方、モデルに音声の内容を推論させたい場合は、チャット機能の音声入力(audio input)を利用してください。
トランスクリプションエンドポイントは、会議の議事録作成、音声コマンドの実行、キャプション生成、通話やポッドキャストの検索可能なアーカイブ構築などに適しています。
サポートコールでの感情分析(センチメント分析)を行いたい場合、発言内容に関する Q&A を実行したい場合、あるいは他のモダリティと組み合わせたオーディオを単一のプロンプトで処理したい場合は、/chat/completions エンドポイントの input_audio コンテンツタイプを使用してください。
テキストから音声への変換は、これとは別に用意された別のエンドポイントで行います。

- 音声をテキスト(トランスクリプト)に変換したい場合 → POST /api/v1/audio/transcriptions(JSON 形式のテキストと使用量情報)
- オーディオに対して推論を行い、感情分析や Q&A、マルチモーダル処理を行いたい場合 → /chat/completions の input_audio を使用(チャット完了レスポンス)
オーディオ解析および音声合成に関する詳細は、audio APIs 発表記事をご覧ください。
トランスクリプションにおけるプロバイダールーティングの仕組みは?
トランスクリプションもチャットと同様のルーティングレイヤーを使用します。1 つのモデルを複数のプロバイダーがホストしている場合、料金を基準に負荷分散を行いながらリクエストを各プロバイダーへ振り分けます。これにより、特定のベンダーに依存することなく利用できます。
ただし、トランスクリプションでは現在、リクエストごとのルーティング制御機能は提供されていません。チャット呼び出しで設定する order(順序)、allow_fallbacks(フォールバック許可)、data_collection(データ収集)、sort(ソート)といったフィールドは、/api/v1/audio/transcriptions エンドポイントでは適用されません。
このエンドポイントの provider ブロックには、プロバイダー固有の設定オプションが記載されます。
このリクエストは、OpenRouter や API、文字起こしといった固有名詞を誤って処理してしまうのを防ぐため、Groq に語彙のヒントを提供します。オプションはプロバイダーのスラッグでキー付けされており、一致したプロバイダーのオプションのみが転送されます。特定のプロバイダーを固定したり、文字起こしごとにデータポリシーを強制したい場合、その制御機能はまだこのエンドポイントでは利用できません。完全なプロバイダーオブジェクトの詳細は、プロバイダールーティングドキュメント で確認できます。
OpenRouter は プロバイダーごとの価格設定 を表示していないため、カタログレートが実際の請求額となります。また、「ゼロ・コンプリーション・インシュアランス(失敗した文字起こしは課金されない)」により、文字起こしが失敗した場合でも請求されません。すでにプロバイダーとの契約がある場合、BYOK を利用すれば、独自のキー経由でルーティングでき、従量課金のモデルコストではなくプラットフォーム手数料のみを支払うことができます。なお、従量課金プランでは月間 100 万リクエストまで手数料が免除されます。
プランに備えるべき制限は?
文字起こし呼び出しの構成を決定する際、以下の 4 つの制約が影響します:

| 制限 | あなたへの影響 |
|---|---|
| (表の内容は原文に続くため、ここでは省略) |
60 秒のアップストリームタイムアウトは、音声の長さに対する厳格な制限ではなく、処理に要する時間の上限です。そのため、ファイルサイズが大きい uncompressed な録音データでタイムアウトが発生します。長時間の音声は分割して各セグメントを個別に書き起こし、最後にテキストをつなぎ合わせる必要があります。
このエンドポイントでは、音声ファイルを URL で渡すことはできません。base64 形式の JSON データか、OpenAI 仕様に準拠した multipart ファイル(最大 25MB)を送信してください。mp3 や aac などの圧縮フォーマットを使用すれば、データサイズが小さくなり、転送も高速化できます。
SRT や VTT 形式での出力はサポートされていません。これらの形式を指定すると 400 エラーになります。タイムスタンプ情報は、OpenAI 互換プロバイダーを利用する際に verbose_json を指定することで取得可能です。得られたデータから、ご自身で字幕ファイルを生成してください。
対応フォーマットはプロバイダーによって異なります。wav、mp3、flac、m4a、ogg、webm、aac は一般的にサポートされていますが、特定のモデルやプロバイダーではすべてを受け付けるわけではありません。最も安全なデフォルトは wav です。
タイムアウトは音声の長さではなく処理時間を制限するため、クリップの再生時間だけで対応可否を判断することはできません。例えば、一晩続くゲームセッションのような長時間の録音データは、チャンク分割(chunking)が必要です。1 つのリクエストで全てを処理しようとしても失敗します。
キャプション機能については、デフォルトではテキストと使用量のみが返され、タイミング情報は含まれません。response_format を verbose_json に設定すると、セグメントレベルのタイムスタンプを取得できます。さらに timestamp_granularities: ["word"] を指定すれば、単語レベルの詳細なタイムスタンプも得られます。これは OpenAI や Groq、Together などの OpenAI 互換プロバイダーで動作しますが、他のプロバイダーでは 400 エラーとなります。SRT や VTT の出力機能は標準にはないため、取得したタイムスタンプから自分で字幕ファイルを作成する必要があります。
書き起こしリクエストの費用はいくらか?
利用料金はモデルのカタログ価格そのもので、当社のマージンは一切加算されません。各リクエストごとの正確な料金は usage.cost フィールドで確認できます。
Whisper クラスのモデルは音声の秒数に対して課金され、新しいモデルはトークン数に基づいて課金されます。
料率は変動するため、個別のモデルページに最新情報を掲載しており、本記事内で固定値として記載することはありません。各リクエストが実際にいくらだったかは、レスポンスから usage.cost を確認してください。音声認識(STT)モデルは有料サービスのため、API による文字起こしには利用者のクレジット残高から課金されます。
利用を開始するには、まず Playground で対象のモデルがお客様の音声データに適しているか確認し、API 接続を設定します。そして初日から支出を管理できるよう、各リクエストごとの usage.cost を参照してください。
よくある質問
OpenRouter で音声ファイルを文字起こしするには?
base64 でエンコードされた音声データを、モデル名と入力音声オブジェクト(データとフォーマットを含む)と共に /api/v1/audio/transcriptions エンドポイントへ POST 送信します。レスポンスは JSON 形式で、文字列として文字起こし結果(transcript)と、秒数・トークン数・料金を含む usage オブジェクトが含まれます。認証には Chat Completions と同じ Bearer API キーを使用します。
OpenRouter は Whisper をサポートしていますか?
はい、Whisper クラスのモデルは文字起こし用に利用可能です。使用するスラグ(識別子)は openai/whisper-1 です。
音声認識(STT)モデルの ID は、デフォルトの /api/v1/models リストには含まれていません。これらを見つけるには、?output_modalities=transcription でフィルタリングするか、Speech-to-Text コレクション を閲覧してください。
Whisper は音声の秒数に応じて課金されますが、新しい STT モデルはトークン単位での課金となります。
OpenRouter の文字起こしで利用可能なオーディオ形式は?
対応する一般的な形式は、wav、mp3、flac、m4a、ogg、webm、aac です。これらは必須フィールドである input_audio.format に指定します。
ただし、モデルやプロバイダーによってサポート状況が異なるため、すべての形式をすべてのモデルが受け入れるわけではありません。幅広い互換性を確保するには wav が最も安全なデフォルトです。一方、mp3 などの圧縮フォーマットは、データサイズが小さく転送も高速になるという利点があります。
OpenRouter はタイムスタンプや SRT/VTT サブタイトルを返せますか?
タイムスタンプの取得はいくらでも可能です。response_format を verbose_json に設定すればセグメントごとのタイムスタンプが得られ、さらに timestamp_granularities: ["word"] を追加することで、単語レベルのタイムスタンプを words 配列として取得できます。
これは OpenAI や Groq、Together といった OpenAI 互換のプロバイダーで動作しますが、他のプロバイダーではエラー(400)が返されます。SRT/VTT 形式での出力はサポートされていないため、タイムスタンプを取得して自分でサブタイトルファイルを生成する必要があります。
オーディオの長さに制限はあるのでしょうか?
実質的な上限は、約 60 秒のアップストリーム処理タイムアウトであり、固定された音声長さのカップではありません。短〜中程度のクリップであれば、1 つの呼び出しで完了します。長時間の録音については、オーディオをセグメントに分割してそれぞれ文字起こしし、最後にテキストをつなぎ合わせる必要があります。
OpenRouter の転写コストはいくら?
OpenRouter では、モデルのカタログ価格に上乗せ手数料は発生しません。Whisper などの従来の音声認識モデルは音声の再生時間(秒)に対して課金され、より新しい STT(音声テキスト変換)モデルはトークン数に基づいて課金されます。
各レスポンスに含まれる usage.cost フィールドには、そのリクエストにかかった正確なドル額が記載されています。
原文を表示
You’ve got a 40-minute sales call recording, a folder of voice memos, or a user holding down a mic button, and you need a text transcript. The usual approach is to stand up a Whisper server or add a second provider SDK just for speech-to-text, on top of whatever already handles your chat traffic. On OpenRouter you can send the audio to POST /api/v1/audio/transcriptions instead and get back JSON with the transcribed text and a usage object, using the same API key and auth as Chat Completions.
You don’t need a new SDK or a separate service. Because transcription runs on the same platform as your chat traffic, a model hosted by several providers is load-balanced across them automatically instead of being pinned to a single vendor.
Tl;dr
- Transcribe by sending base64-encoded audio to POST /api/v1/audio/transcriptions and reading JSON text plus a usage object off the response. It takes the same Bearer key as Chat Completions.
- Whisper-class models work here (the slug is openai/whisper-1). Newer token-priced speech-to-text (STT) models exist too. Discover them with ?output_modalities=transcription, not the default catalog.
- When a transcription model is hosted by more than one provider, we load-balance across them automatically. The per-request routing controls you use on chat (order, allow_fallbacks, data_collection, sort) are not applied on this endpoint today; the provider block here carries provider-specific options only. Bring-your-own-key (BYOK) routes to your own provider key for the platform fee only.
- The real limits to design around are a 60-second upstream timeout, no audio URLs (send base64 JSON, or an OpenAI-style multipart file up to 25 MB), and no SRT/VTT output. Word and segment timestamps are available with response_format: "verbose_json" on OpenAI-compatible providers.
- Pricing is duration-based or token-based depending on the model, with no provider markup. The usage.cost field returns the actual per-request cost so you can meter spend.
How do you transcribe audio on OpenRouter?
Send base64-encoded audio to POST /api/v1/audio/transcriptions and read the text field off the JSON response. You pass your OpenRouter API key as a Bearer token exactly as you do on a chat call, set a model, and hand it the audio.
The response is JSON with a text string that holds the transcript and a usage object that reports the audio duration in seconds, the token counts, and the dollar cost of the request. You make one request, and the transcript comes back in the response body, so there’s no polling and no job ID to track.

The request body carries a model and an input_audio object. Inside input_audio you put the file as base64 data and a format string. Optionally, you add a language hint, a temperature, and a provider block. Here it is end-to-end:
# Encode the file to base64, then POST it.
AUDIO_B64=$(base64 -i meeting.mp3 | tr -d '\n')
curl https://openrouter.ai/api/v1/audio/transcriptions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/whisper-1",
"input_audio": { "data": "'"$AUDIO_B64"'", "format": "mp3" },
"language": "en"
}'import base64
import os
import requests
with open("meeting.mp3", "rb") as f:
audio_b64 = base64.b64encode(f.read()).decode("utf-8")
api_key = os.environ["OPENROUTER_API_KEY"]
response = requests.post(
"https://openrouter.ai/api/v1/audio/transcriptions",
headers={"Authorization": f"Bearer {api_key}"},
json={
"model": "openai/whisper-1",
"input_audio": {"data": audio_b64, "format": "mp3"},
"language": "en",
},
)
print(response.json()["text"])import { OpenRouter } from '@openrouter/sdk';
import { readFileSync } from 'fs';
const openRouter = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });
const audioB64 = readFileSync('meeting.mp3').toString('base64');
const result = await openRouter.stt.createTranscription({
sttRequest: {
model: 'openai/whisper-1',
inputAudio: { data: audioB64, format: 'mp3' },
language: 'en',
},
});
console.log(result.text);Which speech-to-text models are available?
You can pick from two families of models. Whisper-class models like openai/whisper-1 are priced by duration, per second of audio, while newer speech-to-text models are priced per token. Which one fits depends on your accuracy bar, your language mix, and your budget.
STT model IDs don’t show up in the default /api/v1/models catalog. That’s expected, because transcription is an output modality you filter for.
curl "https://openrouter.ai/api/v1/models?output_modalities=transcription" \
-H "Authorization: Bearer $OPENROUTER_API_KEY"That returns the speech-to-text models with their current per-model pricing. The same list lives in the Speech-to-Text collection if you’d rather read it as a page, and the model catalog carries live per-model rates.
If you want to try a model before you wire it up, the OpenRouter Playground transcribes an uploaded file in-browser.
The field-by-field request contract
The whole flow takes three steps. You base64-encode the file, POST it with a model and a format, and read text and usage off the response. The data field takes raw base64 bytes, not a data: URI, so don’t prefix it with data:audio/mp3;base64,. The format field is required, and it tells the upstream model how to decode those bytes.
ParameterRequiredWhat it is
modelYesSTT model slug, e.g. openai/whisper-1
input_audio.dataYesAudio as base64 (raw bytes, not a data: URI)
input_audio.formatYesOne of wav, mp3, flac, m4a, ogg, webm, aac
languageNoISO-639-1 code (en, es, …). Auto-detected if omitted
temperatureNoSampling temperature, 0 to 1
response_formatNojson (default) or verbose_json, which adds task, language, duration, and segment timestamps (OpenAI-compatible providers only)
timestamp_granularitiesNo["segment"] or ["word"] with verbose_json; word adds word-level timestamps in a words array
providerNoProvider-specific options passthrough (e.g. Groq prompt). Per-request routing controls are not applied on this endpoint
The endpoint also accepts OpenAI-style multipart/form-data uploads (file plus model), capped at 25 MB. If you already have a client built for OpenAI’s /v1/audio/transcriptions, you can point its base URL at https://openrouter.ai/api/v1 and it works unchanged. Files bigger than 25 MB go through the base64 JSON path.
A language hint is optional. If you leave it out, the model detects the language; setting it removes some ambiguity on short or noisy clips. Some providers accept their own extras through provider. Groq, for instance, takes a prompt for expected vocabulary via provider.options.groq.prompt, which helps with proper nouns and jargon the model would otherwise mangle.
The response and its usage accounting
The response is JSON with a text string and a usage object. The usage object is what lets you meter spend per request instead of estimating it.
{
"text": "Thanks everyone for joining. Let's start with the Q3 numbers.",
"usage": {
"seconds": 9.2,
"total_tokens": 113,
"input_tokens": 83,
"output_tokens": 30,
"cost": 0.000508
}
}That cost value is an example from our docs, not a price quote; your actual cost depends on the model and the audio length. The usage object reports seconds (audio duration), the token counts, and cost in dollars. The response also carries an X-Generation-Id header you can log to track or debug a specific request later.
When to use transcription vs. audio input or text-to-speech?
Use /audio/transcriptions when you want audio turned into text, and audio input on chat when you want a model to reason about the audio.
The transcription endpoint fits meeting notes, voice commands, captioning, and searchable archives of calls or podcasts. If you want sentiment on a support call, a Q&A about what was said, or audio mixed with other modalities in one prompt, use the input_audio content type on /chat/completions. Turning text into speech is a third, separate endpoint.

You want…UseYou get
Audio turned into text (a transcript)POST /api/v1/audio/transcriptionsJSON text plus usage
A model to reason about audio (sentiment, Q&A, multimodal)input_audio on /chat/completionsA chat completion
For both audio analysis and text-to-speech, see the audio APIs announcement.
How does provider routing work for transcription?
Transcription uses the same routing layer as chat. When a model is hosted by more than one provider, we distribute your requests across them, load-balanced by price, so you aren’t pinned to a single vendor. What transcription doesn’t expose today is per-request routing control. The order, only, allow_fallbacks, data_collection, and sort fields you’d set on a chat call are not applied on /api/v1/audio/transcriptions. The provider block on this endpoint carries provider-specific options instead:
{
"model": "openai/whisper-large-v3",
"input_audio": { "data": "<base64>", "format": "wav" },
"provider": {
"options": {
"groq": { "prompt": "Expected vocabulary: OpenRouter, API, transcription" }
}
}
}That request passes Groq a vocabulary hint for proper nouns it would otherwise mangle. The options are keyed by provider slug, and only the matched provider’s options are forwarded. If you need to pin a specific provider or enforce a per-request data policy on a transcription, that control isn’t available on this endpoint yet. The full provider object is documented in the provider routing docs.
OpenRouter doesn’t mark up provider pricing, so the catalog rate is what you pay, and Zero Completion Insurance means a transcription that fails isn’t billed. If you already have a provider agreement, BYOK lets you route through your own provider key and pay only our platform fee instead of the per-usage model cost, with the fee waived for the first 1M requests a month on pay-as-you-go.
What are the limits to plan around?
Four constraints shape how you structure a transcription call:

LimitWhat it means for you
60-second upstream timeout~60 seconds of processing time, not a hard cap on audio length. Large or uncompressed recordings are the ones that time out. Split long audio into segments, transcribe each, and stitch the text.
No audio URLsAudio can’t be passed by URL on this endpoint. Send base64 JSON, or an OpenAI-style multipart file up to 25 MB. Compressed formats (mp3, aac) make smaller, faster payloads.
No SRT/VTT outputsrt, vtt, and text response formats are rejected with a 400. Timestamps are available via verbose_json on OpenAI-compatible providers; build subtitle files from those yourself.
Format support varies by providerThe list (wav/mp3/flac/m4a/ogg/webm/aac) is common, but a given model or provider may not accept all of them. wav is the safest default.
Because the timeout caps processing time rather than audio length, a clip’s duration alone doesn’t tell you whether it will fit. A recording that runs for hours, like an overnight game session, needs the chunking treatment; a single call won’t cover it.
For captions, the default response is text plus usage with no timing. Set response_format to verbose_json and you get segment-level timestamps, plus word-level ones if you pass timestamp_granularities: ["word"]. That works on OpenAI-compatible providers (OpenAI, Groq, Together); other providers reject it with a 400. There’s no built-in .srt/.vtt output, so you build the subtitle file from the timestamps yourself.
What does a transcription request cost?
You pay the model’s catalog rate with no markup from us, and the usage.cost field tells you the exact figure per request. Whisper-class models charge per second of audio, and newer models charge per token.
Rates change, so we keep the live figure on each model’s page in the catalog rather than printing one here. Reading usage.cost off the response tells you what each request actually cost. STT models are paid, so API transcription draws on your credit balance.
To get started, confirm a model fits your audio in the Playground, wire up the call, and read usage.cost per request to meter spend from day one.
Frequently asked questions
How do I transcribe audio files with OpenRouter?
Send base64-encoded audio to POST /api/v1/audio/transcriptions with a model and an input_audio object (data plus format). The response is JSON with a text string (the transcript) and a usage object (seconds, tokens, and cost). It uses the same Bearer API key and auth as Chat Completions.
Does OpenRouter support Whisper?
Yes. Whisper-class models are available for transcription, and openai/whisper-1 is the slug to use. STT model IDs aren’t in the default /api/v1/models list, so you discover them by filtering with ?output_modalities=transcription or browsing the Speech-to-Text collection. Whisper is duration-priced, per second of audio; newer STT models price per token instead.
What audio formats does OpenRouter transcription accept?
The common set is wav, mp3, flac, m4a, ogg, webm, and aac, passed in the required input_audio.format field. Support varies by model and provider, so not every model accepts every format. wav is the safest default for broad compatibility; compressed formats like mp3 give smaller, faster payloads.
Can OpenRouter return timestamps or SRT/VTT subtitles?
Timestamps, yes. Set response_format to verbose_json to get segment-level timestamps, and add timestamp_granularities: ["word"] for word-level timestamps in a words array. That works on OpenAI-compatible providers (OpenAI, Groq, Together); other providers reject it with a 400. SRT/VTT output isn’t supported, so build subtitle files from the timestamps yourself.
How long can the audio be?
The practical limit is the roughly 60-second upstream processing timeout, not a fixed audio-length cap. Short and medium clips return in one call. For long recordings, split the audio into segments, transcribe each, and stitch the text together.
How much does transcription cost on OpenRouter?
You pay the model’s catalog rate with no markup. Whisper-class models price per second of audio; newer STT models price per token. The usage.cost field in each response reports the exact dollar cost of that request.
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み