From 853753d38b04436756afeb0be673dbf880b1cdae Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Wed, 10 Jun 2026 20:38:31 +0000 Subject: [PATCH] Update piper TTS wrapper with auto-discovery and espeak_data path for Windows --- Solvers/piper/piper_tts_wrapper.py | 62 ++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/Solvers/piper/piper_tts_wrapper.py b/Solvers/piper/piper_tts_wrapper.py index 1c75301..9cfbbf6 100644 --- a/Solvers/piper/piper_tts_wrapper.py +++ b/Solvers/piper/piper_tts_wrapper.py @@ -14,28 +14,68 @@ import json import subprocess import os + +def find_piper_exe(): + """Find the piper executable in known HyperTwist solver paths or PATH.""" + script_dir = os.path.dirname(os.path.abspath(__file__)) + candidates = [ + os.path.join(script_dir, "piper", "piper", "piper.exe"), + os.path.join(script_dir, "..", "..", "..", "Binaries", "Win64", "Solvers", "piper", "piper", "piper.exe"), + os.path.join(script_dir, "piper", "piper.exe"), + os.path.join(script_dir, "..", "piper", "piper", "piper.exe"), + "piper", + "piper.exe", + ] + for candidate in candidates: + resolved = os.path.abspath(candidate) + if os.path.isfile(resolved): + return resolved + return None + + +def find_espeak_data(piper_exe): + """Locate espeak-ng-data directory next to the piper executable.""" + exe_dir = os.path.dirname(os.path.abspath(piper_exe)) + candidates = [ + os.path.join(exe_dir, "espeak-ng-data"), + os.path.join(exe_dir, "..", "espeak-ng-data"), + ] + for candidate in candidates: + resolved = os.path.abspath(candidate) + if os.path.isdir(resolved): + return resolved + return None + + def synthesize(text: str, model_path: str, config_path: str, output_path: str) -> str: """Synthesize speech using piper.""" if not os.path.exists(model_path): return f"ERROR: Model not found: {model_path}" - - # Try using piper directly if available in PATH + + piper_exe = find_piper_exe() + if not piper_exe: + return "ERROR: piper executable not found. Place it in Solvers/piper/piper/ or add to PATH." + + espeak_data = find_espeak_data(piper_exe) + + cmd = [ + piper_exe, + "--model", os.path.abspath(model_path), + "--config", os.path.abspath(config_path), + "--output_file", os.path.abspath(output_path), + ] + if espeak_data: + cmd.extend(["--espeak_data", espeak_data]) + try: - cmd = [ - "piper", - "--model", model_path, - "--config", config_path, - "--output_file", output_path - ] result = subprocess.run(cmd, input=text, text=True, capture_output=True, timeout=60) if result.returncode == 0: - return output_path + return os.path.abspath(output_path) return f"ERROR: {result.stderr}" - except FileNotFoundError: - return "ERROR: piper executable not found in PATH. Install piper or compile from .external/piper" except Exception as e: return f"ERROR: {e}" + if __name__ == "__main__": parser = argparse.ArgumentParser(description="HyperTwist Piper TTS Wrapper") parser.add_argument("--text", required=True, help="Text to synthesize")