跳至主要內容

Inworld Realtime 語音

InworldRealtimeVoice 類別透過 WebSocket 使用 Inworld AI Realtime API,提供即時全雙工語音互動。它支援語音對語音、Tool 呼叫,以及語意語音活動偵測、MCP Tool 路由和播放速度等 Inworld 專用工作階段設定。

Inworld 的線路協定採用 OpenAI Realtime GA 規格,因此用戶端與伺服器事件名稱均與 @mastra/voice-openai-realtime 相符。Provider 層面的差異包括端點(在 URL 中使用由用戶端產生的工作階段密鑰)、Authorization: Basic <key> 標頭、用於 Inworld 專用設定且具型別的 session 建構函式欄位,以及在 session.providerData 下傳送、用於 Inworld 擴充功能(STT、TTS、記憶、回應聲和回應速度)且具型別的 providerData 物件。

如需批次文字轉語音及語音轉文字,請參閱 @mastra/voice-inworld

使用範例
使用範例 的直接連結

src/mastra/index.ts
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?:

string
Inworld API 金鑰。若未提供,則使用 INWORLD_API_KEY 環境變數。密鑰已以 Basic 編碼,並原封不動在 Authorization 標頭中傳送。

url?:

string
= 'wss://api.inworld.ai/api/v1/realtime/session'
即時 WebSocket 端點。系統會自動附加由用戶端產生的工作階段密鑰及協定參數。

model?:

string
= 'inworld/models/gemma-4-26b-a4b-it'
LLM Router 模型 ID。透過初始 session.update 傳送,而非置於 URL。接受 Inworld Router 支援的任何模型。

speaker?:

string
= 'Sarah'
語音合成的預設語音 ID。接受 Inworld 目錄中的任何語音。

sessionId?:

string
= 'voice-{Date.now()}'
由用戶端產生、顯示為 URL key 參數的工作階段密鑰。省略時會自動產生以時間戳記為基礎的密鑰。

instructions?:

string
隨初始 session.update 傳送的系統提示。

session?:

Partial<InworldSessionConfig>
具型別的第一級工作階段選項(audio、tool_choice、output_modalities、temperature 等)。會深層合併至每個 session.update,使 audio.output.voice 和 audio.output.speed 等巢狀欄位互相組合而非覆寫。請參閱下方 session 欄位。

debug?:

boolean
= false
記錄原始伺服器事件。

providerData?:

InworldProviderData
具型別的 Inworld 擴充設定(stt、tts、memory、backchannel、responsiveness,以及 user_id 和 metadata)。每次 session.update 時在 session.providerData 下傳送。它會與透過 session 欄位設定的任何 session.providerData 組合;若鍵值衝突,以建構函式選項為準。

connectTimeoutMs?:

number
= 15000
connect() 等候 WebSocket 交握及初始 session.updated 往返的最長時間。WebSocket 開啟前發生錯誤或關閉,或此逾時期限屆滿,均會以被拒絕的 promise 呈現,而非未捕捉的 socket 錯誤。

session(具型別的設定)
session-typed-knobs 的直接連結

使用具型別的 session 欄位設定文件所列的 Inworld 即時選項。各欄位會與連線時的預設值組合(例如由 speaker 設定的 audio.output.voice):

output_modalities?:

Array<"text" | "audio">
模型應產生的模態。

audio.output.voice?:

string
語音目錄 ID。省略時會使用建構函式的 speaker

audio.output.speed?:

number
合成音訊的播放速度倍數(0.25 至 1.5)。

audio.output.model?:

string
Inworld TTS 模型(例如 "inworld-tts-2")。

audio.output.format?:

InworldAudioFormat
輸出音訊編碼。可以是編解碼器字串(例如 "audio/pcm"、"audio/pcmu"、"audio/pcma"、"audio/float32"),或物件 { type, rate? }rate(Hz)適用於 audio/pcm 及 audio/float32(預設為 24000);audio/pcmu 及 audio/pcma 固定為 8 kHz。

