Enable live real-time TTS voice synchronization between VoiceManager and KokoroTTS
This commit is contained in:
@@ -345,7 +345,7 @@ def build_tts(args: argparse.Namespace, voice_manager=None):
|
|||||||
logger.info(f"Text to speech: Kokoro {voice}")
|
logger.info(f"Text to speech: Kokoro {voice}")
|
||||||
tts = KokoroTTSService(
|
tts = KokoroTTSService(
|
||||||
settings=KokoroTTSService.Settings(voice=voice, language=Language.EN),
|
settings=KokoroTTSService.Settings(voice=voice, language=Language.EN),
|
||||||
text_filters=[SpokenTextFilter()],
|
text_filters=[SpokenTextFilter(voice_manager=voice_manager)],
|
||||||
)
|
)
|
||||||
if voice_manager:
|
if voice_manager:
|
||||||
voice_manager.set_tts_processor(tts)
|
voice_manager.set_tts_processor(tts)
|
||||||
|
|||||||
@@ -34,7 +34,13 @@ _EXTRA_SPACE = re.compile(r"[ \t]{2,}")
|
|||||||
class SpokenTextFilter(MarkdownTextFilter):
|
class SpokenTextFilter(MarkdownTextFilter):
|
||||||
"""Markdown filtering, plus the leftovers that matter when read aloud."""
|
"""Markdown filtering, plus the leftovers that matter when read aloud."""
|
||||||
|
|
||||||
|
def __init__(self, voice_manager=None, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self._voice_manager = voice_manager
|
||||||
|
|
||||||
async def filter(self, text: str) -> str:
|
async def filter(self, text: str) -> str:
|
||||||
|
if self._voice_manager:
|
||||||
|
self._voice_manager.sync_voice()
|
||||||
text = _TIMES.sub(" times ", text)
|
text = _TIMES.sub(" times ", text)
|
||||||
text = await super().filter(text)
|
text = await super().filter(text)
|
||||||
text = _STRIKETHROUGH.sub(r"\1", text)
|
text = _STRIKETHROUGH.sub(r"\1", text)
|
||||||
|
|||||||
@@ -77,6 +77,19 @@ class VoiceManager:
|
|||||||
logger.warning(f"Could not load saved voice settings: {e}")
|
logger.warning(f"Could not load saved voice settings: {e}")
|
||||||
return self._active_voice
|
return self._active_voice
|
||||||
|
|
||||||
|
def sync_voice(self) -> str:
|
||||||
|
"""Check if voice_settings.json was updated on disk and update TTS live."""
|
||||||
|
current_disk_voice = self.load_saved_voice()
|
||||||
|
if self._tts_processor and current_disk_voice:
|
||||||
|
if hasattr(self._tts_processor, "_settings"):
|
||||||
|
current_tts_voice = getattr(self._tts_processor._settings, "voice", None)
|
||||||
|
if current_tts_voice != current_disk_voice:
|
||||||
|
self._tts_processor._settings.voice = current_disk_voice
|
||||||
|
logger.info(f"Live TTS voice synced to: {current_disk_voice}")
|
||||||
|
elif hasattr(self._tts_processor, "set_voice"):
|
||||||
|
self._tts_processor.set_voice(current_disk_voice)
|
||||||
|
return current_disk_voice
|
||||||
|
|
||||||
def save_voice(self, voice_name: str):
|
def save_voice(self, voice_name: str):
|
||||||
try:
|
try:
|
||||||
self._config_file.write_text(json.dumps({"voice": voice_name}, indent=2))
|
self._config_file.write_text(json.dumps({"voice": voice_name}, indent=2))
|
||||||
|
|||||||
Reference in New Issue
Block a user