Make voice_tool dependency-free and add voice alias mappings for macOS vs Kokoro names
This commit is contained in:
+34
-10
@@ -4,8 +4,13 @@ Supports both Kokoro TTS voices and macOS System voices, persisting user voice p
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from loguru import logger
|
|
||||||
|
try:
|
||||||
|
from loguru import logger
|
||||||
|
except ImportError:
|
||||||
|
logger = logging.getLogger("voice_manager")
|
||||||
|
|
||||||
# Supported Kokoro TTS voices categorized by style
|
# Supported Kokoro TTS voices categorized by style
|
||||||
KOKORO_VOICES = {
|
KOKORO_VOICES = {
|
||||||
@@ -32,6 +37,19 @@ MACOS_VOICES = {
|
|||||||
"Alex": "US Male",
|
"Alex": "US Male",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOICE_ALIASES = {
|
||||||
|
"daniel": "bm_george", # British Male
|
||||||
|
"moira": "bf_emma", # British Female
|
||||||
|
"samantha": "af_bella", # US Female
|
||||||
|
"alex": "am_michael", # US Male
|
||||||
|
"karen": "bf_isabella", # AU/UK Female
|
||||||
|
"michael": "am_michael",
|
||||||
|
"bella": "af_bella",
|
||||||
|
"heart": "af_heart",
|
||||||
|
"fenrir": "am_fenrir",
|
||||||
|
"adam": "am_adam",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class VoiceManager:
|
class VoiceManager:
|
||||||
"""Manages active voice settings and dynamic voice switching."""
|
"""Manages active voice settings and dynamic voice switching."""
|
||||||
@@ -78,21 +96,27 @@ class VoiceManager:
|
|||||||
voice_name = voice_name.strip()
|
voice_name = voice_name.strip()
|
||||||
matched_voice = None
|
matched_voice = None
|
||||||
|
|
||||||
# Exact match or fuzzy match
|
# Check voice aliases first (e.g. Daniel -> bm_george)
|
||||||
for v in {**KOKORO_VOICES, **MACOS_VOICES}:
|
clean_name = voice_name.lower()
|
||||||
if voice_name.lower() == v.lower():
|
if clean_name in VOICE_ALIASES:
|
||||||
matched_voice = v
|
matched_voice = VOICE_ALIASES[clean_name]
|
||||||
break
|
|
||||||
|
|
||||||
|
# Exact match or fuzzy match
|
||||||
if not matched_voice:
|
if not matched_voice:
|
||||||
# Partial match search
|
for v in KOKORO_VOICES:
|
||||||
for v in {**KOKORO_VOICES, **MACOS_VOICES}:
|
if clean_name == v.lower():
|
||||||
if voice_name.lower() in v.lower():
|
|
||||||
matched_voice = v
|
matched_voice = v
|
||||||
break
|
break
|
||||||
|
|
||||||
if not matched_voice:
|
if not matched_voice:
|
||||||
available = ", ".join(list(KOKORO_VOICES.keys()) + list(MACOS_VOICES.keys()))
|
# Partial match search
|
||||||
|
for v in KOKORO_VOICES:
|
||||||
|
if clean_name in v.lower():
|
||||||
|
matched_voice = v
|
||||||
|
break
|
||||||
|
|
||||||
|
if not matched_voice:
|
||||||
|
available = ", ".join(list(KOKORO_VOICES.keys()))
|
||||||
return False, f"Voice '{voice_name}' not found. Available voices: {available}"
|
return False, f"Voice '{voice_name}' not found. Available voices: {available}"
|
||||||
|
|
||||||
self._active_voice = matched_voice
|
self._active_voice = matched_voice
|
||||||
|
|||||||
Reference in New Issue
Block a user