본문으로 건너뛰기

인월드 실시간 음성

그만큼InworldRealtimeVoice클래스는 다음을 사용하여 실시간 전이중 음성 상호작용을 제공합니다.Inworld AI의 실시간 APIWebSocket을 통해. 음성 대 음성, Tool 호출 및 의미론적 음성 활동 감지, MCP Tool 라우팅 및 재생 속도와 같은 Inworld 관련 세션 노브를 지원합니다.

Inworld의 유선 프로토콜은 OpenAI Realtime GA 사양이므로 클라이언트 및 서버 이벤트 이름이 @mastra/voice-openai-realtime과 일치합니다. Provider 수준의 차이점은 엔드포인트(URL에서 클라이언트가 생성한 세션 키 사용), Authorization: Basic <key> 헤더, Inworld 전용 핸들을 위한 형식화된 생성자 session 필드, 그리고 Inworld 확장(STT, TTS, Memory, 백채널, 응답성)을 위한 형식화된 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'
실시간 WebSocket 엔드포인트입니다. 클라이언트가 생성한 세션 키와 프로토콜 매개변수가 자동으로 추가됩니다.

model?:

string
= 'inworld/models/gemma-4-26b-a4b-it'
LLM Router Model ID입니다. URL이 아닌 초기 session.update를 통해 전송됩니다. Inworld 라우터에서 지원하는 모든 Model을 사용할 수 있습니다.

speaker?:

string
= 'Sarah'
음성 합성의 기본 음성 ID입니다. Inworld 카탈로그의 모든 음성을 사용할 수 있습니다.

sessionId?:

string
= 'voice-{Date.now()}'
URL의 key 매개변수로 노출되는 클라이언트 생성 세션 키입니다. 생략하면 타임스탬프 기반 키가 자동으로 생성됩니다.

instructions?:

string
초기 session.update와 함께 전송되는 시스템 Prompt입니다.

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이 열리기 전에 오류가 발생하거나 닫히는 경우 또는 이 제한 시간이 만료되는 경우, 포착되지 않은 소켓 오류 대신 거부된 프로미스로 노출됩니다.

session(타이핑된 손잡이)
session-typed-knobs에 대한 직접 링크

문서화된 Inworld 실시간 옵션에는 형식화된 session 필드를 사용하세요. 필드는 연결 시 기본값(예: speaker에서 설정되는 audio.output.voice)과 조합됩니다.

output_modalities?:

Array<"text" | "audio">
Model이 생성해야 하는 모달리티입니다.

audio.output.voice?:

string
음성 카탈로그 ID입니다. 생략하면 생성자의 speaker가 사용됩니다.

audio.output.speed?:

number
합성된 오디오의 재생 속도 배수입니다(0.25~1.5).

audio.output.model?:

string
Inworld TTS Model입니다(예: "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는 8kHz로 고정됩니다.

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 선택 전략입니다. 구성된 Inworld MCP 서버를 통해 Tool 호출을 라우팅하려면 mcp 변형을 사용하세요.

temperature?:

number
Model의 샘플링 온도입니다.

max_output_tokens?:

number | "inf"
응답당 생성되는 최대 토큰 수입니다.

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
서버 측 Prompt 템플릿에 대한 참조입니다. 지우려면 null을 전달하세요.

providerData(인월드 확장)
providerdata-inworld-extensions에 대한 직접 링크

providerData는 Inworld 관련 실시간 확장을 위한 형식화된 객체입니다. 모든 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: 사용자가 말하는 동안 재생되는 짧은 확인음("어-허")입니다. 오디오는 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이 열리기 전 발생하는 error 또는 close(혹은 connectTimeoutMs의 제한 시간, 기본값 15초를 초과하는 핸드셰이크)는 포착되지 않은 소켓 오류 대신 거부된 프로미스로 노출됩니다. 거부되면 반쯤 열린 소켓이 닫힙니다.

await voice.connect()

보고:Promise<void>

speak()
speak에 대한 직접 링크

Model에 텍스트 메시지를 보내고 오디오 응답을 트리거합니다. 반환된 프로미스는 전체 응답 수명 주기가 완료된 후(이 호출이 트리거한 응답의 response.done)에만 이행되며, 사용자 음성으로 응답이 중단되거나 전송 오류가 발생하면 거부됩니다. 순차적인 speak() 호출이 지원되는 패턴입니다. 동시 호출은 동일한 리스너 풀을 공유하며 응답 고정 순서가 정의되지 않습니다.

input:

string | NodeJS.ReadableStream
음성으로 변환할 텍스트 또는 텍스트 스트림입니다.

options?:

Options
호출별 구성입니다.
Options

speaker?:

string
이 특정 요청에 사용할 음성 ID입니다.

보고:Promise<void>

listen()
listen에 대한 직접 링크

사용자 차례에 따라 단일 오디오 버퍼를 보내고 Model에게 텍스트로만 응답하도록 요청합니다.

audioData:

NodeJS.ReadableStream
전사할 오디오 스트림입니다.

보고:Promise<void>

send()
send에 대한 직접 링크

실시간으로 오디오 데이터를 서버로 스트리밍합니다. 지속적인 마이크 입력에 유용합니다.

audioData:

NodeJS.ReadableStream | Int16Array
스트리밍할 오디오 데이터입니다. Int16Array는 단일 base64 청크로 전송되고, 읽기 가능한 스트림은 청크별로 전달됩니다.

eventId?:

string
각 오디오 청크와 함께 서버로 전달되는 선택적 이벤트 ID입니다.

보고:Promise<void>

updateConfig()
updateconfig에 대한 직접 링크

서버에 session.update를 전송합니다. 형식화된 session 필드는 페이로드에 깊이 병합되며, 생성자의 모든 providerDatasession.providerData 아래에 중첩됩니다.

sessionConfig:

InworldSessionConfig | Record<string, unknown>
적용할 부분 세션 구성입니다.

보고:void

addInstructions()
addinstructions에 대한 직접 링크

다음 connect() 또는 updateConfig() 호출에 사용할 시스템 지침을 설정합니다.

instructions?:

string
Model의 시스템 Prompt입니다.

보고:void

addTools()
addtools에 대한 직접 링크

세션 중에 Model이 호출할 수 있는 Tool을 등록합니다. InworldRealtimeVoice가 Agent에 연결되면 Agent에 구성된 Tool을 자동으로 사용할 수 있습니다.

tools?:

ToolsInput
사용하도록 장착할 Tool 구성입니다.

보고:void

answer()
answer에 대한 직접 링크

Model 응답을 트리거하기 위해 response.create 이벤트를 전송하며, 선택적으로 응답별 옵션을 함께 전달할 수 있습니다.

options?:

Record<string, unknown>
서버로 전달되는 응답 옵션입니다.

보고:Promise<void>

차례대로
차례대로에 대한 직접 링크

commitInput()
commitinput에 대한 직접 링크

버퍼링된 입력 오디오를 사용자 턴으로 수동 커밋합니다. turn_detectionnull로 설정된 경우 눌러서 말하기 또는 수동 턴 전환에 사용하세요.

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에 대한 직접 링크

이벤트 리스너를 등록하고 제거합니다. 보다Events below.

이벤트
이벤트에 대한 직접 링크

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 스트림과 함께 발생합니다. 각 스트림의 .idinterrupted에 절대 나타나지 않는 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
전송 또는 서버 오류가 발생하면 발생합니다.

목소리
목소리에 대한 직접 링크

패키지에는 다음에서 반환된 선별된 음성 ID 세트가 포함되어 있습니다.getSpeakers():

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

Inworld의 음성 카탈로그에 있는 모든 음성 ID를 런타임에 speaker로 전달할 수 있습니다.

메모
메모에 대한 직접 링크

  • API 키는 생성자 옵션 또는 INWORLD_API_KEY 환경 변수를 통해 제공됩니다. 키는 미리 Basic 인코딩되어 있습니다. 다시 인코딩하지 마세요.
  • WebSocket URL에는 ?key=<sessionId>&protocol=realtime이 추가됩니다. Model은 URL이 아니라 초기 session.update를 통해 구성됩니다.
  • 호출별 speak(input, { speaker })는 음성 재정의를 단일 응답에만 적용하고(평면 response.voice 필드를 통해) 세션을 변경하지 않습니다.
  • 오디오 출력은 기본적으로 24kHz PCM16입니다. 8kHz 전화 통신용 audio/pcmuaudio/pcma, 그리고 audio/float32session.audio.output.format을 통해 지원됩니다.
  • send, speak 또는 listen을 호출하기 전에 connect()를 사용하세요. WebSocket이 열리기 전에 전송된 이벤트는 대기열에 저장되며 서버가 session.updated를 확인하면 전송됩니다.
  • WebSocket을 해제하려면 close() 또는 disconnect()로 음성 인스턴스를 닫아야 합니다.
  • sessionaudio.input.turn_detection을 제공하지 않으면 기본값은 의미론적 VAD입니다. 자체 객체로 재정의하거나 null을 전달하여 턴 감지를 완전히 비활성화하세요.
  • audio.input.transcription의 기본값은 { model: 'inworld/inworld-stt-1' }이므로 사용자 측 writing 이벤트가 별도 구성 없이 발생합니다. 자체 객체로 재정의하거나 null을 전달하여 사용자 측 전사를 비활성화하세요.
  • on()off()InworldVoiceEventMap을 기준으로 형식화됩니다. 알려진 이벤트 이름에는 형식화된 콜백 페이로드가 제공됩니다. 알 수 없는 이름은 unknown으로 대체됩니다.