audio.input.format?:

InworldAudioFormat
傳送至伺服器的輸入音訊編碼。格式與 audio.output.format 相同,可以是編解碼器字串或 { type, rate? } 物件。

audio.input.noise_reduction?:

{ type: "near_field" | "far_field" }
在轉錄及 VAD 前套用的輸入降噪模式。

audio.input.transcription?:

{ model?: string; language?: string; prompt?: string }
伺服器端對傳入使用者音訊的轉錄。預設為 { model: "inworld/inworld-stt-1" }prompt 會以詞彙、拼寫或風格提示引導轉錄。提供自訂物件即可覆寫;設為 null 可停用使用者端轉錄。

audio.input.turn_detection?:

InworldTurnDetection | null
語音活動/輪次偵測。預設為 { type: "semantic_vad", eagerness: "medium", create_response: true, interrupt_response: true }。提供自訂物件即可覆寫;設為 null 可完全停用輪次偵測。eagerness 欄位控制語意 VAD 結束使用者輪次的速度:low 會等待更明顯的停頓(較不易被中斷),high 會更快結束輪次(反應較快,但較容易打斷使用者)。預設的 medium 會平衡兩者。idle_timeout_ms(只適用於 server_vad)設定伺服器提交輪次前的閒置時限。

tool_choice?:

string | { type: "function"; name: string } | { type: "mcp"; server_label: string }
Tool 選擇策略。使用 mcp 變體,透過已設定的 Inworld MCP 伺服器路由 Tool 呼叫。

temperature?:

number
模型的取樣溫度。

max_output_tokens?:

number | "inf"
每次回應產生的 token 上限。

truncation?:

"auto" | "disabled" | { type: "retention_ratio"; retention_ratio: number }
對話截斷策略。

tracing?:

"auto" | { workflow_name?: string; group_id?: string; metadata?: Record<string, unknown> }
分散式追蹤設定。使用 "auto" 採用伺服器預設值,或明確指定 Workflow/群組名稱。

include?:

Array<"item.input_audio_transcription.logprobs">
選擇加入伺服器應在發出事件中包含的額外欄位。

prompt?:

string | null
伺服器端提示範本的參照。傳入 null 即可清除。

providerData(Inworld 擴充功能)
providerdata-inworld-extensions 的直接連結

providerData 是用於 Inworld 專用即時擴充功能且具型別的物件。每次 session.update 時都會在 session.providerData 下傳送,並與你透過 session 欄位設定的任何 session.providerData 組合;若鍵值衝突,以建構函式的 providerData 為準。

它有五個分支及兩個工作階段層級欄位:

  • stt: STT 微調,例如 prompt, voice_profile, language_hints, and VAD or end-of-turn thresholds.
  • tts: TTS 分段與傳送,例如 segmenter_strategy, steering_handling, delivery_mode, conversational, and user_turn_mode.
  • memory: 自動滾動記憶,例如 enabled, turn_interval, and max_facts. Inworld 會透過 memory 事件回傳其狀態。
  • backchannel: 使用者說話時的簡短回應聲(「嗯哼」)。音訊會透過 backchannel 事件送達。
  • responsiveness: 產生主要回應期間提早播放的填充音訊。填充音訊會重用一般的 speakerspeaking 事件,因此沒有獨立事件。
  • user_id and 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 開啟前發生的 errorclose(或交握超過 connectTimeoutMs,預設為 15 秒)會以被拒絕的 promise 呈現,而非未捕捉的 socket 錯誤。拒絕時,半開啟的 socket 會關閉。

await voice.connect()

傳回: Promise<void>

speak()
speak 的直接連結

向模型傳送文字訊息並觸發音訊回應。傳回的 promise 只會在完整回應生命週期完成後(即此呼叫所觸發回應的 response.done)完成;若回應被使用者語音中斷或發生傳輸錯誤,則會被拒絕。

支援的模式是依序呼叫 speak()。並行呼叫會共用同一個監聽器集區,而回應綁定次序並未定義。

