7.0 KiB
TTS Voice Selection Fix
Issue
The selected TTS voice was not being used - EVE always used the creepy system default voice instead of the user's selected voice.
Root Causes
- Default value handling - The literal string
"default"was being passed to the voice selection API instead ofundefined - Async voice loading - Browser voices load asynchronously and weren't being properly awaited
- Voice matching - The voice URI wasn't being matched correctly with the available voices
- Prefix handling - Voice IDs with
browser:prefix weren't being stripped before matching
Fixes Applied
1. Fixed Default Voice Handling
Before:
await ttsManager.speak(text, {
voiceId: ttsVoice || undefined, // ❌ "default" is truthy!
})
After:
const voiceId = ttsVoice && ttsVoice !== 'default' ? ttsVoice : undefined
await ttsManager.speak(text, {
voiceId, // ✅ Properly handles "default"
})
2. Fixed Async Voice Loading
Before:
const voices = window.speechSynthesis.getVoices() // ❌ Might be empty!
const voice = voices.find(v => v.voiceURI === options.voiceId)
After:
const getVoicesAsync = (): Promise<SpeechSynthesisVoice[]> => {
return new Promise((resolve) => {
let voices = window.speechSynthesis.getVoices()
if (voices.length > 0) {
resolve(voices)
} else {
// Wait for voices to load
window.speechSynthesis.onvoiceschanged = () => {
voices = window.speechSynthesis.getVoices()
resolve(voices)
}
}
})
}
const voices = await getVoicesAsync() // ✅ Always has voices!
3. Added Debug Logging
Added console logs to help troubleshoot voice selection:
console.log('Available voices:', voices.map(v => `${v.name} (${v.voiceURI})`))
console.log('Looking for voice:', options.voiceId)
console.log('Selected voice:', voice.name, voice.voiceURI)
4. Improved Voice Prefix Handling
if (voiceId.startsWith('browser:')) {
provider = 'browser'
voiceId = voiceId.replace('browser:', '') // ✅ Strip prefix
console.log('Using browser TTS with voice:', voiceId)
}
5. Added Voice Status Indicator
In Settings, shows what type of voice is currently selected:
- "Using system default voice"
- "Using browser voice"
- "Using ElevenLabs voice"
How to Use
Step 1: Open Settings
Click the ⚙️ Settings icon in the top right.
Step 2: Enable TTS
- Scroll to Voice Settings
- Check ✅ Enable text-to-speech for assistant messages
Step 3: Select a Voice
Option A: Use Browser Voices (Free)
- Open TTS Voice Selection dropdown
- Look under Browser Voices (Free)
- Select a voice like:
- "Google US English"
- "Microsoft David"
- "Alex" (macOS)
- etc.
Option B: Use ElevenLabs Voices (Premium)
- Enter your ElevenLabs API key
- Wait for voices to load
- Look under ElevenLabs Voices (Premium)
- Select a voice like:
- "Rachel - American (young)"
- "Adam - American (middle-aged)"
- etc.
Step 4: Test
- Close Settings
- Send a message to EVE
- Click the 🔊 speaker icon on the response
- Should now use your selected voice!
Troubleshooting
Voice Still Not Working
Check Console Logs:
- Open DevTools (F12)
- Go to Console tab
- Look for TTS-related logs:
TTS speak called with: {voiceId: "browser:...", provider: "browser"} Available voices: [...] Looking for voice: ... Selected voice: ...
Common Issues:
-
"Voice not found" warning
- The voice URI doesn't match any available voices
- Try selecting a different voice
- Check that browser voices have loaded
-
No voices in dropdown
- Browser hasn't loaded voices yet
- Try refreshing the page
- Check browser permissions
-
ElevenLabs voices not loading
- Check API key is correct
- Check network connection
- Look for errors in console
Default Voice Still Used
If you hear the "creepy default voice":
-
Make sure you selected a voice
- Default is intentionally left as system voice
- Choose a specific voice from the list
-
Check the status message
- Should show "Using browser voice" or "Using ElevenLabs voice"
- Not "Using system default voice"
-
Verify voice is saved
- Close and reopen Settings
- Check if your selection is still there
- If not, localStorage might be disabled
-
Try a different voice
- Some voices might not work on your system
- Try multiple voices to find one that works
Platform-Specific Issues
Linux:
- May have limited browser voices
- Install
speech-dispatcherfor better TTS - eSpeak voices might sound robotic
macOS:
- Best browser voice support
- Try "Alex" for high quality
- Many system voices available
Windows:
- Microsoft voices work well
- "Microsoft David" is good default
- Install additional voices via Windows Settings
Testing Checklist
- "Default Voice" uses system default
- Browser voices work correctly
- Voice persists after page refresh
- Console logs show correct voice ID
- Multiple voices can be tested
- ElevenLabs voices work (if API key set)
- Status message shows correct voice type
Technical Details
Voice ID Format
Default:
"default"
Browser Voice:
"browser:Google US English"
ElevenLabs Voice:
"elevenlabs:21m00Tcm4TlvDq8ikWAM"
Voice Matching Logic
- Get all available voices (async)
- Strip prefix from voice ID
- Match by
voiceURIfirst, thenname - If no match, use system default
- Log result for debugging
Files Modified
src/lib/tts.ts- Fixed voice selection logicsrc/components/TTSControls.tsx- Fixed default handlingsrc/components/SettingsPanel.tsx- Added status indicator
Benefits
✅ Accurate voice selection - Selected voice is actually used
✅ Better voices - Choose from many high-quality options
✅ Debug friendly - Console logs help troubleshoot
✅ Clear feedback - Status shows what's being used
✅ Persistent - Selection saved across sessions
Example Console Output
Successful voice selection:
Playing TTS with voice: browser:Google US English
TTS speak called with: {voiceId: "browser:Google US English", provider: "browser"}
Using browser TTS with voice: Google US English
Available voices: ["Google US English (Google US English)", "Microsoft David (Microsoft David)", ...]
Looking for voice: Google US English
Selected voice: Google US English Google US English
Using default:
Playing TTS with voice: default
TTS speak called with: {voiceId: undefined, provider: "browser"}
Summary
The TTS voice selection now works correctly! Users can choose from available browser voices or ElevenLabs voices, and the selected voice will actually be used for playback. The fix includes proper async voice loading, prefix handling, and helpful debug logging.
Status: ✅ Fixed
Date: October 5, 2025
Version: v0.2.0-rc