跳至主要內容

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 建構函式欄位,以及用於 Inworld 擴充功能(STT、TTS、記憶體、反饋語和回應速度)的具型別 providerData 物件;此物件會在 session.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'
Realtime 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 Realtime 選項。欄位會與連線時的預設值組合(例如從 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> }
分散式 Trace 設定。使用 "auto" 採用伺服器預設值,或明確指定 Workflow/群組名稱。

include?:

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

prompt?:

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

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

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

它包含五個分支和兩個工作階段層級的欄位:

  • stt:STT 微調,例如 promptvoice_profilelanguage_hints,以及 VAD 或對話輪次結束閾值。
  • tts:TTS 分段和表達,例如 segmenter_strategysteering_handlingdelivery_modeconversationaluser_turn_mode
  • memory:自動捲動記憶體,例如 enabledturn_intervalmax_facts。Inworld 會透過 memory 事件回傳其狀態。
  • backchannel:使用者說話時的簡短反饋語(「嗯哼」)。音訊會透過 backchannel 事件抵達。
  • responsiveness:主要回應產生時提早播放的填充音訊。填充音訊會重複使用一般的 speakerspeaking 事件,因此沒有獨立事件。
  • user_idmetadata:傳遞給 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()disconnect()
「close-and-disconnect」的直接連結

這兩種方法都會關閉 WebSocket,並將執行個體標記為已中斷連線。

傳回:void

getSpeakers()
「getspeakers」的直接連結

傳回套件內附的精選語音清單。Inworld 的目錄比此清單更大;執行階段可將任何語音 ID 傳入 speaker

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

on()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/pcma,以及 audio/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