你有一份40分钟的销售通话录音、一个装满语音备忘录的文件夹,或者有用户一直按着麦克风按钮,而你需要一份文字转录稿。通常的做法是搭建一个 Whisper 服务器,或者额外接入第二个提供商的 SDK 专门用于语音转文字,而这还要叠加在原本处理聊天流量的方案之上。在 OpenRouter 上,你可以直接把音频发送到 POST /api/v1/audio/transcriptions,就能拿到包含转录文本和 usage 对象的 JSON 响应,使用的 API 密钥和认证方式与 Chat Completions 完全一致。
你不需要新的 SDK,也不需要单独的服务。由于转录与聊天流量运行在同一平台上,由多家提供商托管的模型会自动在它们之间进行负载均衡,而不会固定绑定到单一供应商。
摘要
- 转录方式:将 base64 编码的音频发送到 POST /api/v1/audio/transcriptions,然后从响应中读取 JSON 文本和 usage 对象。它使用与 Chat Completions 相同的 Bearer 密钥。
- Whisper 级别的模型在这里可用(slug 为 openai/whisper-1)。更新的按 token 计费的语音转文字(STT)模型也存在。通过 ?output_modalities=transcription 来发现它们,而不是默认目录。
- 当一个转录模型由多家提供商托管时,我们会自动在它们之间进行负载均衡。你在聊天中使用的按请求路由控制(order、allow_fallbacks、data_collection、sort)目前不适用于此端点;这里的 provider 块仅携带提供商特定选项。自带密钥(BYOK)会路由到你自己的提供商密钥,仅收取平台费用。
- 真正需要围绕设计来考虑的限制是:60 秒的上游超时、不支持音频 URL(发送 base64 JSON,或 OpenAI 风格的多部分文件,最大 25 MB)、以及不支持 SRT/VTT 输出。在兼容 OpenAI 的提供商上,使用 response_format: "verbose_json" 可以获得单词和片段级时间戳。
- 定价根据模型不同,按时长或按 token 计费,无提供商加价。usage.cost 字段返回每次请求的实际成本,方便你计量支出。
如何在 OpenRouter 上转录音频?
将 base64 编码的音频发送到 POST /api/v1/audio/transcriptions,然后从 JSON 响应中读取 text 字段。你像在聊天调用中一样,将 OpenRouter API 密钥作为 Bearer token 传入,设置一个模型,然后把音频交给它。
响应是 JSON 格式,包含一个保存转写文本的 text 字符串,以及一个报告音频时长(秒)、token 数量和请求美元成本的 usage 对象。你只需发起一次请求,转写结果就会在响应体中返回,因此无需轮询,也没有需要跟踪的作业 ID。
请求体包含一个 model 和一个 input_audio 对象。在 input_audio 内部,你把文件作为 base64 数据和一个 format 字符串放入。可选地,你还可以添加语言提示、temperature 和一个 provider 块。以下是完整的端到端示例:
# 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); 有哪些可用的语音转文本模型?
你可以从两个模型系列中选择。Whisper 类模型(如 openai/whisper-1)按音频时长(每秒)计费,而更新的语音转文本模型则按 token 计费。选择哪一种取决于你的准确率要求、语言组合和预算。
STT 模型 ID 不会出现在默认的 /api/v1/models 目录中。这是正常的,因为转写是一种需要筛选的输出模态。
curl "https://openrouter.ai/api/v1/models?output_modalities=transcription" \
-H "Authorization: Bearer $OPENROUTER_API_KEY" 这会返回语音转文本模型及其当前的按模型定价。同样的列表也存在于(网页版)中,如果你更愿意以页面形式阅读的话,而模型目录则提供实时的按模型费率。
如果你想在接入之前先试用某个模型,OpenRouter Playground 可以在浏览器内转写上传的文件。
逐字段的请求规范
整个流程分三步。你对文件进行 base64 编码,将其与 model 和 format 一起 POST 出去,然后从响应中读取 text 和 usage。data 字段接受原始 base64 字节,而不是 data: URI,所以不要给它加上 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,后者会额外返回任务类型、语言、时长和分段时间戳(仅限兼容 OpenAI 的提供商) |
| timestamp_granularities | 否 | 配合 verbose_json 使用,可选 ["segment"] 或 ["word"];选择 word 会在 words 数组中返回词级时间戳 |
| provider | 否 | 提供商特定参数的透传(例如 Groq 的 prompt)。此端点不应用按请求的路由控制 |
该端点还接受 OpenAI 风格的多部分表单数据上传(文件加模型),上限为 25 MB。如果你已有针对 OpenAI 的 /v1/audio/transcriptions 构建的客户端,只需将 base URL 指向 https://openrouter.ai/api/v1 即可原样使用。超过 25 MB 的文件则走 base64 JSON 路径。
语言提示是可选的。如果留空,模型会自动检测语言;设置语言提示可以消除短音频或嘈杂片段中的一些歧义。部分提供商通过 provider 参数接受自己的额外设置。例如,Groq 可以通过 provider.options.groq.prompt 接收预期词汇的提示词,这有助于模型正确处理专有名词和术语,避免出错。
响应及其用量统计
响应是 JSON 格式,包含一个 text 字符串和一个 usage 对象。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 对象会报告秒数(音频时长)、token 数量和美元成本。响应还带有 X-Generation-Id 请求头,你可以记录该 ID,以便日后追踪或调试特定请求。
何时使用转录功能,而非音频输入或文本转语音?
当你需要把音频转成文本时,使用 /audio/transcriptions;当你希望模型对音频进行推理分析时,在聊天中使用音频输入。
转录端点适用于会议记录、语音命令、字幕生成,以及通话或播客的可搜索存档。如果你需要对客服通话进行情感分析、就对话内容进行问答,或将音频与其他模态混合在同一个提示词中,请使用 /chat/completions 上的 input_audio 内容类型。将文本转为语音则是第三个独立的端点。
| 你想要…… | 使用 | 你得到 |
|---|---|---|
| 音频转成文本(转录稿) | POST /api/v1/audio/transcriptions | JSON 文本及用量 |
| 一个能够对音频进行推理的模型(情感分析、问答、多模态) | /chat/completions 接口上的 input_audio 参数 | 一次聊天补全 |
关于音频分析和文本转语音,请参阅音频 API 公告。
转录的提供商路由是如何工作的?
转录使用与聊天相同的路由层。当一个模型由多家提供商托管时,我们会将你的请求分发到这些提供商之间,按价格进行负载均衡,这样你就不会绑定在单一供应商上。目前转录功能尚未开放的是按请求级别的路由控制。你在聊天调用中会设置的 order、only、allow_fallbacks、data_collection 和 sort 字段不会应用于 /api/v1/audio/transcriptions 接口。该端点上的 provider 块携带的是提供商特定的选项:
{
"model": "openai/whisper-large-v3",
"input_audio": { "data": "<base64>", "format": "wav" },
"provider": {
"options": {
"groq": { "prompt": "Expected vocabulary: OpenRouter, API, transcription" }
}
}
} 该请求向 Groq 传递了一个词汇提示,用于处理它原本会弄错的专有名词。这些选项以提供商 slug 为键,只有匹配到的提供商的选项才会被转发。如果你需要在转录中固定某个特定提供商,或强制执行按请求级别的数据策略,该端点目前还不支持这种控制。完整的 provider 对象在提供商路由文档中有详细说明。
OpenRouter 不对提供商价格加价,因此目录中的费率就是你所支付的费用,而“零补全保险”意味着失败的转录不会被计费。如果你已有提供商协议,BYOK 可以让你通过自己的提供商密钥进行路由,并且只需支付我们的平台费用,而无需支付按用量计算的模型成本,且按量付费模式下每月前 100 万次请求免收该费用。
规划时需要考虑哪些限制?
有四个约束条件会影响你如何构建转录调用:
| 限制 | 对你的影响 |
|---|---|
| 60 秒上游超时 | 约 60 秒的处理时间,并非音频长度的硬性上限。大型或未压缩的录音是导致超时的原因。将长音频拆分为片段,分别转录,再拼接文本。 |
| 不支持音频 URL | 该端点不能通过 URL 传递音频。请发送 base64 JSON,或不超过 25 MB 的 OpenAI 风格 multipart 文件。压缩格式(mp3、aac)可生成更小、更快的载荷。 |
| 不支持 SRT/VTT 输出 | srt、vtt 和 text 响应格式会被拒绝并返回 400 错误。在兼容 OpenAI 的提供商上,可通过 verbose_json 获取时间戳;字幕文件需自行根据这些时间戳构建。 |
| 格式支持因提供商而异 | 该列表(wav/mp3/flac/m4a/ogg/webm/aac)是常见的,但特定模型或提供商可能不会全部接受。wav 是最稳妥的默认选择。 |
由于超时限制的是处理时间而非音频长度,因此仅凭片段时长无法判断它是否会被处理。长达数小时的录音(例如通宵游戏会话)需要分块处理;单次调用无法覆盖。
对于字幕,默认响应是文本加用量信息,不含时间信息。将 response_format 设置为 verbose_json,即可获得片段级时间戳;如果同时传入 timestamp_granularities: ["word"],还能获得词级时间戳。这在兼容 OpenAI 的提供商(OpenAI、Groq、Together)上有效;其他提供商会以 400 错误拒绝。没有内置的 .srt/.vtt 输出,因此你需要自行根据时间戳构建字幕文件。
一次转录请求的费用是多少?
你按模型的目录价格付费,我们不收取任何加价,usage.cost 字段会告诉你每次请求的确切费用。Whisper 类模型按音频秒数计费,较新的模型按 token 计费。
费率会变化,因此我们在目录中每个模型的页面上保留实时数据,而不是在此处列出。读取响应中的 usage.cost 可以告诉你每次请求的实际费用。STT 模型是付费的,因此 API 转录会从你的余额中扣费。
要开始使用,请在 Playground 中确认某个模型适合你的音频,接入调用,并从第一天起通过读取每次请求的 usage.cost 来计量支出。
常见问题解答
如何使用 OpenRouter 转录音频文件?
将 base64 编码的音频发送到 POST /api/v1/audio/transcriptions,并附带一个模型和一个 input_audio 对象(包含 data 和 format)。响应是 JSON 格式,包含一个 text 字符串(转录文本)和一个 usage 对象(秒数、token 数和费用)。它使用与 Chat Completions 相同的 Bearer API 密钥和认证方式。
OpenRouter 支持 Whisper 吗?
是的。Whisper 类模型可用于转写,使用的 slug 是 openai/whisper-1。STT 模型 ID 不在默认的 /api/v1/models 列表中,因此你需要通过 `?output_modalities=transcription` 过滤或浏览列表来发现它们。Whisper 按音频时长计费,即每秒音频的价格;较新的 STT 模型则改为按 token 计费。
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 的提供商(OpenAI、Groq、Together);其他提供商会以 400 错误拒绝。不支持 SRT/VTT 输出,因此你需要自行根据时间戳构建字幕文件。
音频最长可以是多少?
实际限制是上游约 60 秒的处理超时,而不是固定的音频长度上限。短片段和中长片段可以在一次调用中返回。对于较长的录音,请将音频拆分为多个片段,分别转写,再将文本拼接起来。
OpenRouter 上的转写费用是多少?
你按模型目录价格付费,不加任何加价。Whisper 类模型按每秒音频计费;较新的 STT 模型按 token 计费。每个响应中的 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/transcriptionsand reading JSON text plus ausageobject 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.costfield 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 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.
| Parameter | Required | What it is |
|---|---|---|
model | Yes | STT model slug, e.g. openai/whisper-1 |
input_audio.data | Yes | Audio as base64 (raw bytes, not a data: URI) |
input_audio.format | Yes | One of wav, mp3, flac, m4a, ogg, webm, aac |
language | No | ISO-639-1 code (en, es, …). Auto-detected if omitted |
temperature | No | Sampling temperature, 0 to 1 |
response_format | No | json (default) or verbose_json, which adds task, language, duration, and segment timestamps (OpenAI-compatible providers only) |
timestamp_granularities | No | ["segment"] or ["word"] with verbose_json; word adds word-level timestamps in a words array |
provider | No | Provider-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… | Use | You get |
|---|---|---|
| Audio turned into text (a transcript) | POST /api/v1/audio/transcriptions | JSON text plus usage |
| A model to reason about audio (sentiment, Q&A, multimodal) | input_audio on /chat/completions | A 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:
| Limit | What 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 URLs | Audio 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 output | srt, 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 provider | The 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 . 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.