input:

string | NodeJS.ReadableStream
要轉換為語音的文字或文字串流。

options?:

Options
每次呼叫的設定。
Options

speaker?:

string
此特定要求所使用的語音 ID。

傳回: Promise<void>

listen()
listen 的直接連結

將單一音訊緩衝區作為使用者輪次傳送,並要求模型只以文字回應。

audioData:

NodeJS.ReadableStream
要轉錄的音訊串流。

傳回: Promise<void>

send()
send 的直接連結

即時串流音訊資料至伺服器,適合持續的咪高峰輸入。

audioData:

NodeJS.ReadableStream | Int16Array
要串流的音訊資料。Int16Array 會以單一 base64 區塊傳送;可讀串流則逐個區塊轉送。

eventId?:

string
隨每個音訊區塊轉送至伺服器的可選事件 ID。

傳回: Promise<void>

updateConfig()
updateconfig 的直接連結

向伺服器傳送 session.update。具型別的 session 欄位會深層合併至承載資料,而任何建構函式 providerData 都會置於 session.providerData 下。

sessionConfig:

InworldSessionConfig | Record<string, unknown>
要套用的部分工作階段設定。

傳回: void

addInstructions()
addinstructions 的直接連結

設定下一次呼叫 connect()updateConfig() 時使用的系統指示。

instructions?:

string
模型的系統提示。

傳回: void

addTools()
addtools 的直接連結

註冊模型可在工作階段期間呼叫的 Tool。當 InworldRealtimeVoice 附加至 Agent 時,為該 Agent 設定的 Tool 會自動提供。

tools?:

ToolsInput
要配備的 Tool 設定。

傳回: void

answer()
answer 的直接連結

傳送 response.create 事件以觸發模型回應,亦可選擇加入每次回應的選項。

options?:

Record<string, unknown>
轉送至伺服器的回應選項。

傳回: 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 的直接連結

傳回套件隨附的精選語音清單。Inworld 目錄包含更多語音;執行時可將任何語音 ID 傳給 speaker

傳回: Promise<Array<{ voiceId: string }>>

on() and off()
on-and-off 的直接連結

註冊及移除事件監聽器。請參閱下方的事件

事件
事件 的直接連結

InworldRealtimeVoice 類別會發出以下事件:

speaker:

event
每次回應發出一次,並提供 PCM 音訊的 PassThrough 串流。將音訊管接至播放器時使用此事件。

speaking:

event
每個音訊增量都會發出。回呼會收到 { audio: Buffer, response_id: string }。

speaking.done:

event
回應的音訊輸出完成時發出。回呼會收到 { response_id: string }。

writing:

event
轉錄文字可用時發出。回呼會收到 { text: string, response_id: string, role: "assistant" | "user", voiceProfile? }。同一回應中的音訊轉錄及文字增量會去除重複項目,因此單一回應只會發出一個串流。在使用者事件中,啟用 providerData.stt.voice_profile 時會包含 voiceProfile。

speech-started:

event
來自伺服器的原始 input_audio_buffer.speech_started VAD 邊緣事件。

speech-stopped:

event
來自伺服器的原始 input_audio_buffer.speech_stopped VAD 邊緣事件。

interrupted:

event
合成的用戶端訊號:使用者開始說話時,針對每個進行中的 response_id 發出一次。插話時可用它停止播放主要回應。回呼會收到 { response_id: string }。它只帶有主要回應 ID,絕不會帶有回應聲 ID,因此停止相符的 speaker 串流後,backchannel 串流仍會繼續播放(回應聲原本就會與使用者語音重疊,絕不會因插話而取消)。

turn-suggestion:

event
已緩衝使用者話語的智能輪次端點提示。回呼會收到 { item_id, utterance_index, probability, trailing_silence_ms?, audio_duration_ms?, inference_ms? }。

turn-suggestion-revoked:

event
先前發出的輪次建議已撤回。回呼會收到 { item_id, utterance_index }。

input-committed:

