Basic Voice Chat Component
Hereβs a complete example of a React component that creates a voice conversation using the useConversation
hook:
import React, { useState } from 'react';
import { type SessionConfig } from '@outspeed/client';
import { useConversation } from '@outspeed/react';
const getEphemeralKeyFromServer = async (config: SessionConfig) => {
const tokenResponse = await fetch('/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(config),
});
const data = await tokenResponse.json();
if (!tokenResponse.ok) {
throw new Error('Failed to get ephemeral key');
}
return data.client_secret.value;
};
const sessionConfig: SessionConfig = {
model: 'outspeed-v1',
instructions: 'You are a helpful but witty assistant.',
voice: 'david', // Voice names must be lowercase. Find more voices at dashboard.outspeed.com
turn_detection: {
type: 'semantic_vad',
},
first_message: 'Hello, how can I assist you with Outspeed today?',
};
export default function VoiceChat() {
const [sessionCreated, setSessionCreated] = useState(false);
const [isConnecting, setIsConnecting] = useState(false);
const conversation = useConversation({
sessionConfig: sessionConfig,
});
const startSession = async () => {
try {
setIsConnecting(true);
const ephemeralKey = await getEphemeralKeyFromServer(sessionConfig);
await conversation.startSession(ephemeralKey);
// Listen for session creation event
conversation.on('session.created', (event) => {
console.log('Session created:', event);
setSessionCreated(true);
setIsConnecting(false);
});
} catch (error) {
console.error('Error starting session:', error);
setIsConnecting(false);
}
};
const endSession = async () => {
try {
await conversation.endSession();
setSessionCreated(false);
} catch (error) {
console.error('Error ending session:', error);
}
};
if (isConnecting) {
return (
<div className="voice-chat">
<h2>Connecting...</h2>
<p>Please wait while we establish the connection.</p>
</div>
);
}
if (sessionCreated) {
return (
<div className="voice-chat">
<h2>ποΈ Voice Chat Active</h2>
<p>You can now speak with the AI assistant!</p>
<button onClick={endSession} className="end-button">
End Session
</button>
</div>
);
}
return (
<div className="voice-chat">
<h2>Voice AI Assistant</h2>
<p>Click the button below to start a voice conversation.</p>
<button onClick={startSession} className="start-button">
Start Voice Chat
</button>
</div>
);
}
Advanced Features
Event Handling
You can listen to various events during the conversation:
// Listen for speech detection
conversation.on('input_audio_buffer.speech_started', () => {
console.log('User started speaking');
});
conversation.on('input_audio_buffer.speech_stopped', () => {
console.log('User stopped speaking');
});
// Listen for AI responses
conversation.on('response.text.delta', (event) => {
console.log('AI response text:', event.delta);
});
conversation.on('response.audio_transcript.delta', (event) => {
console.log('AI speech transcript:', event.delta);
});
Text Input
You can also send text messages programmatically:
const sendTextMessage = () => {
conversation.sendText('Tell me about the weather today');
};
return (
<div>
{/* ... other components */}
<button onClick={sendTextMessage}>
Send Text Message
</button>
</div>
);
Mute Control
Toggle the microphone on and off:
const [isMuted, setIsMuted] = useState(false);
const toggleMute = () => {
conversation.toggleMute();
setIsMuted(!isMuted);
};
return (
<div>
{/* ... other components */}
<button onClick={toggleMute}>
{isMuted ? 'π Unmute' : 'π€ Mute'}
</button>
</div>
);
Error Handling
Always implement proper error handling for a robust user experience:
const [error, setError] = useState<string | null>(null);
const conversation = useConversation({
sessionConfig: sessionConfig,
onError: (err) => {
console.error('Conversation error:', err);
setError(err.message);
setSessionCreated(false);
setIsConnecting(false);
},
});
// Display error to user
if (error) {
return (
<div className="error-state">
<h2>β Error</h2>
<p>{error}</p>
<button onClick={() => setError(null)}>Try Again</button>
</div>
);
}
Next Steps