Лёгкий API‑сервис на FastAPI для транскрибации речи из видеофайлов с помощью OpenAI Whisper. На вход — видео, на выход — язык и текст. Есть простой Web UI для ручной загрузки, Docker‑окружение и автотесты.
Стек: Python, FastAPI, Uvicorn, FFmpeg (через ffmpeg-python), OpenAI Whisper, Docker, PyTest.
Ключевые фичи
POST /api/v1/transcribe — принимает видео и возвращает JSON с языком и транскриптом.GET / — статический Web UI для загрузки и проверки.GET /docs — интерактивная OpenAPI‑спецификация.Sparq_voice_recognition-master/
├─ app/
│ ├─ main.py # Точка входа FastAPI, маршруты и статик
│ ├─ core/
│ │ └─ config.py # Конфиг: выбор модели WHISPER_MODEL
│ ├─ services/
│ │ ├─ audio_service.py # Извлечение аудио из видео (FFmpeg)
│ │ └─ transcription_service.py# Загрузка и вызов Whisper, пост-очистка
│ ├─ api/
│ │ └─ v1/endpoints/transcription.py # REST‑эндпоинт транскрибации
│ └─ static/index.html # Простая страница загрузки видео
├─ tests/
│ ├─ test_api.py # Юнит‑тесты API
│ └─ test_data/*.mp4 # Тестовые видео (в т.ч. «тихий» ролик)
├─ requirements.txt # Зависимости
├─ Dockerfile # Продакшен‑сборка
└─ README.md # (заменить на этот файл)
flowchart LR
UI[Web UI / клиент] -- video/mp4 --> API[FastAPI /api/v1/transcribe]
API -- UploadFile --> AS[audio_service.extract_audio]
AS -- FFmpeg --> WAV[(temp WAV 16kHz mono)]
WAV --> TS[transcription_service.transcribe_audio]
TS -- load once --> Whisper[(Whisper model)]
Whisper -- text+lang --> TS
TS -- JSON --> API
API -- language+transcript --> UI
sequenceDiagram
participant C as Client (UI/cURL)
participant A as FastAPI
participant FF as FFmpeg
participant W as Whisper
C->>A: POST /api/v1/transcribe (video file)
A->>FF: Извлечение аудио (PCM 16kHz mono)
FF-->>A: Путь к temp .wav
A->>W: model.transcribe(.wav)
W-->>A: { language, text }
A-->>C: 200 OK + JSON
/api/v1/transcribeФорма: multipart/form-data с полем file (видео — content_type начинается с video/).
Успешный ответ (200):
{
"video_id": "550e8400-e29b-41d4-a716-446655440000",
"language": "en",
"transcript": "Hello world ..."
}
Ошибки:
400 — неправильный тип файла (не video/*).500 — внутренняя ошибка при извлечении аудио/транскрипции.cURL пример:
curl -X POST \
-F "file=@/path/to/video.mp4" \
http://localhost:8000/api/v1/transcribe
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
Понадобится установленный FFmpeg в системе (ffmpeg в PATH).
WHISPER_MODEL — название модели Whisper: tiny | base | small | medium | large (по умолчанию base).uvicorn app.main:app --reload --port 8000
После запуска:
http://localhost:8000/http://localhost:8000/docsdocker build -t sparq-vr .
docker run --rm -p 8000:8000 -e WHISPER_MODEL=base --name sparq-app sparq-vr
Контейнер собран для прод‑режима на Uvicorn. Не забудьте выделить достаточно памяти для модели.
pytest -q
Включены проверки:
200 OK.content_type → 400 Bad Request.audio_service.extract_audio: сохраняет загруженное видео во временный файл и через ffmpeg извлекает mono 16kHz PCM .wav, затем чистит временные артефакты.transcription_service.transcribe_audio: лениво загружает модель (whisper.load_model), вызывает model.transcribe(fp16=False), удаляет временный .wav.api/v1/endpoints/transcription.py: проверка content_type, склейка сервиса аудио и сервиса транскрипции, единый обработчик ошибок, генерация video_id (uuid4).Сервис поддерживает два провайдера распознавания речи:
tiny, base, small, medium, largee2e_rnnt (рекомендуется), e2e_ctc, rnnt, ctc# Выбор провайдера: "whisper" или "gigaam"
STT_PROVIDER=whisper
# Настройки Whisper
WHISPER_MODEL=small
# Настройки GigaAM
GIGAAM_MODEL_VARIANT=e2e_rnnt
# A/B тестирование: процент запросов на GigaAM (0-100)
STT_AB_GIGAAM_PERCENT=0
Для сравнения провайдеров можно использовать A/B режим:
# 50% запросов на Whisper, 50% на GigaAM
STT_AB_GIGAAM_PERCENT=50 uvicorn app.main:app --reload
Для сравнения скорости и качества:
# Положите тестовые файлы в benchmark/test_samples/
python benchmark/run_benchmark.py --samples benchmark/test_samples/ --output benchmark/results/
# Результаты будут в benchmark/results/comparison.md
base/small.fp16=False (оставить по умолчанию) и запускать на CUDA-окружении.medium/large) могут быть очень медленными.finally, но при внезапном падении окружения имеет смысл запускать периодическую очистку /tmp.Где менять модель? — в переменной окружения WHISPER_MODEL или app/core/config.py.
Нужно ли отдельно ставить FFmpeg? — Да, бинарь ffmpeg должен быть в PATH (в Docker уже включён через базовый образ).
Как быстро проверить? — откройте http://localhost:8000/, загрузите .mp4 и смотрите JSON‑ответ.
Python
72.3%
HTML
25.2%
Dockerfile
2.5%
Лёгкий API‑сервис на FastAPI для транскрибации речи из видеофайлов с помощью OpenAI Whisper. На вход — видео, на выход — язык и текст. Есть простой Web UI для ручной загрузки, Docker‑окружение и автотесты.
Стек: Python, FastAPI, Uvicorn, FFmpeg (через ffmpeg-python), OpenAI Whisper, Docker, PyTest.
Ключевые фичи
POST /api/v1/transcribe — принимает видео и возвращает JSON с языком и транскриптом.GET / — статический Web UI для загрузки и проверки.GET /docs — интерактивная OpenAPI‑спецификация.Sparq_voice_recognition-master/
├─ app/
│ ├─ main.py # Точка входа FastAPI, маршруты и статик
│ ├─ core/
│ │ └─ config.py # Конфиг: выбор модели WHISPER_MODEL
│ ├─ services/
│ │ ├─ audio_service.py # Извлечение аудио из видео (FFmpeg)
│ │ └─ transcription_service.py# Загрузка и вызов Whisper, пост-очистка
│ ├─ api/
│ │ └─ v1/endpoints/transcription.py # REST‑эндпоинт транскрибации
│ └─ static/index.html # Простая страница загрузки видео
├─ tests/
│ ├─ test_api.py # Юнит‑тесты API
│ └─ test_data/*.mp4 # Тестовые видео (в т.ч. «тихий» ролик)
├─ requirements.txt # Зависимости
├─ Dockerfile # Продакшен‑сборка
└─ README.md # (заменить на этот файл)
flowchart LR
UI[Web UI / клиент] -- video/mp4 --> API[FastAPI /api/v1/transcribe]
API -- UploadFile --> AS[audio_service.extract_audio]
AS -- FFmpeg --> WAV[(temp WAV 16kHz mono)]
WAV --> TS[transcription_service.transcribe_audio]
TS -- load once --> Whisper[(Whisper model)]
Whisper -- text+lang --> TS
TS -- JSON --> API
API -- language+transcript --> UI
sequenceDiagram
participant C as Client (UI/cURL)
participant A as FastAPI
participant FF as FFmpeg
participant W as Whisper
C->>A: POST /api/v1/transcribe (video file)
A->>FF: Извлечение аудио (PCM 16kHz mono)
FF-->>A: Путь к temp .wav
A->>W: model.transcribe(.wav)
W-->>A: { language, text }
A-->>C: 200 OK + JSON
/api/v1/transcribeФорма: multipart/form-data с полем file (видео — content_type начинается с video/).
Успешный ответ (200):
{
"video_id": "550e8400-e29b-41d4-a716-446655440000",
"language": "en",
"transcript": "Hello world ..."
}
Ошибки:
400 — неправильный тип файла (не video/*).500 — внутренняя ошибка при извлечении аудио/транскрипции.cURL пример:
curl -X POST \
-F "file=@/path/to/video.mp4" \
http://localhost:8000/api/v1/transcribe
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
Понадобится установленный FFmpeg в системе (ffmpeg в PATH).
WHISPER_MODEL — название модели Whisper: tiny | base | small | medium | large (по умолчанию base).uvicorn app.main:app --reload --port 8000
После запуска:
http://localhost:8000/http://localhost:8000/docsdocker build -t sparq-vr .
docker run --rm -p 8000:8000 -e WHISPER_MODEL=base --name sparq-app sparq-vr
Контейнер собран для прод‑режима на Uvicorn. Не забудьте выделить достаточно памяти для модели.
pytest -q
Включены проверки:
200 OK.content_type → 400 Bad Request.audio_service.extract_audio: сохраняет загруженное видео во временный файл и через ffmpeg извлекает mono 16kHz PCM .wav, затем чистит временные артефакты.transcription_service.transcribe_audio: лениво загружает модель (whisper.load_model), вызывает model.transcribe(fp16=False), удаляет временный .wav.api/v1/endpoints/transcription.py: проверка content_type, склейка сервиса аудио и сервиса транскрипции, единый обработчик ошибок, генерация video_id (uuid4).Сервис поддерживает два провайдера распознавания речи:
tiny, base, small, medium, largee2e_rnnt (рекомендуется), e2e_ctc, rnnt, ctc# Выбор провайдера: "whisper" или "gigaam"
STT_PROVIDER=whisper
# Настройки Whisper
WHISPER_MODEL=small
# Настройки GigaAM
GIGAAM_MODEL_VARIANT=e2e_rnnt
# A/B тестирование: процент запросов на GigaAM (0-100)
STT_AB_GIGAAM_PERCENT=0
Для сравнения провайдеров можно использовать A/B режим:
# 50% запросов на Whisper, 50% на GigaAM
STT_AB_GIGAAM_PERCENT=50 uvicorn app.main:app --reload
Для сравнения скорости и качества:
# Положите тестовые файлы в benchmark/test_samples/
python benchmark/run_benchmark.py --samples benchmark/test_samples/ --output benchmark/results/
# Результаты будут в benchmark/results/comparison.md
base/small.fp16=False (оставить по умолчанию) и запускать на CUDA-окружении.medium/large) могут быть очень медленными.finally, но при внезапном падении окружения имеет смысл запускать периодическую очистку /tmp.Где менять модель? — в переменной окружения WHISPER_MODEL или app/core/config.py.
Нужно ли отдельно ставить FFmpeg? — Да, бинарь ffmpeg должен быть в PATH (в Docker уже включён через базовый образ).
Как быстро проверить? — откройте http://localhost:8000/, загрузите .mp4 и смотрите JSON‑ответ.
Python
72.3%
HTML
25.2%
Dockerfile
2.5%