リアルタイム ASR(WebSocket)
リアルタイム ASR は、WebSocket 経由で音声をストリーミングし、発話中に文字起こしを返します。音声がまだ流れている間は暫定的な**部分(partial)結果を、発話ごとに確定的な確定(final)**結果を返します。ライブ字幕、会議の文字起こし、音声インターフェースに利用できます。
完全な音声ファイルを一度に文字起こしする場合は、代わりにバッチ ASR エンドポイントを使用してください。
エンドポイント
wss://api.shisa.ai/ws/asr/realtime
WebSocket ハンドシェイク時に、ASR 用のベアラートークンで認証します:
Authorization: Bearer YOUR_API_KEY
API キーには shisa/asr-realtime サービスへの明示的なアクセス権が必要です。バッチ ASR、チャット、翻訳、TTS へのアクセス権があっても、リアルタイム ASR へのアクセス権は付与されません。キーがサービス許可リストを使用している場合は、shisa/asr-realtime を追加してください。追加されていないと、ハンドシェイクは拒否されます。
リアルタイム ASR はバックエンドでの利用を想定しています。API キーはサーバーサイドに保管してください。ブラウザから自前のサーバーへ音声を中継し、そこから Shisa に接続します。
仕組み
Authorizationヘッダーを付けてエンドポイントに WebSocket を開きます。session.updateメッセージを 1 回送信し、音声形式と言語を設定します。session.createdを待ちます。- 生の音声を base64 の
input_audio.appendメッセージとしてストリーミングします(1 チャンクあたり 50〜250 ms が目安です)。 asr.partial_resultをライブの暫定テキストとして表示し、asr.final_resultが届いたら置き換えます。- 完了したら
session.closeを送信します。
音声の要件
生の PCM を送信してください。コンテナや圧縮は使用しません:
| プロパティ | 値 |
|---|---|
| エンコーディング | pcm_s16le(符号付き 16 ビットリトルエンディアン) |
| サンプルレート | 16000 Hz |
| チャンネル | 1(モノラル) |
| チャンク間隔 | 50〜250 ms 推奨(例では 100 ms) |
送信前にクライアント側でリサンプリングとダウンミックスを行ってください。WAV ヘッダー、Ogg、MP3、データ URL、浮動小数点 PCM、ステレオ音声は送信しないでください。
クライアントメッセージ
session.update
音声を送信する前に、session.update を必ず 1 回送信します。言語を固定するセッションが最もシンプルです:
{
"type": "session.update",
"session": {
"input_audio_format": "pcm_s16le",
"sample_rate": 16000,
"channels": 1,
"language": "ja"
}
}
| フィールド | 必須 | 値 | 備考 |
|---|---|---|---|
input_audio_format | はい | pcm_s16le | 生の符号付き 16 ビットリトルエンディアン PCM。 |
sample_rate | はい | 16000 | 送信前に 16 kHz にリサンプリングします。 |
channels | はい | 1 | モノラルのみ。ステレオは先にダウンミックスします。 |
language | はい | ja、en、zh、auto | 言語が分かっている場合は固定します。自動言語識別には auto を使用します(後述)。 |
default_language | auto 時のみ | ja、en、zh | 検出が確信できない場合のフォールバック。 |
language_detection_mode | auto 時のみ | session、utterance | session は一度だけ検出、utterance はセグメントごとに検出(応用 — 後述)。 |
input_audio.append
音声チャンクを base64 エンコードした PCM としてストリーミングします:
{
"type": "input_audio.append",
"audio": "<base64 pcm_s16le bytes>"
}
session.close
完了したら、セッションを正常にクローズします:
{ "type": "session.close" }
言語識別(任意)
発話される言語が事前に分からない場合は、language: "auto" を設定します。2 つのモードがあります。
セッション検出は、開始直後に一度だけ言語を識別し、セッション全体でその言語を使用します:
{
"type": "session.update",
"session": {
"input_audio_format": "pcm_s16le",
"sample_rate": 16000,
"channels": 1,
"language": "auto",
"default_language": "en",
"language_detection_mode": "session"
}
}
セッションは session.language_detecting を発行し、続いて選択された language を含む session.language_detected を 1 回発行します。
発話単位の検出(language_detection_mode: "utterance")は、発話ごとに個別に言語を検出するため、複数言語が混在する音声に便利です。発話ごとに utterance.language_detected を発行します。このモードはバックエンドで有効化されている必要があり、有効でない場合、セッションは code: "invalid_config" の error を返します。その場合は、固定言語またはセッション検出にフォールバックしてください。
検出が確信を持って選択できない場合は default_language にフォールバックし、イベントには source: "default" と reason(例: no_speech、short_utterance、inconclusive、timeout)が含まれます。asr.final_result.text を常に権威ある結果として扱い、言語イベントだけを根拠に文字起こしを書き換えないでください。
サービスイベント
すべてのイベントは JSON テキストメッセージです。セッション作成後、各イベントには session_id と単調増加する seq が含まれます。
session.created
セッションが受け入れられ、音声の送信を開始できます:
{
"type": "session.created",
"session_id": "asr_sess_...",
"seq": 1,
"format": { "encoding": "pcm_s16le", "sample_rate": 16000, "channels": 1 }
}
発話境界
speech_started と speech_stopped は、各発話の音声区間検出(VAD)の境界を示します:
{
"type": "speech_started",
"session_id": "asr_sess_...",
"seq": 4,
"utterance_id": "utt_0001",
"audio_start_ms": 420
}
{
"type": "speech_stopped",
"session_id": "asr_sess_...",
"seq": 9,
"utterance_id": "utt_0001",
"audio_start_ms": 420,
"audio_end_ms": 2860,
"reason": "vad_endpoint"
}
一般的な停止理由は vad_endpoint、max_buffer、session_close です。
asr.partial_result
進行中の発話の暫定テキストです。utterance_id ごとに最新の部分結果を表示し、前のものを置き換えてください。すべての部分結果を履歴に追加しないでください:
{
"type": "asr.partial_result",
"session_id": "asr_sess_...",
"seq": 7,
"utterance_id": "utt_0001",
"result_id": "utt_0001:p3",
"text": "今日の会議は3時から",
"is_final": false,
"audio_start_ms": 420,
"audio_end_ms": 2260
}
asr.final_result
発話の確定テキストです。表示していた暫定の部分結果を破棄するには replaces を使用します:
{
"type": "asr.final_result",
"session_id": "asr_sess_...",
"seq": 12,
"utterance_id": "utt_0001",
"result_id": "utt_0001:final",
"replaces": ["utt_0001:p1", "utt_0001:p2", "utt_0001:p3"],
"replaces_audio_range_ms": [420, 2860],
"text": "今日の会議は3時からです。",
"is_final": true,
"audio_start_ms": 420,
"audio_end_ms": 2860
}
確定結果は非同期であり、後続の音声イベントより遅れて届くことがあります。非常に長い発話は、追加の continuation_of と overlap_mode メタデータを持つ継続確定結果に分割される場合があります。表示は論理的な audio_start_ms〜audio_end_ms の範囲のみとしてください。
session.usage
利用量は累積です。課金は最新のイベントを使用します。billable_duration は整数秒です:
{
"type": "session.usage",
"session_id": "asr_sess_...",
"seq": 20,
"final": true,
"usage": {
"input_duration": 18.3036875,
"billable_duration": 19,
"utterance_count": 3,
"final_result_count": 3,
"status": "completed",
"final": true
}
}
error
{
"type": "error",
"code": "finalization_failed",
"message": "Finalization failed",
"fatal": false,
"session_id": "asr_sess_...",
"seq": 18,
"utterance_id": "utt_0002"
}
致命的(fatal)エラーの後はクローズが続きます。致命的でない発話エラーの場合、セッションは継続できます。
文字起こしの取り扱い
- 暫定テキストは
utterance_idをキーとして保持します。 - より新しい
asr.partial_resultが届いたら、アクティブな部分結果を置き換えます。 asr.final_resultを受け取ったら、replacesの ID を削除し、確定テキストを確定します。- 空の確定テキストは表示上は無視します(診断用には保持します)。
session.usageを文字起こしテキストとして表示しないでください。
次のステップ
- 完全なファイルの文字起こしはバッチ ASR エンドポイントで行えます。
- サポートされている形式と言語は音声と言語を参照してください。
- 利用がどのように課金されるかは料金を参照してください。