Files
crm.clientright.ru/whisper_api
Fedor 01c4fe80b5 chore: snapshot current working tree changes
Save all currently accumulated repository changes as a backup snapshot for Gitea so no local work is lost.
2026-03-26 14:19:01 +03:00
..

Whisper API

Сервис транскрипции аудио (speech-to-text) на базе faster-whisper. FastAPI, доступ снаружи только по API-ключу.

Запуск

  1. Создать .env из примера и задать хитрый API-ключ:

    cp .env.example .env
    # Сгенерировать ключ: openssl rand -hex 32
    # Вписать в .env: WHISPER_API_KEY=<полученная строка>
    
  2. Собрать и запустить:

    docker compose up -d --build
    
  3. Проверка:

    curl http://localhost:8310/health
    

Доступ извне

  • Порт 8310 (проброшен в docker-compose). Либо повесить перед сервисом nginx с SSL и ограничением по IP, либо оставить только проверку по ключу (как сейчас).
  • Все запросы (кроме GET /health) требуют заголовок X-API-Key с тем же значением, что и WHISPER_API_KEY в .env.

Пример синхронной транскрипции:

curl -X POST "https://your-domain/whisper/transcribe" \
  -H "X-API-Key: YOUR_SECRET_KEY" \
  -F "file=@audio.mp3"

Ответ: {"text": "...", "language": "ru", "segments": [...]}.

Пример асинхронной (ответ сразу, результат придёт на callback URL из env или из заголовка X-Callback-Url):

curl -X POST "https://your-domain/whisper/transcribe-async" \
  -H "X-API-Key: YOUR_SECRET_KEY" \
  -H "X-Callback-Id: my-record-123" \
  -F "file=@audio.mp3"
# без X-Callback-Url → используется N8N_CALLBACK_URL из .env

Ответ: 202 Accepted, {"job_id": "...", "status": "accepted", "callback_url": "..."}.

Документация API

После запуска: http://localhost:8310/docs (Swagger) и http://localhost:8310/redoc.

Переменные окружения

Переменная Описание По умолчанию
WHISPER_API_KEY Секретный ключ для заголовка X-API-Key — (обязательно)
WHISPER_MODEL_SIZE Модель: tiny, base, small, medium, large-v3 base
WHISPER_DEVICE cpu или cuda cpu
WHISPER_COMPUTE_TYPE int8 или float16 int8
WHISPER_CPU_THREADS Число потоков CTranslate2 (меньше = меньше нагрузка на CPU) 2
OMP_NUM_THREADS Потоки OpenMP / Hugging Face (ограничивает фоновые потоки) 2
LOG_DIR Папка для логов (в контейнере) /app/logs
N8N_CALLBACK_URL URL для callback: по готовности расшифровки сюда POST-ится JSON (n8n webhook)

Первая загрузка модели при запросе может занять 12 минуты (скачивание с Hugging Face).

Асинхронный режим (n8n callback)

Чтобы не ждать ответа и не настраивать большие таймауты:

  1. В .env задайте N8N_CALLBACK_URL — URL webhook'а n8n, который примет результат (например https://your-n8n.com/webhook/whisper-result).

  2. В n8n создайте workflow с Webhook-нодой (Trigger), метод POST. Скопируйте URL webhook'а в N8N_CALLBACK_URL.

  3. Вместо POST /transcribe вызывайте POST /transcribe-async с тем же телом (файл в file или сырое тело). Ответ сразу: 202 Accepted, тело например:

    { "job_id": "uuid", "status": "accepted", "callback_url": "https://...", "callback_id": "..." }
    

    Опциональный заголовок X-Callback-Id — ваш идентификатор (id записи, item id в n8n); он вернётся в теле callback'а для связи.

  4. Когда расшифровка готова, сервис отправит на callback URL один POST с JSON. URL берётся из заголовка X-Callback-Url (если передан), иначе из N8N_CALLBACK_URL в .env:

    • при успехе: {"job_id": "...", "success": true, "text": "...", "language": "ru", "segments": [...], "callback_id": "..."}
    • при ошибке: {"job_id": "...", "success": false, "error": "сообщение", "callback_id": "..."}

В n8n после Webhook можно обработать body.text, body.language и т.д. Таймаут на запрос к Whisper не нужен — запрос к /transcribe-async завершается сразу.

Таймауты (n8n и прокси)

Транскрипция длинного аудио на CPU (особенно large-v3) может занимать несколько минут. Если запрос обрывается с timeout of 600000ms exceeded или ECONNABORTED:

  1. n8n (HTTP Request)
    В настройках ноды задайте таймаут не меньше 1520 минут:

    • Timeout = 1200000 (20 мин в мс) или 900000 (15 мин).
      Иначе при длинной очереди (несколько файлов подряд) или долгом файле соединение обрывается.
  2. Nginx перед API
    Если запросы идут через nginx, по умолчанию он режет соединение через 60 с. В location для Whisper API добавьте:

    proxy_read_timeout 1200s;
    proxy_send_timeout 1200s;
    proxy_connect_timeout 60s;
    

    (1200 с = 20 мин). Перезагрузите nginx: sudo nginx -s reload.

  3. Очередь
    Если n8n запускает много запросов параллельно, они по очереди обрабатываются одним процессом. Последний может начаться через 10+ минут — таймаут в n8n должен это учитывать (см. п. 1).

Логи

Логи приложения пишутся в папку logs/ внутри проекта (монтируется в контейнер как /app/logs):

  • logs/whisper_api.log — ротация 10 МБ, 3 файла (.log.1, .log.2, .log.3).
  • Логи контейнера по-прежнему доступны: docker compose logs -f whisper_api.