Добавлен полный пайплайн выгрузки записей разговоров из IMAP-почты Yandex, транскрипции через faster-whisper (turbo, CUDA) и сохранения в Directus. Новые файлы: - imap/email_fetcher.py — подключение к IMAP (imap.yandex.ru:993), пагинация по UID (200/страница), автоматическое переподключение при IMAP4.abort (3 retry) - imap/config.py — конфигурация из .env - imap/ingestor.py — основной цикл: чтение письма, парсинг метаданных, сохранение вложения, конвертация в WAV, разделение стереоканалов, транскрипция, запись в Directus; поддержка --limit - imap/parsers/base.py — абстрактный парсер писем - imap/parsers/novofon.py — парсер писем Novofon/Zadarma: темы [АТС Zadarma] и Novofon, тело письма (JSON+HTML), имя файла вложения как fallback; маппинг внутренних номеров 102/201 на виртуальные; _clean_number без + - imap/preprocessor.py — конвертация в WAV (ffmpeg), разделение стереоканалов (левый=callee, правый=caller), get_audio_duration() через ffprobe - imap/stt.py — транскрипция через faster-whisper (turbo, CUDA) - imap/aligner.py — alignment результатов STT - imap/directus.py — клиент Directus: check_call (дедуп), save_call в calls/calls_74951284933, find_contact - match_contacts.py — сопоставление всех звонков с контактами по номеру телефона, заполнение caller_name/callee_name - count_remaining.py — утилита подсчёта оставшихся писем в IMAP Изменения: - .env.example: добавлена секция IMAP (сервер, логин, пароль, папка) - requirements.txt: добавлен imap-tools (IMAP-клиент) Обработано ~3900 звонков из IMAP (3670 в calls + 687 в calls_74951284933). Все записи с длительностью аудио из файла (ffprobe). Все звонки без + в номерах телефонов.
31 lines
1 KiB
Python
31 lines
1 KiB
Python
from typing import Optional
|
|
from faster_whisper import WhisperModel
|
|
|
|
|
|
_model: Optional[WhisperModel] = None
|
|
|
|
|
|
def get_model(model_size: str = "turbo", device: str = "cuda", compute_type: str = "float16") -> WhisperModel:
|
|
global _model
|
|
if _model is None:
|
|
_model = WhisperModel(model_size, device=device, compute_type=compute_type)
|
|
return _model
|
|
|
|
|
|
def transcribe(audio_path: str, model_size: str = "turbo", device: str = "cuda", compute_type: str = "float16", language: str = "ru") -> tuple[list[dict], str]:
|
|
model = get_model(model_size, device, compute_type)
|
|
|
|
segments, info = model.transcribe(audio_path, language=language, beam_size=5, vad_filter=True)
|
|
|
|
result = []
|
|
full_text_parts = []
|
|
for seg in segments:
|
|
result.append({
|
|
"start": round(seg.start, 2),
|
|
"end": round(seg.end, 2),
|
|
"text": seg.text.strip(),
|
|
})
|
|
full_text_parts.append(seg.text.strip())
|
|
|
|
full_text = " ".join(full_text_parts)
|
|
return result, full_text
|