Inworld Realtime Voice
InworldRealtimeVoice クラスは、WebSocket 経由の Inworld AI Realtime API を使用したリアルタイムの全二重 Voice 対話を提供します。音声間通信、Tool 呼び出し、Semantic Voice Activity Detection、MCP Tool ルーティング、再生速度などの Inworld 固有のセッション調整をサポートします。
Inworld のワイヤープロトコルは OpenAI Realtime GA 仕様であるため、クライアントとサーバーのイベント名は @mastra/voice-openai-realtime と一致します。Provider レベルで異なるのは、エンドポイント(URL にクライアント生成のセッションキーを使用)、Authorization: Basic <key> ヘッダー、Inworld 固有の調整に使用する型付き session コンストラクターフィールド、session.providerData で送信する Inworld 拡張(STT、TTS、Memory、バックチャンネル、応答性)用の型付き providerData オブジェクトです。
バッチ Text-to-Speech と Speech-to-Text については、@mastra/voice-inworld を参照してください。
使用例使用例への直接リンク
import { InworldRealtimeVoice } from '@mastra/voice-inworld'
import { playAudio, getMicrophoneStream } from '@mastra/node-audio'
// Initialize with INWORLD_API_KEY from the environment
const voice = new InworldRealtimeVoice()
// Or initialize with explicit configuration
const voiceWithConfig = new InworldRealtimeVoice({
apiKey: 'your-inworld-api-key',
model: 'inworld/models/gemma-4-26b-a4b-it',
speaker: 'Sarah',
instructions: 'You are a helpful voice assistant.',
session: {
audio: {
output: { speed: 1.1 },
input: { turn_detection: { type: 'semantic_vad', eagerness: 'high' } },
},
},
})
// Establish connection
await voice.connect()
// Listen for audio output (PCM16 @ 24 kHz by default)
voice.on('speaker', stream => {
playAudio(stream)
})
voice.on('writing', ({ text, role }) => {
console.log(`${role}: ${text}`)
})
// Convert text to speech
await voice.speak('Hello, how can I help you today?', {
speaker: 'Hades',
})
// Stream microphone audio to the model
const microphoneStream = getMicrophoneStream()
await voice.send(microphoneStream)
// Clean up
voice.close()
Inworld API キーはあらかじめ Basic エンコードされています。
INWORLD_API_KEYにそのまま貼り付けてください。パッケージでは再エンコードしません。
コンストラクターパラメーターコンストラクターパラメーターへの直接リンク
apiKey?:
url?:
model?:
speaker?:
sessionId?:
key パラメーターとして公開されるクライアント生成のセッションキー。省略するとタイムスタンプベースのキーが自動生成されます。instructions?:
session?:
debug?:
providerData?:
session フィールドで設定した session.providerData と合成され、キーが競合した場合はコンストラクターオプションが優先されます。connectTimeoutMs?:
connect() が WebSocket ハンドシェイクと最初の session.updated 往復の両方を待機する最大時間。WebSocket が開く前のエラーや切断、またはこのタイムアウトの期限切れは、未捕捉のソケットエラーではなく reject された Promise として公開されます。session(型付きの調整項目)session-typed-knobsへの直接リンク
ドキュメントに記載された Inworld Realtime オプションには、型付きの session フィールドを使用します。フィールドは接続時のデフォルト値(speaker から設定される audio.output.voice など)と合成されます。
output_modalities?:
audio.output.voice?:
speaker を使用します。audio.output.speed?:
audio.output.model?:
audio.output.format?:
{ type, rate? } オブジェクトを指定します。rate(Hz)は audio/pcm と audio/float32 に適用され(デフォルト 24000)、audio/pcmu と audio/pcma は 8 kHz 固定です。audio.input.format?:
audio.output.format と同じ形式で、コーデック文字列または { type, rate? } オブジェクトです。audio.input.noise_reduction?:
audio.input.transcription?:
{ model: "inworld/inworld-stt-1" } です。prompt は語彙、綴り、スタイルのヒントで文字起こしにバイアスをかけます。上書きするには独自のオブジェクトを指定し、ユーザー側の文字起こしを無効にするには null を設定します。audio.input.turn_detection?:
{ type: "semantic_vad", eagerness: "medium", create_response: true, interrupt_response: true } です。上書きするには独自のオブジェクトを指定し、ターン検出を完全に無効にするには null を設定します。eagerness フィールドは Semantic VAD がユーザーのターンを終了する速さを制御します。low は明確な停止を待ち、high は早く終了します。デフォルトの medium は両者のバランスを取ります。idle_timeout_ms(server_vad だけ)は、サーバーがターンをコミットするまでのアイドル時間を設定します。tool_choice?:
temperature?:
max_output_tokens?:
truncation?:
tracing?:
include?:
prompt?:
providerData(Inworld 拡張)providerdata-inworld-extensionsへの直接リンク
providerData は Inworld 固有の Realtime 拡張用の型付きオブジェクトです。すべての session.update で session.providerData の下に送信され、session フィールドで設定した任意の session.providerData と合成されます。キーが競合した場合はコンストラクターの providerData が優先されます。
5つのブランチと2つのセッションレベルフィールドがあります。
stt:prompt、voice_profile、language_hints、VAD またはターン終了のしきい値などの STT 調整。tts:segmenter_strategy、steering_handling、delivery_mode、conversational、user_turn_modeなどの TTS セグメント化と配信。memory:enabled、turn_interval、max_factsなどの自動ローリング Memory。Inworld は状態をmemoryイベントで返します。backchannel:ユーザーの発話中の短い相づち(「uh-huh」)。音声はbackchannelイベントで届きます。responsiveness:メイン応答の生成中に再生する早期フィラー音声。通常のspeakerとspeakingイベントを再利用するため、個別のイベントはありません。user_idとmetadata:Inworld にそのまま渡されるセッションレベルの識別子。
const voice = new InworldRealtimeVoice({
providerData: {
stt: { voice_profile: true, language_hints: ['en-US'] },
tts: { delivery_mode: 'CREATIVE', segmenter_strategy: 'balanced' },
memory: { enabled: true, turn_interval: 4 },
backchannel: { enabled: true, max_per_turn: 1 },
user_id: 'user-123',
},
})
メソッドメソッドへの直接リンク
connect()connectへの直接リンク
WebSocket 接続を開いて最初の session.update を送信し、サーバーが session.updated で確認すると解決します。speak()、listen()、send() より前に呼び出す必要があります。
WebSocket が開く前の error または close(あるいは connectTimeoutMs、デフォルト15秒を超えるハンドシェイク)は、未捕捉のソケットエラーではなく reject された Promise として公開されます。reject 時には半開きのソケットが閉じられます。
await voice.connect()
戻り値:Promise<void>
speak()speakへの直接リンク
モデルにテキストメッセージを送信して音声応答を開始します。返された Promise は応答のライフサイクル全体(この呼び出しで開始した応答の response.done)が完了した後にだけ解決し、ユーザーの発話によって応答が中断された場合やトランスポートエラーが発生した場合は reject されます。
連続した speak() 呼び出しがサポートされるパターンです。同時呼び出しは同じリスナープールを共有し、応答を固定する順序は未定義です。
input:
options?:
speaker?:
戻り値: Promise<void>
listen()listenへの直接リンク
単一の音声バッファをユーザーのターンとして送信し、テキストだけで応答するようモデルに求めます。
audioData:
戻り値: Promise<void>
send()sendへの直接リンク
音声データをサーバーへリアルタイムでストリーミングします。継続的なマイク入力に役立ちます。
audioData:
eventId?:
戻り値: Promise<void>
updateConfig()updateconfigへの直接リンク
サーバーへ session.update を送信します。型付きの session フィールドはペイロードに深く統合され、コンストラクターの providerData は session.providerData の下にネストされます。
sessionConfig:
戻り値:void
addInstructions()addinstructionsへの直接リンク
次回の connect() または updateConfig() 呼び出しで使用するシステム指示を設定します。
instructions?:
戻り値: void
addTools()addtoolsへの直接リンク
セッション中にモデルが呼び出せる Tool を登録します。InworldRealtimeVoice を Agent に関連付けると、Agent に設定された Tool が自動的に利用可能になります。
tools?:
戻り値: void
answer()answerへの直接リンク
response.create イベントを送信してモデルの応答を開始します。応答ごとのオプションも指定できます。
options?:
戻り値: Promise<void>
ターン交代ターン交代への直接リンク
commitInput()commitinputへの直接リンク
バッファリングされた入力音声をユーザーのターンとして手動でコミットします。turn_detection を null に設定した場合のプッシュツートークまたは手動ターン交代に使用します。
voice.commitInput()
戻り値: void
clearInput()clearinputへの直接リンク
バッファリングされた入力音声をユーザーのターンとしてコミットせずに破棄します。
voice.clearInput()
戻り値: void
clearOutput()clearoutputへの直接リンク
サーバーの出力音声バッファ全体を消去して再生を停止します。処理中のバックチャンネル音声も停止します。デフォルトの割り込みパス(interrupted での response.cancel)はバックチャンネルに影響しないため、そちらを優先してください。すべてを消去する場合だけ clearOutput() を使用します。
voice.clearOutput()
戻り値: void
close() and disconnect()close-and-disconnectへの直接リンク
どちらのメソッドも WebSocket を閉じ、インスタンスを切断済みとしてマークします。
戻り値: void
getSpeakers()getspeakersへの直接リンク
パッケージに同梱された厳選 Voice の一覧を返します。Inworld のカタログにはこの一覧より多くの Voice があり、実行時に任意の Voice ID を speaker に渡せます。
戻り値:Promise<Array<{ voiceId: string }>>
on() and off()on-and-offへの直接リンク
イベントリスナーを登録および削除します。以下のイベントを参照してください。
イベントイベントへの直接リンク
InworldRealtimeVoice クラスは次のイベントを送出します。
speaker:
speaking:
speaking.done:
writing:
speech-started:
input_audio_buffer.speech_started VAD エッジ。speech-stopped:
input_audio_buffer.speech_stopped VAD エッジ。interrupted:
response_id ごとに1回送出されます。割り込み時にメイン応答の再生を停止するために使用します。コールバックは { response_id: string } を受け取ります。メイン応答 ID だけを含み、バックチャンネル ID は含まれません。そのため、対応する speaker ストリームを停止しても backchannel ストリームは再生を続けます。turn-suggestion:
turn-suggestion-revoked:
input-committed:
input-cleared:
input-timeout:
output-audio-started:
output-audio-stopped:
output-audio-cleared:
memory:
backchannel:
.id は interrupted に決して現れない backchannel_id なので、割り込みで停止しない別トラックで再生してください。providerData.backchannel.enabled が必要です。backchannel.done:
backchannel.skipped:
response.created:
response.done:
conversation.item.added:
conversation.item.done:
function_call.arguments:
tool-call-start:
tool-call-result:
error:
VoiceVoiceへの直接リンク
パッケージには、getSpeakers() から返される厳選された Voice ID が含まれています。
DennisHadesWendyEdwardOliviaSarahTimothyPriyaRonaldDeborah
Inworld Voice カタログの任意の Voice ID を実行時に speaker へ渡せます。
注意事項注意事項への直接リンク
- API キーは、コンストラクターオプションまたは
INWORLD_API_KEY環境変数で指定できます。キーはあらかじめ Basic エンコードされています。再エンコードしないでください。 - WebSocket URL には
?key=<sessionId>&protocol=realtimeが追加されます。モデルは URL ではなく、最初のsession.updateで設定されます。 - 呼び出しごとの
speak(input, { speaker })は、Voice の上書きを単一の応答(フラットなresponse.voiceフィールド)だけに適用し、セッションを変更しません。 - 音声出力のデフォルトは 24 kHz の PCM16 です。8 kHz のテレフォニー
audio/pcmuとaudio/pcma、およびaudio/float32もsession.audio.output.formatでサポートされます。 - send、speak、listen を呼び出す前に
connect()を使用してください。WebSocket が開く前に送信されたイベントはキューに入り、サーバーがsession.updatedを確認するとフラッシュされます。 - WebSocket を解放するには、Voice インスタンスを
close()またはdisconnect()で閉じる必要があります。 sessionで指定しない場合、audio.input.turn_detectionのデフォルトは Semantic VAD です。独自のオブジェクトで上書きするか、ターン検出を完全に無効にするにはnullを渡します。audio.input.transcriptionのデフォルトは{ model: 'inworld/inworld-stt-1' }なので、ユーザー側のwritingイベントはそのまま発生します。独自のオブジェクトで上書きするか、ユーザー側の文字起こしを無効にするにはnullを渡します。on()とoff()はInworldVoiceEventMapに対して型付けされます。既知のイベント名では型付きのコールバックペイロードを取得し、不明な名前ではunknownにフォールバックします。