call-to-text/README.md

246 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Call-to-Text
Транскрипция звонков из **Novofon DATA API** с сохранением в **Directus**.
## Архитектура
```
Novofon DATA API ──► call-to-text ──► Directus (Postgres)
│ │
│ ┌──────┴──────┐
│ calls calls_* contacts
┌────┴────┐
│ FFmpeg │ конвертация аудио → WAV 16 кГц
└────┬────┘
┌────┴──────────┐
│ faster-whisper │ распознавание речи (модель turbo / large-v3)
└────┬──────────┘
┌────┴──────┐
│ aligner │ маркировка спикеров: caller / callee
└───────────┘
```
- Звонки получаются через JSON-RPC API (`get.calls_report`)
- Аудио скачивается по прямой ссылке
- Стерео-файлы разделяются на каналы: левый = callee, правый = caller
- Каждый канал транскрибируется через faster-whisper на CUDA
- Результат сохраняется в Directus (коллекции `calls` / `calls_*`)
## Требования
- **Python** 3.10+
- **FFmpeg** (в PATH) — для конвертации аудио
- **NVIDIA GPU** с CUDA (опционально, для ускорения)
- **Docker** + **Docker Compose** (для Directus + Postgres)
## Установка и запуск
### 1. Клонировать
```bash
git clone https://git.itoservice.ru/dosnav/call-to-text.git
cd call-to-text
```
### 2. Настроить окружение
```bash
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # Linux
pip install -r requirements.txt
```
### 3. Поднять Directus
```bash
docker compose up -d
```
Создадутся контейнеры:
- `postgres` (порт не наружу)
- `directus` (порт `8055`)
После первого запуска инициализировать коллекции:
```bash
python setup_directus.py
```
Создаст коллекции: `calls`, `calls_74951284933`, `contacts`с полной схемой полей.
### 4. Настроить `.env`
Скопировать `.env.example``.env` и заполнить:
```env
# Novofon DATA API
NOVOFON_ACCESS_TOKEN=ваш_токен
NOVOFON_DATE_FROM=2024-01-01
# Directus
DIRECTUS_URL=http://localhost:8055
DIRECTUS_TOKEN=call-to-text-admin-token
# Whisper
WHISPER_MODEL_SIZE=turbo # tiny/base/small/medium/large-v3/turbo
WHISPER_DEVICE=cuda # cpu / cuda
WHISPER_COMPUTE_TYPE=float16 # int8 / float16
```
### 5. Настроить Novofon
IP-адрес сервера, откуда будет запускаться скрипт, должен быть **внесён в белый список** в админ-панели Novofon:
**Настройки → Правила и настройки безопасности → API**
Токен доступа (permanent API key) создаётся там же.
### 6. Загрузить звонки
```bash
python -m main process --limit 50
```
Первая загрузка — модель Whisper скачается автоматически (HuggingFace Hub).
## CLI-команды
### `process`
Пакетная загрузка и транскрипция звонков из Novofon API.
```bash
python -m main process --limit 100 --date-from "2024-06-01"
```
Опции:
- `--limit N` — максимальное количество звонков за запуск
- `--date-from YYYY-MM-DD` — начальная дата (по умолчанию из .env)
### `process-file`
Транскрипция одного аудиофайла (для тестов).
```bash
python -m main process-file --file "путь/к/файлу.wav" --caller "79161234567" --callee "74951284933"
```
### `export`
Выгрузка всех звонков из Directus в JSON.
```bash
python -m main export --output calls.json
```
### `daemon`
Фоновый режим — проверяет новые звонки каждые 5 минут.
```bash
python -m main daemon --max 10 --hours-back 6
```
## Модели Whisper
| Модель | Размер | Качество | Скорость |
|--------|--------|----------|----------|
| `tiny` | 39 MB | низкое | 🚀 |
| `base` | 74 MB | среднее | 🚀 |
| `small` | 244 MB | хорошее | ⚡ |
| `medium` | 769 MB | очень хорошее | ⚡ |
| `large-v3` | 1.5 GB | **лучшее** | 🐢 |
| `turbo` | 809 MB | как large-v3 | 🚀 (в 5x быстрее) |
Рекомендуется `turbo` — качество large-v3 при заметно меньшем времени транскрипции.
Переключение — одной строкой в `.env`:
```env
WHISPER_MODEL_SIZE=turbo
```
Модель кешируется после первой загрузки в `~/.cache/huggingface/hub/`.
## Структура проекта
```
├── main.py # CLI-точка входа
├── config.py # Настройки из .env
├── setup_directus.py # Инициализация Directus
├── requirements.txt # Зависимости
├── docker-compose.yml # Directus + Postgres
├── .env # Локальные настройки (в .gitignore)
├── .env.example # Шаблон настроек
├── ingestor/
│ ├── novofon_api.py # Клиент Novofon DATA API
│ └── downloader.py # Скачивание аудио по URL
├── audio/
│ ├── stt.py # Распознавание (faster-whisper)
│ ├── preprocessor.py # FFmpeg конвертация, разделение каналов
│ └── diarization.py # Диаризация (pyannote)
├── aligner/
│ └── aligner.py # Маркировка спикеров
├── storage/
│ ├── directus.py # HTTP-клиент Directus
│ ├── contacts.py # Поиск контактов по номеру
│ └── exporter.py # Экспорт в JSON
├── old/ # Архив: email-парсинг (не используется)
└── temp/ # Временные WAV-файлы (в .gitignore)
```
## Управление Directus
**Админка:** http://localhost:8055/admin
**Данные по умолчанию:**
- Email: `admin@example.com`
- Пароль: `admin-password-123`
**Остановить:**
```bash
docker compose down
```
**Удалить данные:**
```bash
docker compose down -v
```
## Коллекции Directus
### `calls`
Основная коллекция звонков (не на номер 74951284933).
### `calls_74951284933`
Звонки, где одна из сторон — 74951284933.
### `contacts`
Телефонная книга. Поля: `phone_number`, `name`, `company`, `notes`.
При транскрипции номера автоматически резолвятся в имена из `contacts`.
## Принцип работы
1. `get.calls_report` получает звонки чанками по 90 дней (максимум API)
2. Скачивается аудио по `full_record_file_link` или `call_records`
3. FFmpeg конвертирует в WAV: 16 кГц, pcm_s16le, моно или стерео
4. Если каналы разные (реальное стерео) — левый = callee, правый = caller
5. Каждый канал транскрибируется faster-whisper на CUDA (float16)
6. Сегменты выравниваются по времени и маркируются спикером
7. Результат сохраняется в Directus
8. Звонки с `talk_duration=0` и без аудио — пропускаются