> Discover all available pages from the documentation index: https://mastra.zisheng.pro/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 中的 Voice](https://mastra.zisheng.pro/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) }) ``` 事件名称和 payload 因 Provider 而异。完整事件列表请查看下面的 Provider 部分或相应 Provider 参考。 ## 为每个会话创建语音实例 静态 `voice` 实例会在所有请求间共享。这适用于一次性文本转语音,但实时和语音转语音 Provider 会存储 WebSocket 连接、Tool、instructions 和请求上下文等会话状态。如果一个 Agent 同时处理多个实时会话,共享实例可能会让一个会话覆盖另一个会话的状态。 当每个实时会话都需要自己的语音实例时,请将 `voice` 作为 resolver 提供。Mastra 会在每次调用 `getVoice()` 时运行 resolver,并为该请求上下文返回一个新实例: ```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() ``` 使用 resolver 时: - 每次调用 `getVoice()` 都会返回新实例,因此并发会话不会共享状态。 - Mastra 不会向 resolver 实例添加 Tool 或 instructions。请在 resolver 内部或 Provider 上进行配置。 - 返回实例的生命周期由你管理,因此请在会话结束时调用 `disconnect()` 或 `close()`。 `agent.voice` getter 没有请求上下文,因此当 `voice` 是 resolver 时会抛出错误。请改用 `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 eagerness、播放速度、转录模型、输出模态等)通过 `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`。