diff --git a/satellite/audio.py b/satellite/audio.py index 5e048a9..9569ca9 100644 --- a/satellite/audio.py +++ b/satellite/audio.py @@ -27,10 +27,13 @@ def record() -> str: speaking_started = False max_chunks = int(16000 / 1024 * MAX_DURATION) silence_chunks_needed = int(16000 / 1024 * SILENCE_DURATION) + warmup_chunks = int(16000 / 1024 * 0.3) # 0.3 сек — эхо звука активации try: - for _ in range(max_chunks): + for i in range(max_chunks): data = stream.read(1024, exception_on_overflow=False) + if i < warmup_chunks: + continue # пропускаем эхо от звука активации frames.append(data) amplitude = np.abs(np.frombuffer(data, dtype=np.int16)).mean() diff --git a/satellite/llm.py b/satellite/llm.py index c03f3cf..82f0600 100644 --- a/satellite/llm.py +++ b/satellite/llm.py @@ -5,7 +5,7 @@ from datetime import date from .config import GATEWAY_URL, VOICE_MODEL, AGENT, AGENTS, log from .text import clean_for_speech, find_sentence_end -from .tts import speak +from .tts import speak, play_error_sound SYSTEM_PROMPT = "Отвечай кратко, 1-2 предложения, без markdown, без эмодзи." MAX_HISTORY = int(__import__("os").getenv("MAX_HISTORY", "20")) @@ -79,18 +79,21 @@ def ask_agent_stream(text: str, conv: "Conversation | None" = None, agent_id: st log.exception("Gateway недоступен") msg = "Не могу связаться с сервером, попробуй ещё раз." print(f"⚠️ {msg}") + #play_error_sound() speak(msg, agent_id) return msg except requests.Timeout: log.exception("Gateway таймаут") msg = "Сервер не ответил вовремя, попробуй ещё раз." print(f"⚠️ {msg}") + #play_error_sound() speak(msg, agent_id) return msg except requests.HTTPError: log.exception(f"Gateway HTTP ошибка {resp.status_code}") msg = "Ошибка сервера, попробуй ещё раз." print(f"⚠️ Gateway {resp.status_code}: {resp.text}") + #play_error_sound() speak(msg, agent_id) return msg diff --git a/satellite/tts.py b/satellite/tts.py index bc8f694..89cfa59 100644 --- a/satellite/tts.py +++ b/satellite/tts.py @@ -41,7 +41,8 @@ def is_speaking() -> bool: def _mpv_cmd() -> list[str]: """Команда mpv для воспроизведения из stdin""" - cmd = ["mpv", "--no-video", "--really-quiet", "--no-terminal"] + mpv_bin = os.getenv("MPV_PATH", "mpv") + cmd = [mpv_bin, "--no-video", "--really-quiet", "--no-terminal"] if AUDIO_SINK: cmd.append(f"--audio-device=pulse/{AUDIO_SINK}") cmd.append("-") @@ -54,6 +55,7 @@ def speak(text: str, agent_id: str = "cosmo"): except Exception as e: log.exception("TTS ошибка") print(f"⚠️ Ошибка воспроизведения: {e}") + play_error_sound() def _speak_elevenlabs(text: str, agent_id: str): @@ -98,13 +100,33 @@ def _speak_elevenlabs(text: str, agent_id: str): _current_process = None +def _play_sound_file(filename: str, wait: bool = False): + """Воспроизводит файл из папки sounds/ через mpv. + wait=True — блокирует до конца воспроизведения.""" + sounds_dir = os.path.join(os.path.dirname(__file__), "..", "sounds") + path = os.path.normpath(os.path.join(sounds_dir, filename)) + mpv_bin = os.getenv("MPV_PATH", "mpv") + cmd = [mpv_bin, "--no-video", "--really-quiet", "--no-terminal", path] + if wait: + subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + else: + subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + def play_activation_sound(): - """Звук активации после wake word""" + """Звук активации — неблокирующий""" try: - if sys.platform == "darwin": - subprocess.run(["afplay", "/System/Library/Sounds/Glass.aiff"]) - else: - subprocess.run(["paplay", "/usr/share/sounds/freedesktop/stereo/bell.oga"]) + _play_sound_file("Success_Cosmo.mp3", wait=False) except Exception as e: - log.exception("Ошибка звука активации") - print(f"⚠️ Ошибка звука: {e}") + log.warning(f"Ошибка звука активации: {e}") + + +def play_error_sound(): + """Звук ошибки — 'не получилось'""" + import traceback + print("🔴 play_error_sound вызван из:") + traceback.print_stack() + try: + _play_sound_file("Error_Cosmo.mp3") + except Exception as e: + log.warning(f"Ошибка звука ошибки: {e}") diff --git a/sounds/Error_Cosmo.mp3 b/sounds/Error_Cosmo.mp3 new file mode 100644 index 0000000..3c83450 Binary files /dev/null and b/sounds/Error_Cosmo.mp3 differ diff --git a/sounds/Success_Cosmo.mp3 b/sounds/Success_Cosmo.mp3 new file mode 100644 index 0000000..5b13bbf Binary files /dev/null and b/sounds/Success_Cosmo.mp3 differ