refactor(tools): fold tts voice-delivery native branch, config-load fallthrough, speaker one-liners
This commit is contained in:
@@ -161,10 +161,9 @@ def _load_tts_config() -> Dict[str, Any]:
|
||||
return load_config().get("tts") or {}
|
||||
except ImportError:
|
||||
logger.debug("hermes_cli.config not available, using default TTS config")
|
||||
return {}
|
||||
except Exception as e:
|
||||
logger.warning("Failed to load TTS config: %s", e, exc_info=True)
|
||||
return {}
|
||||
return {}
|
||||
|
||||
|
||||
def _get_provider(tts_config: Dict[str, Any]) -> str:
|
||||
@@ -269,10 +268,9 @@ def _finalize_voice_delivery(
|
||||
elif want_opus and provider in _FFMPEG_OPUS_PROVIDERS and not file_str.endswith(".ogg"):
|
||||
opus_path = _convert_to_opus(file_str)
|
||||
return (opus_path, True) if opus_path else (file_str, False)
|
||||
elif provider in _NATIVE_OPUS_PROVIDERS:
|
||||
return file_str, want_opus and file_str.endswith(".ogg")
|
||||
else:
|
||||
return file_str, False
|
||||
native = provider in _NATIVE_OPUS_PROVIDERS
|
||||
return file_str, native and want_opus and file_str.endswith(".ogg")
|
||||
if not opted_in:
|
||||
return file_str, False
|
||||
if not file_str.endswith(".ogg"):
|
||||
@@ -282,12 +280,11 @@ def _finalize_voice_delivery(
|
||||
|
||||
# --- Main tool function ---
|
||||
def _apply_call_overrides(tts_config: Dict[str, Any], speed: Optional[float], provider: Optional[str]):
|
||||
"""Apply per-call ``speed`` (clamped, on a shallow copy) and resolve the provider name."""
|
||||
"""Apply per-call ``speed`` (clamped, on a shallow copy so the cached config isn't mutated) and
|
||||
resolve the provider name."""
|
||||
if speed is not None:
|
||||
tts_config = dict(tts_config) # shallow copy to avoid mutating the cache
|
||||
tts_config["speed"] = max(0.25, min(4.0, float(speed)))
|
||||
provider = provider.lower().strip() if provider else _get_provider(tts_config)
|
||||
return tts_config, provider
|
||||
tts_config = {**tts_config, "speed": max(0.25, min(4.0, float(speed)))}
|
||||
return tts_config, provider.lower().strip() if provider else _get_provider(tts_config)
|
||||
|
||||
|
||||
def _session_platform() -> tuple:
|
||||
|
||||
@@ -194,13 +194,13 @@ def _rewrite_with_auxiliary_model(
|
||||
|
||||
# --- Edge TTS (free default) ---
|
||||
async def _generate_edge_tts(text: str, output_path: str, tts_config: Dict[str, Any]) -> str:
|
||||
_edge_tts = _origin()._import_edge_tts()
|
||||
edge_tts = _origin()._import_edge_tts()
|
||||
edge_config = tts_config.get("edge") or {}
|
||||
speed = float(edge_config.get("speed", tts_config.get("speed", 1.0)))
|
||||
kwargs = {"voice": edge_config.get("voice", DEFAULT_EDGE_VOICE)}
|
||||
if speed != 1.0:
|
||||
kwargs["rate"] = f"{round((speed - 1.0) * 100):+d}%"
|
||||
await _edge_tts.Communicate(text, **kwargs).save(output_path)
|
||||
await edge_tts.Communicate(text, **kwargs).save(output_path)
|
||||
return output_path
|
||||
|
||||
|
||||
@@ -211,8 +211,8 @@ def _elevenlabs_environment_kwargs(el_config: Dict[str, Any]) -> Dict[str, Any]:
|
||||
base_url = (el_config.get("base_url") or "").rstrip("/")
|
||||
if not base_url:
|
||||
return {}
|
||||
wss_url = (el_config.get("wss_url") or "").rstrip("/") or re.sub(r"^http", "ws", base_url)
|
||||
from elevenlabs.environment import ElevenLabsEnvironment
|
||||
wss_url = (el_config.get("wss_url") or "").rstrip("/") or re.sub(r"^http", "ws", base_url)
|
||||
return {"environment": ElevenLabsEnvironment(base=base_url, wss=wss_url)}
|
||||
|
||||
|
||||
|
||||
@@ -93,9 +93,8 @@ class _SyncSentencePipeline:
|
||||
|
||||
def speak(self, cleaned: str) -> None:
|
||||
"""Queue one sentence. Blocks only when the lookahead bound is full."""
|
||||
if self._stop.is_set():
|
||||
return
|
||||
self._queue.put((cleaned, self._executor.submit(self._synthesize_to_tmp, cleaned)))
|
||||
if not self._stop.is_set():
|
||||
self._queue.put((cleaned, self._executor.submit(self._synthesize_to_tmp, cleaned)))
|
||||
|
||||
def close(self) -> None:
|
||||
"""Flush queued sentences in order (skipped if stopped), then join."""
|
||||
@@ -208,8 +207,7 @@ class _StreamerPlayback:
|
||||
self._prefetch_sem.release()
|
||||
|
||||
def _play_sentence_via_tempfile(self, chunk_queue) -> None:
|
||||
_play_via_tempfile(
|
||||
iter(_drain_chunks(chunk_queue)), self.stop_event, self.streamer.sample_rate)
|
||||
_play_via_tempfile(_drain_chunks(chunk_queue), self.stop_event, self.streamer.sample_rate)
|
||||
|
||||
def _for_each_sentence(self, play: Callable[[queue.Queue], None]) -> None:
|
||||
"""Feed queued sentences to *play* in order until the end sentinel; stopped sentences are skipped."""
|
||||
|
||||
Reference in New Issue
Block a user