> Discover all available pages from the documentation index: https://mastra.zisheng.pro/ko/llms.txt # 인월드 실시간 음성 그만큼`InworldRealtimeVoice`클래스는 다음을 사용하여 실시간 전이중 음성 상호작용을 제공합니다.[Inworld AI의 실시간 API](https://docs.inworld.ai/realtime/quickstart-websocket)WebSocket을 통해. 음성 대 음성, Tool 호출 및 의미론적 음성 활동 감지, MCP Tool 라우팅 및 재생 속도와 같은 Inworld 관련 세션 노브를 지원합니다. Inworld의 유선 프로토콜은 OpenAI Realtime GA 사양이므로 클라이언트 및 서버 이벤트 이름이 `@mastra/voice-openai-realtime`과 일치합니다. Provider 수준의 차이점은 엔드포인트(URL에서 클라이언트가 생성한 세션 키 사용), `Authorization: Basic ` 헤더, Inworld 전용 핸들을 위한 형식화된 생성자 `session` 필드, 그리고 Inworld 확장(STT, TTS, Memory, 백채널, 응답성)을 위한 형식화된 `providerData` 객체가 `session.providerData`에 있다는 점입니다. 일괄 텍스트 음성 변환 및 음성 텍스트 변환에 대해서는 다음을 참조하세요.[`@mastra/voice-inworld`](https://mastra.zisheng.pro/ko/reference/voice/inworld). ## 사용예 ```typescript 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`): 실시간 WebSocket 엔드포인트입니다. 클라이언트가 생성한 세션 키와 프로토콜 매개변수가 자동으로 추가됩니다. (Default: `'wss://api.inworld.ai/api/v1/realtime/session'`) **model** (`string`): LLM Router Model ID입니다. URL이 아닌 초기 session.update를 통해 전송됩니다. Inworld 라우터에서 지원하는 모든 Model을 사용할 수 있습니다. (Default: `'inworld/models/gemma-4-26b-a4b-it'`) **speaker** (`string`): 음성 합성의 기본 음성 ID입니다. Inworld 카탈로그의 모든 음성을 사용할 수 있습니다. (Default: `'Sarah'`) **sessionId** (`string`): URL의 key 매개변수로 노출되는 클라이언트 생성 세션 키입니다. 생략하면 타임스탬프 기반 키가 자동으로 생성됩니다. (Default: `'voice-{Date.now()}'`) **instructions** (`string`): 초기 session.update와 함께 전송되는 시스템 Prompt입니다. **session** (`Partial`): 형식화된 일급 세션 옵션입니다(audio, tool\_choice, output\_modalities, temperature, ...). 모든 session.update에 깊이 병합되므로 audio.output.voice 및 audio.output.speed 같은 중첩 필드는 서로 덮어쓰지 않고 조합됩니다. 아래의 session 필드를 참조하세요. **debug** (`boolean`): 원시 서버 이벤트를 기록합니다. (Default: `false`) **providerData** (`InworldProviderData`): 형식화된 Inworld 확장 구성입니다(stt, tts, memory, backchannel, responsiveness와 user\_id 및 metadata). 모든 session.update에서 session.providerData 아래에 전송됩니다. session 필드로 설정된 session.providerData와 조합되며, 키가 충돌하면 생성자 옵션이 우선합니다. **connectTimeoutMs** (`number`): connect()가 WebSocket 핸드셰이크와 초기 session.updated 왕복 모두를 기다리는 최대 시간입니다. WebSocket이 열리기 전에 오류가 발생하거나 닫히는 경우 또는 이 제한 시간이 만료되는 경우, 포착되지 않은 소켓 오류 대신 거부된 프로미스로 노출됩니다. (Default: `15000`) ### `session`(타이핑된 손잡이) 문서화된 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 }`): 분산 Trace 구성입니다. 서버 기본값을 사용하려면 "auto"를 사용하고, 그렇지 않으면 Workflow/그룹 이름을 명시적으로 지정하세요. **include** (`Array<"item.input_audio_transcription.logprobs">`): 서버가 발생시키는 이벤트에 포함하도록 선택하는 추가 필드입니다. **prompt** (`string | null`): 서버 측 Prompt 템플릿에 대한 참조입니다. 지우려면 null을 전달하세요. ### `providerData`(인월드 확장) `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`: 기본 응답이 생성되는 동안 재생되는 초기 필러 오디오입니다. 필러 오디오는 일반 오디오의 `speaker` 및 `speaking` 이벤트를 재사용하므로 별도의 이벤트가 없습니다. - `user_id` 및 `metadata`: Inworld로 그대로 전달되는 세션 수준 식별자입니다. ```typescript 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()` WebSocket 연결을 열고 초기 `session.update`를 전송한 다음, 서버가 `session.updated`로 확인하면 완료됩니다. `speak()`, `listen()` 또는 `send()`보다 먼저 호출해야 합니다. WebSocket이 열리기 전 발생하는 `error` 또는 `close`(혹은 `connectTimeoutMs`의 제한 시간, 기본값 15초를 초과하는 핸드셰이크)는 포착되지 않은 소켓 오류 대신 거부된 프로미스로 노출됩니다. 거부되면 반쯤 열린 소켓이 닫힙니다. ```typescript await voice.connect() ``` 보고:`Promise` ### `speak()` Model에 텍스트 메시지를 보내고 오디오 응답을 트리거합니다. 반환된 프로미스는 전체 응답 수명 주기가 완료된 후(이 호출이 트리거한 응답의 `response.done`)에만 이행되며, 사용자 음성으로 응답이 중단되거나 전송 오류가 발생하면 거부됩니다. 순차적인 `speak()` 호출이 지원되는 패턴입니다. 동시 호출은 동일한 리스너 풀을 공유하며 응답 고정 순서가 정의되지 않습니다. **input** (`string | NodeJS.ReadableStream`): 음성으로 변환할 텍스트 또는 텍스트 스트림입니다. **options** (`Options`): 호출별 구성입니다. **options.speaker** (`string`): 이 특정 요청에 사용할 음성 ID입니다. 보고:`Promise` ### `listen()` 사용자 차례에 따라 단일 오디오 버퍼를 보내고 Model에게 텍스트로만 응답하도록 요청합니다. **audioData** (`NodeJS.ReadableStream`): 전사할 오디오 스트림입니다. 보고:`Promise` ### `send()` 실시간으로 오디오 데이터를 서버로 스트리밍합니다. 지속적인 마이크 입력에 유용합니다. **audioData** (`NodeJS.ReadableStream | Int16Array`): 스트리밍할 오디오 데이터입니다. Int16Array는 단일 base64 청크로 전송되고, 읽기 가능한 스트림은 청크별로 전달됩니다. **eventId** (`string`): 각 오디오 청크와 함께 서버로 전달되는 선택적 이벤트 ID입니다. 보고:`Promise` ### `updateConfig()` 서버에 `session.update`를 전송합니다. 형식화된 `session` 필드는 페이로드에 깊이 병합되며, 생성자의 모든 `providerData`는 `session.providerData` 아래에 중첩됩니다. **sessionConfig** (`InworldSessionConfig | Record`): 적용할 부분 세션 구성입니다. 보고:`void` ### `addInstructions()` 다음 `connect()` 또는 `updateConfig()` 호출에 사용할 시스템 지침을 설정합니다. **instructions** (`string`): Model의 시스템 Prompt입니다. 보고:`void` ### `addTools()` 세션 중에 Model이 호출할 수 있는 Tool을 등록합니다. `InworldRealtimeVoice`가 Agent에 연결되면 Agent에 구성된 Tool을 자동으로 사용할 수 있습니다. **tools** (`ToolsInput`): 사용하도록 장착할 Tool 구성입니다. 보고:`void` ### `answer()` Model 응답을 트리거하기 위해 `response.create` 이벤트를 전송하며, 선택적으로 응답별 옵션을 함께 전달할 수 있습니다. **options** (`Record`): 서버로 전달되는 응답 옵션입니다. 보고:`Promise` ### 차례대로 #### `commitInput()` 버퍼링된 입력 오디오를 사용자 턴으로 수동 커밋합니다. `turn_detection`이 `null`로 설정된 경우 눌러서 말하기 또는 수동 턴 전환에 사용하세요. ```typescript voice.commitInput() ``` 보고:`void` #### `clearInput()` 사용자 차례로 커밋하지 않고 버퍼링된 입력 오디오를 삭제합니다. ```typescript voice.clearInput() ``` 보고:`void` #### `clearOutput()` 서버의 전체 출력 오디오 버퍼를 비우고 재생을 중지합니다. 진행 중인 백채널 오디오도 중지됩니다. 기본 끼어들기 경로(`interrupted` 발생 시 `response.cancel`)는 백채널에 안전합니다. 이 경로를 우선 사용하세요. 모든 항목을 비우려는 경우에만 `clearOutput()`을 사용하세요. ```typescript voice.clearOutput() ``` 보고:`void` ### `close()`그리고`disconnect()` 두 방법 모두 WebSocket을 닫고 인스턴스를 연결 해제된 것으로 표시합니다. 보고:`void` ### `getSpeakers()` 패키지에 번들로 제공되는 엄선된 음성 목록을 반환합니다. Inworld의 카탈로그는 이 목록보다 큽니다. 런타임에 모든 음성 ID를 `speaker`로 전달할 수 있습니다. 보고:`Promise>` ### `on()`그리고`off()` 이벤트 리스너를 등록하고 제거합니다. 보다[Events](#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 스트림과 함께 발생합니다. 각 스트림의 .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`): 전송 또는 서버 오류가 발생하면 발생합니다. ## 목소리 패키지에는 다음에서 반환된 선별된 음성 ID 세트가 포함되어 있습니다.`getSpeakers()`: - `Dennis` - `Hades` - `Wendy` - `Edward` - `Olivia` - `Sarah` - `Timothy` - `Priya` - `Ronald` - `Deborah` [Inworld의 음성 카탈로그](https://docs.inworld.ai/quickstart-tts)에 있는 모든 음성 ID를 런타임에 `speaker`로 전달할 수 있습니다. ## 메모 - API 키는 생성자 옵션 또는 `INWORLD_API_KEY` 환경 변수를 통해 제공됩니다. 키는 미리 Basic 인코딩되어 있습니다. 다시 인코딩하지 마세요. - WebSocket URL에는 `?key=&protocol=realtime`이 추가됩니다. Model은 URL이 아니라 초기 `session.update`를 통해 구성됩니다. - 호출별 `speak(input, { speaker })`는 음성 재정의를 단일 응답에만 적용하고(평면 `response.voice` 필드를 통해) 세션을 변경하지 않습니다. - 오디오 출력은 기본적으로 24kHz PCM16입니다. 8kHz 전화 통신용 `audio/pcmu` 및 `audio/pcma`, 그리고 `audio/float32`도 `session.audio.output.format`을 통해 지원됩니다. - send, speak 또는 listen을 호출하기 전에 `connect()`를 사용하세요. WebSocket이 열리기 전에 전송된 이벤트는 대기열에 저장되며 서버가 `session.updated`를 확인하면 전송됩니다. - WebSocket을 해제하려면 `close()` 또는 `disconnect()`로 음성 인스턴스를 닫아야 합니다. - `session`이 `audio.input.turn_detection`을 제공하지 않으면 기본값은 의미론적 VAD입니다. 자체 객체로 재정의하거나 `null`을 전달하여 턴 감지를 완전히 비활성화하세요. - `audio.input.transcription`의 기본값은 `{ model: 'inworld/inworld-stt-1' }`이므로 사용자 측 `writing` 이벤트가 별도 구성 없이 발생합니다. 자체 객체로 재정의하거나 `null`을 전달하여 사용자 측 전사를 비활성화하세요. - `on()` 및 `off()`는 `InworldVoiceEventMap`을 기준으로 형식화됩니다. 알려진 이벤트 이름에는 형식화된 콜백 페이로드가 제공됩니다. 알 수 없는 이름은 `unknown`으로 대체됩니다.