Фикс произношения дат и температуры + wheather -лишние файлы

This commit is contained in:
2026-01-10 23:50:02 +03:00
parent 3818f0ad22
commit 8f44fd2460
10 changed files with 295 additions and 82 deletions

View File

@@ -20,6 +20,8 @@ from ..core.config import TTS_SPEAKER, TTS_EN_SPEAKER, TTS_SAMPLE_RATE
# Подавляем предупреждения Silero о длинном тексте (мы сами его режем)
warnings.filterwarnings("ignore", message="Text string is longer than 1000 symbols")
_EN_WORD_RE = re.compile(r"[A-Za-z][A-Za-z0-9'-]*")
class TextToSpeech:
"""Класс синтеза речи с поддержкой прерывания."""
@@ -109,19 +111,52 @@ class TextToSpeech:
return [c for c in chunks if c]
def speak(self, text: str, check_interrupt=None, language: str = "ru") -> bool:
def _split_mixed_language(self, text: str) -> list[tuple[str, str]]:
"""
Основная функция: генерирует аудио и воспроизводит его.
Args:
text: Текст для озвучки.
check_interrupt: Функция, возвращающая True, если надо прерваться (например, check_wakeword_once).
language: "ru" или "en".
Returns:
True, если договорил до конца.
False, если был прерван.
Разбивает текст на сегменты русского и английского текста.
Английские слова (латиница) будут озвучены английской моделью.
"""
matches = list(_EN_WORD_RE.finditer(text))
if not matches:
return [(text, "ru")]
segments = []
idx = 0
for match in matches:
if match.start() > idx:
segments.append((text[idx : match.start()], "ru"))
segments.append((match.group(0), "en"))
idx = match.end()
if idx < len(text):
segments.append((text[idx:], "ru"))
# Склеиваем соседние сегменты и прикрепляем чистую пунктуацию к предыдущему.
merged = []
for segment, lang in segments:
if not segment:
continue
if not any(ch.isalnum() for ch in segment):
if merged:
merged[-1] = (merged[-1][0] + segment, merged[-1][1])
else:
merged.append((segment, lang))
continue
if merged and merged[-1][1] == lang:
merged[-1] = (merged[-1][0] + segment, lang)
else:
merged.append((segment, lang))
if merged and not any(ch.isalnum() for ch in merged[0][0]) and len(merged) > 1:
merged[1] = (merged[0][0] + merged[1][0], merged[1][1])
merged = merged[1:]
return merged
def _speak_single_language(
self, text: str, check_interrupt=None, language: str = "ru"
) -> bool:
"""Озвучивание текста одной моделью языка."""
if not text.strip():
return True
@@ -197,6 +232,45 @@ class TextToSpeech:
else:
return False
def _speak_mixed(
self, segments: list[tuple[str, str]], check_interrupt=None
) -> bool:
"""Озвучивание текста с переключением RU/EN по сегментам."""
for segment, lang in segments:
if not segment.strip():
continue
completed = self._speak_single_language(
segment, check_interrupt=check_interrupt, language=lang
)
if not completed:
return False
return True
def speak(self, text: str, check_interrupt=None, language: str = "ru") -> bool:
"""
Основная функция: генерирует аудио и воспроизводит его.
Args:
text: Текст для озвучки.
check_interrupt: Функция, возвращающая True, если надо прерваться (например, check_wakeword_once).
language: "ru" или "en".
Returns:
True, если договорил до конца.
False, если был прерван.
"""
if not text.strip():
return True
if language == "ru":
segments = self._split_mixed_language(text)
if any(lang == "en" for _, lang in segments):
return self._speak_mixed(segments, check_interrupt=check_interrupt)
return self._speak_single_language(
text, check_interrupt=check_interrupt, language=language
)
def _check_interrupt_worker(self, check_interrupt):
"""
Фоновая функция для потока: постоянно опрашивает check_interrupt.

View File

@@ -22,7 +22,6 @@ class WakeWordDetector:
self.pa = None
self._stream_closed = True # Флаг состояния потока (закрыт/открыт)
self._last_hit_ts = 0.0
self._hit_streak = 0
def initialize(self):
"""Инициализация Porcupine и PyAudio."""
@@ -136,16 +135,11 @@ class WakeWordDetector:
keyword_index = self.porcupine.process(pcm)
if keyword_index >= 0:
now = time.time()
if now - self._last_hit_ts < 0.6:
self._hit_streak += 1
else:
self._hit_streak = 1
if now - self._last_hit_ts < 0.4:
return False
self._last_hit_ts = now
if self._hit_streak >= 2:
self._hit_streak = 0
print("🛑 Wake word подтвержден во время ответа!")
return True
print("🛑 Wake word обнаружен во время ответа!")
return True
return False
except Exception:
return False