openrouter-tts について
openrouter-ttsは、OpenRouterの音声合成エンドポイントを使うためのスキルガイドです。リクエスト設定、音声の検索、出力形式、SDKの利用方法、長文の処理を説明します。
主な機能
- 01OpenRouter経由の音声合成
- 02モデルと対応音声の検索
- 03MP3・PCM出力の説明
- 04プロバイダー固有オプション
- 05長文の分割手順
活用シーン
- 01テキストから音声ファイルを作成
- 02モデルで使える音声の確認
- 03ストリーミング処理向けの音声準備
- 04長い記事や台本の分割合成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ openrouterteam/ skills --skill openrouter-ttsインストール後、Claude Code で/openrouter-ttsを入力して読み込まれたか確認します。
同梱ファイルREADME.md
詳細
OpenRouter Text-to-Speech
curl を使用して POST /api/v1/audio/speech 経由で音声を合成します。このエンドポイントは OpenAI 互換のため、OpenAI SDK は接続先を https://openrouter.ai/api/v1 に設定すれば使用できます。OPENROUTER_API_KEY が必要です(https://openrouter.ai/keys で取得できます)。設定されていない場合は、処理を中止して確認してください。
1 回の呼び出しで音声バイト列を取得
レスポンスの本文は音声バイト列です。response_format に一致する拡張子を付けてファイルに書き込みます。JSON ではありません。エラーレスポンスは JSON なので、ステータスコードが 200 以外の場合に限り、JSON の解析を試みてください。
保持しておくと便利なレスポンスヘッダーは次の 2 つです。
Content-Type— mp3 の場合はaudio/mpeg、pcm の場合はサンプルレートとチャンネル数が含まれます(例:audio/pcm;rate=24000;channels=1)。生のバイト列を WAV コンテナに格納する場合は、これらのパラメーターを解析してください。X-Generation-Id— 生成 ID(形式:gen-tts-<timestamp>-<suffix>)です。追跡、デバッグ、コストの確認に役立ちます。
すぐに使えるワークフロー
#!/usr/bin/env bash
set -euo pipefail
MODEL="openai/gpt-4o-mini-tts-2025-12-15"
VOICE="alloy"
FORMAT="mp3" # mp3 or pcm
INPUT="Hello! This is a text-to-speech test."
OUTPUT="speech-$(date +%Y%m%d-%H%M%S).${FORMAT}"
HEADERS=$(mktemp)
payload=$(jq -n --arg model "$MODEL" --arg input "$INPUT" \
--arg voice "$VOICE" --arg fmt "$FORMAT" \
'{model: $model, input: $input, voice: $voice, response_format: $fmt}')
http_code=$(curl -sS -X POST https://openrouter.ai/api/v1/audio/speech \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-D "$HEADERS" \
--output "$OUTPUT" \
-w '%{http_code}' \
-d "$payload")
if [[ "$http_code" != "200" ]]; then
echo "TTS failed (HTTP $http_code):" >&2
cat "$OUTPUT" >&2 # error body is JSON, not audio
rm -f "$OUTPUT" "$HEADERS"
exit 1
fi
gen_id=$(grep -i '^x-generation-id:' "$HEADERS" | awk '{print $2}' | tr -d '\r')
rm -f "$HEADERS"
echo "Saved $(realpath "$OUTPUT") (generation_id=${gen_id:-unknown})"
TTS モデルと音声の確認
モデルエンドポイントを出力モダリティでフィルターして、音声モデルを一覧表示します。各モデルには、プロバイダーが受け付ける正確な音声 ID を示す supported_voices 配列が含まれています。
# Models + voices in one shot
curl -sS "https://openrouter.ai/api/v1/models?output_modalities=speech" \
| jq '.data[] | {id, name, supported_voices, pricing}'
# Just the voices for a specific model
curl -sS "https://openrouter.ai/api/v1/models?output_modalities=speech" \
| jq -r '.data[] | select(.id=="openai/gpt-4o-mini-tts-2025-12-15") | .supported_voices[]'
音声 ID はプロバイダーごとに異なります。OpenAI は短い名前(alloy、nova)を使用し、Voxtral は言語+ペルソナ+感情を表す形式(en_paul_happy)、Kokoro は言語/性別の接頭辞(af_bella はアメリカ英語の女性 Bella)を使用します。
パラメーター
| フィールド | 必須 | 説明 |
|---|---|---|
model | はい | TTS モデルのスラッグ(例:openai/gpt-4o-mini-tts-2025-12-15、mistralai/voxtral-mini-tts-2603)。 |
input | はい | 合成するテキストです。 |
voice | はい | 音声 ID です。モデルで使用できる正確な一覧は、モデルエンドポイントの supported_voices を確認してください(上記の確認セクションを参照)。音声 ID はプロバイダーごとに異なるため、たとえば alloy は OpenAI の音声であり、Voxtral や Kokoro では使用できません。 |
response_format | いいえ | mp3 または pcm です。デフォルトは pcm です。明示的に設定してください。デフォルトは通常、ユーザーが保存したい形式ではありません。 |
speed | いいえ | 再生速度の倍率(例:1.25)です。OpenAI TTS では反映されます。他のプロバイダーでは受け付けて無視される場合や、不明なフィールドとして拒否される場合があります。重要な場合は、プロバイダーの動作を確認してください。 |
provider | いいえ | プロバイダーへのパススルー設定です。以下を参照してください。 |
形式の選択
mp3(audio/mpeg)— 圧縮形式で、どのオーディオアプリでもすぐに再生できます。ユーザーが聴いたり共有したりするファイルには、通常この形式を選びます。pcm(audio/pcm;rate=<rate>;channels=<n>)— 圧縮されていない生のサンプルです。レスポンスのContent-Typeにはサンプルレートとチャンネル数が含まれます(例:OpenAI TTS ではrate=24000;channels=1)。バイト列を WAV コンテナに格納する場合に必要です。リアルタイムのストリーミングパイプラインでは遅延を抑えられますが、そのままでは再生できません。ユーザーが生の音声を明示的に求めている場合、またはストリーミングシステムにパイプする場合に限り選択してください。
ファイルの拡張子は形式に合わせてください。pcm のバイト列を .mp3 として保存すると、どのプレーヤーでも開けないファイルになります。これは「空または破損した音声」の報告で最もよくある原因です。
プロバイダー固有のオプション
プロバイダーへのパススルー設定は provider.options.<slug> に指定し、そのプロバイダーがリクエストを処理する場合に限り転送されます。特に便利なのは OpenAI の instructions で、再トレーニングすることなく、口調、アクセント、話す速さ、感情を調整できます。
{
"model": "openai/gpt-4o-mini-tts-2025-12-15",
"input": "Welcome to the show.",
"voice": "alloy",
"response_format": "mp3",
"provider": {
"options": {
"openai": {
"instructions": "Speak in a warm, friendly tone with a slow pace."
}
}
}
}
他のプロバイダーについては、利用できるパススルーキーを各プロバイダーの上流ドキュメントで確認してください。命名規則はプロバイダーによって異なります(OpenAI/Google は camelCase、その他の多くは snake_case です)。
OpenAI SDK との互換性
エンドポイントは OpenAI の /audio/speech をミラーしているため、ベース URL を変更するだけで、どちらの OpenAI SDK も動作します。すでに Python/TypeScript プロジェクトを使用していて、シェルコマンドを実行したくない場合は、この方法がおすすめです。
# Python — streaming write to file
import os
from openai import OpenAI
client = OpenAI(base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"])
with client.audio.speech.with_streaming_response.create(
model="openai/gpt-4o-mini-tts-2025-12-15",
input="The quick brown fox jumps over the lazy dog.",
voice="nova",
response_format="mp3",
) as response:
response.stream_to_file("output.mp3")
// TypeScript — collect bytes, write once
import OpenAI from "openai";
import fs from "fs";
const client = new OpenAI({
baseURL: "https://openrouter.ai/api/v1",
apiKey: process.env.OPENROUTER_API_KEY!,
});
const response = await client.audio.speech.create({
model: "openai/gpt-4o-mini-tts-2025-12-15",
input: "The quick brown fox jumps over the lazy dog.",
voice: "nova",
response_format: "mp3",
});
await fs.promises.writeFile(
"output.mp3",
Buffer.from(await response.arrayBuffer()),
);
長い入力
TTS モデルにはリクエストごとの文字数制限(通常は数千文字)があり、料金は入力文字数ごとに設定されているため、分割しても追加料金はかかりません。章、記事、台本など長いテキストを扱う場合は、次の手順に従ってください。
- 文や段落の区切りでテキストを分割します。単語の途中では分割しないでください。
- 抑揚の一貫性を保つため、各チャンクを同じ
modelとvoiceで合成します。 - 生成された音声ファイルを結合します。mp3 の場合、単純なケースでは
ffmpeg -i "concat:part1.mp3|part2.mp3" -c copy out.mp3が使えます。ビットレートが異なる場合や、継ぎ目を目立たなくしたい場合は、ffmpeg -f concat -safe 0 -i list.txt output.mp3で再エンコードしてください。
生成したチャンクをユーザーに順次ストリーミング配信すれば、音声が最初に届くまでの時間も短縮できます。
トラブルシューティング
音声ファイルが空、または再生できない — ほとんどの場合、形式と拡張子が一致していません。レスポンスヘッダーの Content-Type を確認してください。audio/pcm を .mp3 として保存しても再生できません。response_format: "mp3" を指定して再リクエストするか、形式に合った拡張子で保存してください。
"Model X does not exist" という 400 エラー — スラッグが正しくありません。モデルのエンドポイントに記載されている日付付きの完全なスラッグを使用してください(gpt-4o-mini-tts ではなく openai/gpt-4o-mini-tts-2025-12-15)。
ZodError を含む 400 エラー — 必須フィールドが欠けているか、型が正しくありません。リクエストボディは {"success":false,"error":{"name":"ZodError","message":"[...]"}} のようになります。ネストされた message の JSON 文字列に、誤りのあるパス(例:"path":["voice"])が示されています。
speed が反映されない — プロバイダーが対応していない可能性があります。OpenAI TTS はこの設定を反映しますが、ほかのプロバイダーでは、設定に依存する前に上流のドキュメントを確認してください。