> Discover all available pages from the documentation index: https://mastra.zisheng.pro/fr/llms.txt # Fonctionnalités Speech-to-Speech dans Mastra ## Introduction La fonctionnalité Speech-to-Speech (STS) de Mastra fournit une interface standardisée pour des interactions en temps réel auprès de plusieurs fournisseurs. STS permet une communication audio bidirectionnelle continue en écoutant les événements des modèles Realtime. Contrairement à des opérations TTS et STT séparées, STS maintient une connexion ouverte qui traite la parole continuellement dans les deux directions. ## Configuration - **`apiKey`** : votre clé API OpenAI. Par défaut, la variable d’environnement `OPENAI_API_KEY` est utilisée. - **`model`** : l’identifiant du modèle à utiliser pour les interactions vocales en temps réel, par exemple `gpt-5.1-realtime`. - **`speaker`** : l’identifiant vocal par défaut pour la synthèse vocale. Vous pouvez indiquer la voix à utiliser pour la sortie vocale. ```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() ``` ## Utiliser 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) ``` Pour une présentation plus générale des fournisseurs vocaux associés aux Agents, consultez [Voice dans Mastra](https://mastra.zisheng.pro/fr/guides/voice/overview). ## Utiliser des Tools dans des sessions en temps réel Les fournisseurs vocaux en temps réel peuvent utiliser les Tools configurés sur l’Agent. Ajoutez les Tools à la définition de `Agent`, puis connectez-vous et envoyez l’audio via le fournisseur vocal : ```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(), }) ``` ## Écouter les événements en temps réel Les fournisseurs vocaux en temps réel émettent des événements que vous pouvez utiliser pour mettre à jour votre interface, lire l’audio de l’assistant, consigner les transcriptions et gérer les erreurs : ```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) }) ``` Les noms et les charges utiles des événements varient selon le fournisseur. Consultez la section du fournisseur ci-dessous ou sa référence pour obtenir la liste complète des événements. ## Instances vocales par session Une instance `voice` statique est partagée entre toutes les requêtes. Cela fonctionne pour une synthèse vocale ponctuelle, mais les fournisseurs en temps réel et Speech-to-Speech stockent l’état de la session, tel que la connexion WebSocket, les Tools, les instructions et le contexte de requête. Si un Agent gère plusieurs sessions actives simultanément, une instance partagée peut permettre à une session d’écraser l’état d’une autre. Fournissez `voice` sous forme de résolveur lorsque chaque session active a besoin de sa propre instance vocale. Mastra exécute le résolveur à chaque appel de `getVoice()` et retourne une nouvelle instance pour ce contexte de requête : ```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() ``` Lorsque vous utilisez un résolveur : - Chaque appel à `getVoice()` retourne une nouvelle instance ; les sessions concurrentes ne partagent donc pas d’état. - Mastra n’ajoute pas de Tools ni d’instructions à une instance de résolveur. Configurez-les dans le résolveur ou sur le fournisseur. - Vous êtes responsable du cycle de vie de l’instance retournée ; appelez donc `disconnect()` ou `close()` lorsque la session se termine. L’accesseur `agent.voice` n’a pas de contexte de requête ; il lève donc une erreur lorsque `voice` est un résolveur. Utilisez plutôt `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) ``` Remarque : - Live API requiert `GOOGLE_API_KEY`. Vertex AI requiert le projet, l’emplacement et les identifiants du compte de service. - Événements : `speaker` (flux audio), `writing` (texte), `turnComplete`, `usage` et `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) ``` Remarque : - Régions disponibles : `us-east-1`, `us-west-2` et `ap-northeast-1`. - L’authentification passe par la chaîne standard de fournisseurs d’identifiants AWS. Transmettez `credentials` pour la remplacer. - Événements : `speaking` (audio Int16Array), `writing` (texte avec `generationStage`), `toolCall`, `interrupt`, `turnComplete`, `usage`, `session` et `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) ``` Remarque : - Requiert `INWORLD_API_KEY`. Les clés API Inworld sont préencodées en Basic : collez-les telles quelles. - L’URL WebSocket ajoute une valeur `?key=...&protocol=realtime` générée par le client. Le modèle est configuré par le `session.update` initial, et non dans l’URL. - Le protocole filaire d’Inworld est la spécification OpenAI Realtime GA ; les noms des événements correspondent donc à ceux de `@mastra/voice-openai-realtime`. - Les réglages Inworld en temps réel typés, notamment le routage de Tools MCP, le niveau d’empressement VAD sémantique, la vitesse de lecture, le modèle de transcription et les modalités de sortie, sont exposés par le champ constructeur `session`. Une échappatoire `providerData` non typée est également fusionnée en profondeur pour assurer la compatibilité future avec les nouvelles fonctionnalités Inworld. - Événements : `speaker` (flux audio PCM), `speaking` (Buffer audio par delta), `writing` (texte), `conversation.item.added`, `conversation.item.done`, `function_call.arguments`, `tool-call-start`, `tool-call-result` et `error`.