Files
eve-alpha/docs/tts/TTS_VOICE_SELECTION_FIX.md
Aodhan Collins 66749a5ce7 Initial commit
2025-10-06 00:33:04 +01:00

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

  1. Default value handling - The literal string "default" was being passed to the voice selection API instead of undefined
  2. Async voice loading - Browser voices load asynchronously and weren't being properly awaited
  3. Voice matching - The voice URI wasn't being matched correctly with the available voices
  4. 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

  1. Scroll to Voice Settings
  2. Check Enable text-to-speech for assistant messages

Step 3: Select a Voice

Option A: Use Browser Voices (Free)

  1. Open TTS Voice Selection dropdown
  2. Look under Browser Voices (Free)
  3. Select a voice like:
    • "Google US English"
    • "Microsoft David"
    • "Alex" (macOS)
    • etc.

Option B: Use ElevenLabs Voices (Premium)

  1. Enter your ElevenLabs API key
  2. Wait for voices to load
  3. Look under ElevenLabs Voices (Premium)
  4. Select a voice like:
    • "Rachel - American (young)"
    • "Adam - American (middle-aged)"
    • etc.

Step 4: Test

  1. Close Settings
  2. Send a message to EVE
  3. Click the 🔊 speaker icon on the response
  4. Should now use your selected voice!

Troubleshooting

Voice Still Not Working

Check Console Logs:

  1. Open DevTools (F12)
  2. Go to Console tab
  3. Look for TTS-related logs:
    TTS speak called with: {voiceId: "browser:...", provider: "browser"}
    Available voices: [...]
    Looking for voice: ...
    Selected voice: ...
    

Common Issues:

  1. "Voice not found" warning

    • The voice URI doesn't match any available voices
    • Try selecting a different voice
    • Check that browser voices have loaded
  2. No voices in dropdown

    • Browser hasn't loaded voices yet
    • Try refreshing the page
    • Check browser permissions
  3. 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":

  1. Make sure you selected a voice

    • Default is intentionally left as system voice
    • Choose a specific voice from the list
  2. Check the status message

    • Should show "Using browser voice" or "Using ElevenLabs voice"
    • Not "Using system default voice"
  3. Verify voice is saved

    • Close and reopen Settings
    • Check if your selection is still there
    • If not, localStorage might be disabled
  4. 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-dispatcher for 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

  1. Get all available voices (async)
  2. Strip prefix from voice ID
  3. Match by voiceURI first, then name
  4. If no match, use system default
  5. Log result for debugging

Files Modified

  • src/lib/tts.ts - Fixed voice selection logic
  • src/components/TTSControls.tsx - Fixed default handling
  • src/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