mcpField
O
openrouter-stt

openrouter-stt

github.com/openrouterteam生産性309255 回インストール1 日前に更新
リポジトリ

openrouter-stt について

OpenRouterの音声認識エンドポイントで音声を文字起こしするスキルです。Base64音声を含むJSONリクエストとモデル選択を案内し、文字起こしと使用量情報を取得します。

主な機能

  1. 01Base64音声をJSONで送信
  2. 02完全なスラッグで文字起こしモデルを選択
  3. 03言語と温度の指定
  4. 04プロバイダー固有オプションの送信
  5. 05文字起こしと使用量データの取得

活用シーン

  1. 01録音音声の文字起こし
  2. 02ブラウザー録音音声の処理
  3. 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 で、input_audio: { data, format } の下に Base64 エンコードされた音声を含めます。OpenAI の /v1/audio/transcriptions のように、file フィールドを含む multipart/form-data ではありません。OpenAI SDK をこのエンドポイントに向けないでください。誤った形式のリクエストが送信されます。curl、fetch、または requests を直接使用してください。

1 回の呼び出しで JSON を返す

リクエストとレスポンスはどちらも JSON です。レスポンス本文には次の情報が含まれます。

  • text — 書き起こしテキスト。
  • usage — 常に cost を含みます。プロバイダーは、リクエストの料金設定に応じて、課金対象の音声の seconds またはトークンの内訳(total_tokens、input_tokens、output_tokens)を追加で報告します。両方が含まれるとは限りません。

レスポンスの例(音声の長さに応じて課金するプロバイダー。例:google/chirp-3):

{
  "text": "I used to rule the world.",
  "usage": {
    "seconds": 20,
    "cost": 0.005333
  }
}

レスポンスの例(トークン数に応じて課金するプロバイダー):

{
  "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"

音声認識モデルの検索

モデルエンドポイントを出力モダリティでフィルタリングして、音声認識モデルの一覧を取得します。

curl -sS "https://openrouter.ai/api/v1/models?output_modalities=transcription" \
  | jq '.data[] | {id, name, pricing}'

モデル名にはプロバイダーの名前空間が含まれます。短縮名ではなく、完全なスラッグ(google/chirp-3、openai/whisper-1、openai/whisper-large-v3)を使用してください。

パラメーター

フィールド必須備考
modelはい/api/v1/models?output_modalities=transcription から取得した完全なモデルスラッグ。
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"
      }
    }
  }
}

プロバイダーのスラッグをキーにしたオプションは、そのプロバイダーが一致する場合にのみ転送されます。それ以外のキーは無視されます。利用可能なパススルーキーについては、各プロバイダーの上流ドキュメントを確認してください。

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 で確認してください。

"Invalid base64" を含む 400 エラー、または応答がない場合 — data には base64 のみを指定してください。データ URI(data:audio/wav;base64,...)は指定できません。ブラウザーの FileReader からコピーした場合は、プレフィックスを削除してください。

ZodError を含む 400 エラーの場合 — 必須フィールドが欠落しているか、型が間違っています。リクエスト本文は {"success":false,"error":{"name":"ZodError","message":"[...]"}} のようになります。入れ子になった message の JSON 文字列に、問題のあるパスが示されます(よくあるのは input_audio.data または input_audio.format です)。

413 エラー/リクエストサイズが大きすぎる場合 — base64 にするとバイト数が約 33%増えるため、大きな元ファイルはさらに大きな JSON ペイロードになります。より小さいソースファイル(圧縮形式、低いサンプルレート、または短く切り詰めたクリップ)を使用してください。

モデルが見つからない場合 — /api/v1/models?output_modalities=transcription の完全なスラッグを使用してください(chirp-3 ではなく google/chirp-3)。

参考資料

コメント