first commit

This commit is contained in:
workD12
2026-09-11 19:47:15 +03:00
commit 32754a1fe2
56 changed files with 3836 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
"""Базовый интерфейс STT-модуля (речь → текст).
Любой распознаватель (faster-whisper, vosk, ...) реализует SttProvider,
чтобы остальной проект не зависел от конкретной библиотеки.
Замена провайдера = правка одной строки в конфиге.
"""
from __future__ import annotations
from abc import ABC, abstractmethod
from dataclasses import dataclass
from pathlib import Path
from typing import Union
import numpy as np
# Что умеет принимать transcribe(): путь к файлу ЛИБО готовый массив float32
AudioInput = Union[str, Path, np.ndarray]
# Все провайдеры ждут 16 кГц mono float32 ([-1 .. 1])
SAMPLE_RATE = 16000
@dataclass
class TranscriptResult:
"""Результат распознавания одной фразы."""
text: str
duration_sec: float # длина аудио в секундах
processing_sec: float # сколько времени считали
language: str = "ru"
language_probability: float = 0.0
@property
def realtime_factor(self) -> float:
"""processing / duration. Значение < 1.0 — быстрее реального времени."""
if self.duration_sec <= 0:
return float("inf")
return self.processing_sec / self.duration_sec
def __str__(self) -> str:
return (
f"[{self.duration_sec:.1f} c аудио → {self.processing_sec:.2f} c, "
f"RTF {self.realtime_factor:.2f}] {self.text!r}"
)
class SttProvider(ABC):
"""Интерфейс провайдера распознавания речи."""
name: str = "base"
@abstractmethod
def transcribe(self, audio: AudioInput, sample_rate: int = SAMPLE_RATE) -> TranscriptResult:
"""Распознать речь.
audio — путь к файлу (wav/mp3/flac, декодирование внутри) ИЛИ
numpy-массив float32 mono с частотой sample_rate.
"""
def close(self) -> None:
"""Освободить ресурсы (по умолчанию — ничего)."""