import os import subprocess import sys import tempfile def speak(text: str, voice_path: str) -> None: with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tf: wav_path = tf.name try: proc = subprocess.run( ["piper", "--model", voice_path, "--output_file", wav_path], input=text.encode(), capture_output=True, timeout=15, ) if proc.returncode != 0: stderr = proc.stderr.decode(errors="replace").strip() print(f"[TTS off: piper błąd {proc.returncode}: {stderr}]") return _play(wav_path) except FileNotFoundError: print("[TTS off: piper nie znaleziony — zainstaluj piper-tts]") except subprocess.TimeoutExpired: print("[TTS off: piper timeout]") except Exception as exc: print(f"[TTS off: {exc}]") finally: try: os.unlink(wav_path) except OSError: pass def _play(wav_path: str) -> None: if sys.platform.startswith("linux"): _run_player("aplay", wav_path) elif sys.platform == "darwin": _run_player("afplay", wav_path) elif sys.platform == "win32": try: import winsound winsound.PlaySound(wav_path, winsound.SND_FILENAME) except Exception as exc: print(f"[TTS off: winsound: {exc}]") else: print(f"[TTS off: nieobsługiwana platforma {sys.platform}]") def _run_player(player: str, wav_path: str) -> None: try: subprocess.run([player, wav_path], capture_output=True, timeout=30) except FileNotFoundError: print(f"[TTS off: {player} nie znaleziony]") except Exception as exc: print(f"[TTS off: {exc}]")