import os import time import json import base64 import requests import tempfile import threading import queue import winsound TRANSCRIPT_PATH = r"C:\Users\nasko\.gemini\antigravity\brain\695897cf-1c58-4886-a686-e9d8c406ebef\.system_generated\logs\transcript.jsonl" API_URL = "http://localhost:8000/api/v1/synthesize/stream" audio_queue = queue.Queue() def player_worker(): """ Взима готови WAV файлове от опашката и ги пуска. """ while True: file_path = audio_queue.get() if file_path is None: break print(f"🔊 Възпроизвеждам от API...") winsound.PlaySound(file_path, winsound.SND_FILENAME) try: os.remove(file_path) except OSError: pass audio_queue.task_done() def process_text(text: str): """ Изпраща текста към API-то и чака за стрийминг на аудио парчета. """ print(f"📡 Изпращане към API: {text[:50]}...") try: response = requests.post(API_URL, json={ "text": text, "voice_style": "F5", "speed": 1.6 }, stream=True) if response.status_code != 200: print(f"Грешка от API: {response.status_code} - {response.text}") return for line in response.iter_lines(): if line: data = json.loads(line) if "error" in data: print(f"API Грешка: {data['error']}") continue chunk_index = data.get("chunk_index") audio_base64 = data.get("audio_base64") if audio_base64: audio_bytes = base64.b64decode(audio_base64) # Записваме временно файла и го пускаме в опашката fd, file_path = tempfile.mkstemp(suffix=f"_chunk_{chunk_index}.wav") os.close(fd) with open(file_path, "wb") as f: f.write(audio_bytes) audio_queue.put(file_path) except requests.exceptions.ConnectionError: print("Не мога да се свържа с API-то! Увери се, че `api.py` работи на порт 8000.") except Exception as e: print(f"Грешка при комуникация с API: {e}") def tail_file(): """ Следи чата (transcript.jsonl) за нови съобщения от модела. """ if not os.path.exists(TRANSCRIPT_PATH): print(f"Файлът не съществува: {TRANSCRIPT_PATH}") return with open(TRANSCRIPT_PATH, "r", encoding="utf-8") as f: f.seek(0, 2) while True: line = f.readline() if not line: time.sleep(0.5) continue try: data = json.loads(line) if data.get("source") == "MODEL" and data.get("type") in ["PLANNER_RESPONSE", "GENERIC"]: full_text = data.get("content", "") if full_text and not full_text.startswith("Created At:"): print("\n📝 Получен нов текст от чата.") process_text(full_text) except Exception as e: pass if __name__ == "__main__": t_play = threading.Thread(target=player_worker, daemon=True) t_play.start() print("Ani Voice Client слуша за съобщения и чака API-то...") tail_file()