event
已緩衝的輸入音訊已提交為使用者輪次(透過 commitInput() 或自動 VAD)。回呼會收到 { item_id, previous_item_id? },其中 previous_item_id 可以是 null。

input-cleared:

event
已緩衝的輸入音訊已捨棄(透過 clearInput())。回呼會收到 {}。

input-timeout:

event
伺服器 VAD 閒置逾時已提交使用者輪次。回呼會收到 { audio_start_ms, audio_end_ms, item_id }。

output-audio-started:

event
伺服器開始發出輸出音訊。回呼會收到 {}。

output-audio-stopped:

event
伺服器停止為目前回應發出輸出音訊。回呼會收到 {}。

output-audio-cleared:

event
伺服器輸出音訊緩衝區已清除並停止播放(透過 clearOutput())。回呼會收到 {}。

memory:

event
連同 Inworld 的滾動摘要及事實狀態發出,並按版本去除重複項目。需要 providerData.memory.enabled。回呼會收到 InworldMemoryState。

backchannel:

event
連同回應聲 PCM 音訊的 PassThrough 串流發出(使用者說話時的簡短回應聲)。每個串流的 .id 都是絕不會出現在 interrupted 中的 backchannel_id,因此請在不會因插話而停止的獨立音軌上播放。需要 providerData.backchannel.enabled。

backchannel.done:

event
回應聲完成時發出。回呼會收到 { backchannel_id: string, phrase? }。

backchannel.skipped:

event
決策器在產生任何音訊前略過回應聲時發出。回呼會收到 { reason: string }。

response.created:

event
新回應開始時發出。回呼會收到完整的伺服器事件。

response.done:

event
回應完成時發出。回呼會收到完整的伺服器事件。

conversation.item.added:

event
附加新對話項目時發出。

conversation.item.done:

event
對話項目完成時發出。

function_call.arguments:

event
連同完整的 Tool 呼叫引數發出。回呼會收到 { call_id, name, arguments }。

tool-call-start:

event
執行已註冊的 Tool 前發出。

tool-call-result:

event
已註冊的 Tool 傳回後發出。

error:

event
發生傳輸或伺服器錯誤時發出。

語音
語音 的直接連結

套件包含一組由 getSpeakers() 傳回的精選語音 ID:

  • Dennis
  • Hades
  • Wendy
  • Edward
  • Olivia
  • Sarah
  • Timothy
  • Priya
  • Ronald
  • Deborah

執行時可將 Inworld 語音目錄中的任何語音 ID 傳給 speaker

注意事項
注意事項 的直接連結

  • API 金鑰可透過建構函式選項或 INWORLD_API_KEY 環境變數提供。密鑰已預先以 Basic 編碼,請勿重新編碼。
  • WebSocket URL 會附加 ?key=<sessionId>&protocol=realtime。模型透過初始 session.update 設定,而非 URL。
  • 每次呼叫的 speak(input, { speaker }) 會將語音覆寫限制於單一回應(透過扁平的 response.voice 欄位),不會變更工作階段。
  • 音訊輸出預設為 24 kHz PCM16。亦可透過 session.audio.output.format 使用 8 kHz 電話音訊 audio/pcmuaudio/pcmaaudio/float32
  • 在任何 send、speak 或 listen 呼叫前使用 connect()。WebSocket 開啟前傳送的事件會排入佇列,待伺服器確認 session.updated 後送出。
  • 必須使用 close()disconnect() 關閉語音執行個體,以釋放 WebSocket。
  • session 未提供,audio.input.turn_detection 預設為語意 VAD。可使用自訂物件覆寫,或傳入 null 完全停用輪次偵測。
  • audio.input.transcription 預設為 { model: 'inworld/inworld-stt-1' },因此使用者端 writing 事件無需額外設定即可觸發。可使用自訂物件覆寫,或傳入 null 停用使用者端轉錄。
  • on()off()InworldVoiceEventMap 定型。已知事件名稱會產生具型別的回呼承載資料;未知名稱則回退至 unknown