> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-HK/llms.txt # Mastra 的語音轉語音功能 ## 簡介 Mastra 的語音轉語音(STS)功能為跨多個 Provider 的即時互動提供標準化介面。 STS 透過監聽 Realtime 模型的事件,實現持續的雙向音訊通訊。與分開執行 TTS 和 STT 不同,STS 會保持連線開啟,持續處理雙向語音。 ## 設定 - **`apiKey`**:你的 OpenAI API 金鑰。如未提供,會改用 `OPENAI_API_KEY` 環境變數。 - **`model`**:用於即時語音互動的模型 ID(例如 `gpt-5.1-realtime`)。 - **`speaker`**:語音合成的預設語音 ID。你可以指定語音輸出所使用的聲音。 ```typescript const voice = new OpenAIRealtimeVoice({ apiKey: 'your-openai-api-key', model: 'gpt-5.1-realtime', speaker: 'alloy', // Default voice }) // If using default settings the configuration can be simplified to: const voice = new OpenAIRealtimeVoice() ``` ## 使用 STS ```typescript import { Agent } from '@mastra/core/agent' import { OpenAIRealtimeVoice } from '@mastra/voice-openai-realtime' import { playAudio, getMicrophoneStream } from '@mastra/node-audio' const agent = new Agent({ id: 'agent', name: 'OpenAI Realtime Agent', instructions: `You are a helpful assistant with real-time voice capabilities.`, model: 'openai/gpt-5.6-sol', voice: new OpenAIRealtimeVoice(), }) // Connect to the voice service await agent.voice.connect() // Listen for agent audio responses agent.voice.on('speaker', ({ audio }) => { playAudio(audio) }) // Initiate the conversation await agent.voice.speak('How can I help you today?') // Send continuous audio from the microphone const micStream = getMicrophoneStream() await agent.voice.send(micStream) ``` 如需 Agent 語音 Provider 的更全面概覽,請參閱 [Mastra 的語音功能](https://mastra.zisheng.pro/zh-HK/guides/voice/overview)。 ## 在即時工作階段中使用 Tool 即時語音 Provider 可以使用 Agent 上設定的 Tool。請將 Tool 加至 `Agent` 定義,然後連線並透過語音 Provider 傳送音訊: ```typescript import { Agent } from '@mastra/core/agent' import { OpenAIRealtimeVoice } from '@mastra/voice-openai-realtime' import { calculate, search } from '../tools' export const agent = new Agent({ id: 'speech-to-speech-agent', name: 'Speech-to-Speech Agent', instructions: 'You are a helpful assistant with speech-to-speech capabilities.', model: 'openai/gpt-5.6-sol', tools: { search, calculate, }, voice: new OpenAIRealtimeVoice(), }) ``` ## 監聽即時事件 即時語音 Provider 會發出事件,你可以利用這些事件更新 UI、播放助手音訊、記錄轉錄文字及處理錯誤: ```typescript agent.voice.on('speaking', ({ audio }) => { playAudio(audio) }) agent.voice.on('writing', ({ text, role }) => { console.log(`${role}: ${text}`) }) agent.voice.on('error', error => { console.error('Voice error:', error) }) ``` 事件名稱和資料內容因 Provider 而異。完整事件清單請參閱下方相應的 Provider 章節或 Provider 參考文件。 ## 每個工作階段的語音實例 靜態 `voice` 實例會由所有請求共用。這適用於單次文字轉語音,但即時及語音轉語音 Provider 會儲存工作階段狀態,例如 WebSocket 連線、Tool、指示及請求情境。如果一個 Agent 同時處理多個即時工作階段,共用實例可能會令某個工作階段覆寫另一個工作階段的狀態。 當每個即時工作階段都需要自己的語音實例時,請將 `voice` 設為解析器。Mastra 會在每次呼叫 `getVoice()` 時執行解析器,並為該請求情境傳回全新實例: ```typescript import { Agent } from '@mastra/core/agent' import { RequestContext } from '@mastra/core/request-context' import { OpenAIRealtimeVoice } from '@mastra/voice-openai-realtime' export const agent = new Agent({ id: 'support-line', name: 'Support Line', instructions: ({ requestContext }) => `Help user ${requestContext.get('user')}.`, model: 'openai/gpt-5.6-sol', voice: ({ requestContext }) => new OpenAIRealtimeVoice({ apiKey: requestContext.get('apiKey'), }), }) const requestContext = new RequestContext() requestContext.set('user', 'user-123') requestContext.set('apiKey', process.env.OPENAI_API_KEY) const voice = await agent.getVoice({ requestContext }) await voice.connect() ``` 使用解析器時: - 每次呼叫 `getVoice()` 都會傳回新實例,因此並行工作階段不會共用狀態。 - Mastra 不會將 Tool 或指示加入解析器實例。請在解析器內或 Provider 上設定這些項目。 - 你需要自行管理所傳回實例的生命週期,因此請在工作階段結束時呼叫 `disconnect()` 或 `close()`。 `agent.voice` getter 沒有請求情境,因此當 `voice` 是解析器時會擲回錯誤。請改用 `agent.getVoice({ requestContext })`。 ## Google Gemini Live (Realtime) ```typescript import { Agent } from '@mastra/core/agent' import { GeminiLiveVoice } from '@mastra/voice-google-gemini-live' import { playAudio, getMicrophoneStream } from '@mastra/node-audio' const agent = new Agent({ id: 'agent', name: 'Gemini Live Agent', instructions: 'You are a helpful assistant with real-time voice capabilities.', // Model used for text generation; voice provider handles realtime audio model: 'openai/gpt-5.6-sol', voice: new GeminiLiveVoice({ apiKey: process.env.GOOGLE_API_KEY, model: 'gemini-2.0-flash-exp', speaker: 'Puck', debug: true, // Vertex AI option: // vertexAI: true, // project: 'your-gcp-project', // location: 'us-central1', // serviceAccountKeyFile: '/path/to/service-account.json', }), }) await agent.voice.connect() agent.voice.on('speaker', ({ audio }) => { playAudio(audio) }) agent.voice.on('writing', ({ role, text }) => { console.log(`${role}: ${text}`) }) await agent.voice.speak('How can I help you today?') const micStream = getMicrophoneStream() await agent.voice.send(micStream) ``` 注意: - Live API 需要 `GOOGLE_API_KEY`。Vertex AI 需要項目、位置及服務帳戶憑證。 - 事件:`speaker`(音訊串流)、`writing`(文字)、`turnComplete`、`usage` 及 `error`。 ## AWS Nova Sonic (Realtime) ```typescript import { Agent } from '@mastra/core/agent' import { NovaSonicVoice } from '@mastra/voice-aws-nova-sonic' import { playAudio, getMicrophoneStream } from '@mastra/node-audio' const agent = new Agent({ id: 'agent', name: 'Nova Sonic Agent', instructions: 'You are a helpful assistant with real-time voice capabilities.', // Model used for text generation; voice provider handles realtime audio model: 'openai/gpt-5.6-sol', voice: new NovaSonicVoice({ region: 'us-east-1', speaker: 'matthew', // Static credentials are optional. The default AWS credential provider // chain is used when none are passed. }), }) await agent.voice.connect() // Assistant audio is emitted as 16-bit PCM on the `speaking` event agent.voice.on('speaking', ({ audioData }) => { if (audioData) playAudio(audioData) }) agent.voice.on('writing', ({ role, text }) => { console.log(`${role}: ${text}`) }) await agent.voice.speak('How can I help you today?') const micStream = getMicrophoneStream() await agent.voice.send(micStream) ``` 注意: - 可用區域:`us-east-1`、`us-west-2` 及 `ap-northeast-1`。 - 透過標準 AWS 憑證 Provider 鏈進行驗證。傳入 `credentials` 即可覆寫。 - 事件:`speaking`(Int16Array 音訊)、`writing`(包含 `generationStage` 的文字)、`toolCall`、`interrupt`、`turnComplete`、`usage`、`session` 及 `error`。 ## Inworld Realtime ```typescript import { Agent } from '@mastra/core/agent' import { InworldRealtimeVoice } from '@mastra/voice-inworld' import { playAudio, getMicrophoneStream } from '@mastra/node-audio' const agent = new Agent({ id: 'agent', name: 'Inworld Realtime Agent', instructions: 'You are a helpful assistant with real-time voice capabilities.', // Model used for text generation; voice provider handles realtime audio model: 'openai/gpt-5.6-sol', voice: new InworldRealtimeVoice({ apiKey: process.env.INWORLD_API_KEY, model: 'inworld/models/gemma-4-26b-a4b-it', speaker: 'Sarah', // Typed Inworld realtime knobs (semantic VAD, playback speed, etc.) // session: { // audio: { // output: { speed: 1.1 }, // input: { turn_detection: { type: 'semantic_vad', eagerness: 'high' } }, // }, // }, }), }) await agent.voice.connect() agent.voice.on('speaker', stream => { playAudio(stream) }) agent.voice.on('writing', ({ role, text }) => { console.log(`${role}: ${text}`) }) await agent.voice.speak('How can I help you today?') const micStream = getMicrophoneStream() await agent.voice.send(micStream) ``` 注意: - 需要 `INWORLD_API_KEY`。Inworld API 金鑰已預先使用 Basic 編碼,請原樣貼上。 - WebSocket URL 會附加由用戶端產生的 `?key=...&protocol=realtime`。模型透過初始 `session.update` 設定,而不是在 URL 中設定。 - Inworld 的通訊協定採用 OpenAI Realtime GA 規格,因此事件名稱與 `@mastra/voice-openai-realtime` 相符。 - 具類型的 Inworld 即時控制選項(MCP Tool 路由、語意 VAD 靈敏度、播放速度、轉錄模型、輸出模態等)透過 `session` 建構函式欄位公開。另有未設定類型的 `providerData` 後備機制,系統亦會將它深層合併,以便向前兼容 Inworld 的新功能。 - 事件:`speaker`(PCM 音訊串流)、`speaking`(每個 delta 的音訊 Buffer)、`writing`(文字)、`conversation.item.added`、`conversation.item.done`、`function_call.arguments`、`tool-call-start`、`tool-call-result` 及 `error`。