from __future__ import annotations import argparse import os from pathlib import Path import sys import tempfile ROOT = Path(__file__).resolve().parents[1] if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from services.ai_voice_runtime_service.audiosocket import pcm16le_to_wav_bytes, resample_pcm16le from services.ai_voice_runtime_service.providers.tts import build_tts_provider def _parse_args() -> argparse.Namespace: default_provider = os.getenv("AI_VOICE_TTS_PROVIDER", "yandex").strip() or "yandex" parser = argparse.ArgumentParser( description="Generate TTS once, cache it on the server, and materialize a WAV prompt file.", ) parser.add_argument("--text", required=True, help="Text to synthesize.") parser.add_argument("--output", required=True, help="Target WAV path.") parser.add_argument("--language", default=None, help="Optional language hint.") parser.add_argument( "--provider", default=default_provider, help="TTS provider name. Defaults to AI_VOICE_TTS_PROVIDER or yandex.", ) parser.add_argument("--sample-rate", type=int, default=8000, help="Target WAV sample rate. Defaults to 8000.") return parser.parse_args() def _write_atomic(target: Path, payload: bytes) -> None: target.parent.mkdir(parents=True, exist_ok=True) temp_path: str | None = None try: with tempfile.NamedTemporaryFile(dir=target.parent, delete=False, suffix=".tmp") as handle: handle.write(payload) temp_path = handle.name Path(temp_path).replace(target) target.chmod(0o644) finally: if temp_path: try: Path(temp_path).unlink(missing_ok=True) except OSError: pass def main() -> int: args = _parse_args() provider = build_tts_provider(args.provider) synthesis = provider.synthesize(args.text, language=args.language) pcm_bytes = resample_pcm16le( synthesis.audio_bytes, input_rate_hz=synthesis.sample_rate_hz, output_rate_hz=max(args.sample_rate, 1), ) wav_bytes = pcm16le_to_wav_bytes( pcm_bytes, sample_rate_hz=max(args.sample_rate, 1), ) output_path = Path(args.output).expanduser() _write_atomic(output_path, wav_bytes) print(output_path) return 0 if __name__ == "__main__": raise SystemExit(main())