关于 openrouter-stt
通过 OpenRouter 语音转文字端点转录音频的技能,说明如何以 JSON 提交 Base64 音频并选择模型,返回转录文本和用量信息。
主要功能
- 01以 JSON 提交 Base64 音频
- 02按完整标识选择转录模型
- 03设置语言和温度
- 04传递提供方专属选项
- 05读取转录文本及用量
适用场景
- 01转录录制的音频
- 02处理浏览器录制的音频
- 03向支持的提供方提供词汇提示
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ openrouterteam/ skills --skill openrouter-stt安装后在 Claude Code 中输入/openrouter-stt确认已加载。
附带文件README.md
详细介绍
OpenRouter 语音转文本
使用 curl 通过 POST /api/v1/audio/transcriptions 转录音频。需要 OPENROUTER_API_KEY(在 https://openrouter.ai/keys 获取)。如果未设置,请停止并询问。
此端点与 OpenAI 不兼容。 请求体是 JSON,音频以 base64 格式放在 input_audio: { data, format } 中,而不是像 OpenAI 的 /v1/audio/transcriptions 那样使用带有 file 字段的 multipart/form-data。不要让 OpenAI SDK 调用此端点;它会发送错误格式的数据。请直接使用 curl、fetch 或 requests。
一次调用,返回 JSON
请求和响应均为 JSON。响应正文包含:
text— 转录文本。usage— 始终包含cost。根据请求的计价方式,提供商还会报告音频计费时长(seconds)或 token 明细(total_tokens、input_tokens、output_tokens)。不要假设两者都会出现。
示例响应(按时长计价的提供商,例如 google/chirp-3):
{
"text": "I used to rule the world.",
"usage": {
"seconds": 20,
"cost": 0.005333
}
}
示例响应(按 token 计价的提供商):
{
"text": "Hello, this is a test of speech-to-text transcription.",
"usage": {
"total_tokens": 113,
"input_tokens": 83,
"output_tokens": 30,
"cost": 0.000508
}
}
即用型工作流
#!/usr/bin/env bash
set -euo pipefail
MODEL="google/chirp-3"
FORMAT="wav" # wav, mp3, flac, m4a, ogg, webm, aac
AUDIO="audio.wav"
BODY=$(mktemp)
PAYLOAD=$(mktemp)
audio_b64=$(base64 < "$AUDIO" | tr -d '\n')
jq -n --arg model "$MODEL" --arg data "$audio_b64" --arg fmt "$FORMAT" \
'{model: $model, input_audio: {data: $data, format: $fmt}}' > "$PAYLOAD"
# --data-binary @file keeps the base64 payload off argv (avoids E2BIG / ARG_MAX).
http_code=$(curl -sS -X POST https://openrouter.ai/api/v1/audio/transcriptions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
--output "$BODY" \
-w '%{http_code}' \
--data-binary @"$PAYLOAD")
if [[ "$http_code" != "200" ]]; then
echo "STT failed (HTTP $http_code):" >&2
cat "$BODY" >&2
rm -f "$BODY" "$PAYLOAD"
exit 1
fi
jq -r '.text' "$BODY"
rm -f "$BODY" "$PAYLOAD"
查找 STT 模型
按输出模态筛选模型端点,即可列出转录模型。
curl -sS "https://openrouter.ai/api/v1/models?output_modalities=transcription" \
| jq '.data[] | {id, name, pricing}'
模型名称包含提供商命名空间 — 请使用完整的 slug(google/chirp-3、openai/whisper-1、openai/whisper-large-v3),而非短名称。
参数
| 字段 | 必填 | 说明 |
|---|---|---|
model | 是 | 来自 /api/v1/models?output_modalities=transcription 的完整模型 slug。 |
input_audio.data | 是 | Base64 编码的原始音频字节。不是数据 URI — 仅使用 base64 负载,不要添加 data:audio/...;base64, 前缀。 |
input_audio.format | 是 | wav、mp3、flac、m4a、ogg、webm 或 aac。必须与实际字节匹配。支持情况因提供商而异。 |
language | 否 | ISO-639-1 代码(en、ja、fr)。省略时会自动检测。 |
temperature | 否 | 0–1。数值越低,结果越稳定。 |
provider | 否 | 提供商透传 — 见下文。 |
选择音频格式
wav/flac— 未压缩或无损格式。质量最高,上传文件也最大。mp3/m4a/aac— 压缩格式。负载更小;这很重要,因为在文件本身大小的基础上,base64 还会使字节数增加约 33%。webm/ogg— 常用于浏览器录音(MediaRecorder)。
format 字段必须与字节的实际容器/编解码器匹配。一个以 .wav 保存、实际却是 mp3 的文件会被拒绝或错误解码。如有疑问,请使用 ffprobe <file> 确认。
提供商专属选项
提供商透传选项放在 provider.options.<slug> 下,且只有在该提供商处理请求时才会转发。示例 — Groq 用于词汇提示的 prompt:
{
"model": "openai/whisper-large-v3",
"input_audio": { "data": "UklGRiQA...", "format": "wav" },
"provider": {
"options": {
"groq": {
"prompt": "Expected vocabulary: OpenRouter, API, transcription"
}
}
}
}
只有提供商匹配时,才会转发以提供商 slug 为键的选项;其他键会被忽略。请查看各提供商的上游文档,了解可用的透传键。
TypeScript(fetch)
import fs from "fs";
const audio = await fs.promises.readFile("audio.wav");
const data = audio.toString("base64");
const res = await fetch("https://openrouter.ai/api/v1/audio/transcriptions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "google/chirp-3",
input_audio: { data, format: "wav" },
}),
});
if (!res.ok) {
throw new Error(`STT failed (HTTP ${res.status}): ${await res.text()}`);
}
const result = await res.json();
console.log(result.text);
Python(requests)
import base64
import os
import requests
with open("audio.wav", "rb") as f:
data = base64.b64encode(f.read()).decode("utf-8")
res = requests.post(
"https://openrouter.ai/api/v1/audio/transcriptions",
headers={
"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
"Content-Type": "application/json",
},
json={
"model": "google/chirp-3",
"input_audio": {"data": data, "format": "wav"},
},
)
if not res.ok:
raise RuntimeError(f"STT failed (HTTP {res.status_code}): {res.text}")
print(res.json()["text"])
故障排除
text 乱码或为空——format 字段可能与实际字节不匹配,或者音频无声或已损坏。使用 ffprobe audio.wav 确认。
返回 400,并提示 "Invalid base64",或静默失败——data 必须只有 base64,不能是数据 URI(data:audio/wav;base64,...)。如果是从浏览器的 FileReader 复制的,请去掉前缀。
返回 400,并提示 ZodError——缺少必填字段,或字段类型错误。请求体格式如下:{"success":false,"error":{"name":"ZodError","message":"[...]"}}——其中嵌套的 message JSON 字符串会指出错误路径(常见的是 input_audio.data 或 input_audio.format)。
413 / 请求过大——base64 会使字节数膨胀约 33%,因此较大的原始文件会变成更大的 JSON 负载。请使用较小的源文件(压缩格式、较低采样率或裁剪后的片段)。
找不到模型——请使用 /api/v1/models?output_modalities=transcription 中的完整 slug(google/chirp-3,而不是 chirp-3)。