Whisper на GPU: Транскрибация быстрее API в 60 раз
TL;DR — Кратко:
- CPU не тянет: почему для продакшена Large-v3 нужна карта с 10GB+ VRAM.
- Faster-Whisper + CTranslate2 ускоряют инференс в 4 раза по сравнению с ванильной версией.
- Готовый код: заворачиваем микросервис на FastAPI в Docker с пробросом GPU.
Voice AI: Поднимаем Whisper для транскрибации. Быстро, дешево, на GPU
Пока менеджеры рисуют красивые презентации про “AI-революцию”, инженеры смотрят на счета от OpenAI за использование API. $0.006 за минуту аудио — это копейки, пока у вас пара тестов. Но когда нужно переварить архив записей колл-центра за год или транскрибировать потоки видео для арбитража, счетчик начинает крутиться быстрее, чем электросчетчик на майнинг-ферме.
К тому же, есть Privacy. Отправлять конфиденциальные звонки на серверы “дяди Сэма” — идея так себе, особенно если ваш NDA толщиной с “Войну и мир”.
Решение очевидное: Self-hosted Whisper. Поднимаем модель у себя, платим только за железку и не зависим от капризов API. В этой статье разберем, как развернуть Whisper в продакшене, почему ванильная версия от OpenAI — это тормоз, и как faster-whisper ускоряет инференс в 4-5 раз.
Часть 1. Железо: жадность моделей и VRAM
Первое, что нужно понять: CPU для инференса Whisper — это тупик. Если вы попытаетесь гонять модель large-v3 на процессоре, даже мощном, скорость будет удручающей (Real Time Factor > 1). То есть часовое аудио будет обрабатываться полтора часа. Нам такое не подходит.
Нам нужна GPU. И здесь важен объем VRAM, так как он диктует, какую версию модели вы сможете загрузить.
Таблица требований VRAM (приблизительно)
| Модель | Параметры | VRAM (FP16) | VRAM (INT8) | Качество | Применение |
|---|---|---|---|---|---|
| tiny | 39 M | ~1 GB | < 1 GB | Низкое | Голосовые команды |
| base | 74 M | ~1 GB | < 1 GB | Среднее | Черновики |
| small | 244 M | ~2 GB | ~1 GB | Приемлемое | YouTube субтитры (англ) |
| medium | 769 M | ~5 GB | ~3 GB | Хорошее | Подкасты, лекции |
| large-v3 | 1550 M | ~10 GB | ~6 GB | SOTA | Сложный продакшен |
Note: Данные в таблице — для загрузки весов. В процессе работы потребление памяти растет в зависимости от длины аудио и
beam_size.
Для серьезных задач (русский язык, сленг, шумы) нужна только Large-v3. Если у вас локально стоит RTX 3060 на 12GB — вы впритык, но влезете. Если же нужно обрабатывать потоки параллельно, вам потребуются серьезные карты уровня RTX A5000/A6000 или A100.
Например, на yougpu.ru мы часто видим, как клиенты берут A6000 (48GB VRAM). Это позволяет запустить 4-6 параллельных воркеров large-v3 и перемалывать сотни часов аудио в сутки.
Часть 2. Ванильный Whisper vs Faster-Whisper
Официальный репозиторий openai/whisper написан на PyTorch. Он работает, он точный, но он не оптимизирован для высоконагруженного продакшена.
Для продакшена стандартом де-факто стал проект Faster-Whisper.
В чем магия? Он использует CTranslate2 — движок инференса для Transformer-моделей, написанный на C++.
- Вес: Использует квантование (8-bit) без ощутимой потери качества.
- Скорость: В 4 раза быстрее ванильной реализации.
- Память: Жрет меньше VRAM.
Мы будем строить наше решение именно на faster-whisper.
Часть 3. Подготовка окружения (Docker)
Засорять хост-систему зависимостями Python — дурной тон. Будем все паковать в Docker.
Вам понадобятся:
- Linux (Ubuntu 20.04/22.04).
- Драйверы Nvidia (проверяем через
nvidia-smi). - NVIDIA Container Toolkit. Без него Докер не увидит видеокарту.
Если тулкит не стоит, ставим быстро:
curl -fsSL [https://nvidia.github.io/libnvidia-container/gpgkey](https://nvidia.github.io/libnvidia-container/gpgkey) | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
&& curl -s -L [https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list](https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list) |
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' |
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker Часть 4. Пишем сервис (FastAPI + Faster-Whisper)
Не будем запускать скрипты руками. Сделаем нормальный микросервис с API, который принимает файл и отдает JSON с текстом.
1. Структура проекта
whisper-service/
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── app/
└── main.py 2. requirements.txt
fastapi
uvicorn[standard]
python-multipart
faster-whisper 3. main.py (Сердце сервиса)
Здесь мы инициализируем модель один раз при старте приложения, а не на каждый запрос. Это критично для производительности.
from fastapi import FastAPI, UploadFile, File, HTTPException
from faster_whisper import WhisperModel
import os
import shutil
import time
app = FastAPI(title="Whisper GPU Service")
# Конфигурация
MODEL_SIZE = "large-v3"
DEVICE = "cuda" # Или "cpu", если вы мазохист
COMPUTE_TYPE = "float16" # Используйте "int8_float16" для экономии VRAM
print(f"Loading Whisper model: {MODEL_SIZE} on {DEVICE}...")
# Загружаем модель в память при старте
model = WhisperModel(MODEL_SIZE, device=DEVICE, compute_type=COMPUTE_TYPE)
print("Model loaded successfully!")
@app.post("/transcribe")
async def transcribe(file: UploadFile = File(...)):
start_time = time.time()
# Сохраняем временный файл
temp_filename = f"temp_{file.filename}"
try:
with open(temp_filename, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
# Инференс
# beam_size=5 дает лучшее качество, но медленнее. Для скорости ставьте 1.
segments, info = model.transcribe(temp_filename, beam_size=5, language="ru")
# Сборка результата. Важно: segments - это генератор!
# Транскрибация идет именно в момент итерации по генератору.
result_text = ""
segments_data = []
for segment in segments:
result_text += segment.text + " "
segments_data.append({
"start": segment.start,
"end": segment.end,
"text": segment.text
})
processing_time = time.time() - start_time
return {
"language": info.language,
"language_probability": info.language_probability,
"duration": info.duration,
"processing_time": processing_time,
"text": result_text.strip(),
"segments": segments_data
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
finally:
# Уборка мусора
if os.path.exists(temp_filename):
os.remove(temp_filename) 4. Dockerfile
Используем официальный образ Python. faster-whisper подтянет нужные бинарники CTranslate2 сам.
FROM python:3.10-slim
# Установка системных зависимостей (нужны для обработки аудио)
RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app /app
# Порт
EXPOSE 8000
# Запуск
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] 5. docker-compose.yml
Самая важная часть — проброс GPU.
version: "3.8"
services:
whisper:
build: .
ports:
- "8000:8000"
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1 # Количество GPU
capabilities: [gpu]
volumes:
- ./cache:/root/.cache/huggingface # Кешируем модель, чтобы не качать каждый раз Часть 5. Запуск и Тесты
Сборка и старт:
docker-compose up --build -dПроверка логов: Убедитесь, что модель загрузилась и CUDA видна.
docker-compose logs -fТестовый запрос (curl):
curl -X POST -F "file=@test_audio.mp3" http://localhost:8000/transcribe
Реальные цифры (Benchmarks)
Я прогнал 10-минутный подкаст на разных конфигурациях. Результаты вас удивят.
| Железо | Модель | Время обработки | RTF (Real Time Factor) |
|---|---|---|---|
| CPU (Core i9) | large-v3 | 14 мин 20 сек | 1.43 (Медленно!) |
| RTX 3060 (12GB) | large-v3 | 45 сек | 0.075 |
| RTX A5000 | large-v3 | 22 сек | 0.036 |
| RTX A6000 | large-v3 | 18 сек | 0.03 |
Если перевести это в деньги: арендуя сервер с GPU на yougpu.ru, вы платите фиксированную цену за час/месяц. При высокой загрузке стоимость минуты транскрибации падает до $0.0001. Это в 60 раз дешевле, чем API OpenAI.
Часть 6. Troubleshooting: Где вы набьете шишки
Даже у large-v3 бывают проблемы. Вот топ-3, с которыми я сталкивался в проде:
1. Галлюцинации в тишине
Если в аудио есть длинная пауза или фоновый шум, Whisper может начать генерировать бред: “Спасибо за просмотр”, “Субтитры создавал…” или повторять одну фразу бесконечно. Решение: В параметрах transcribe используйте VAD (Voice Activity Detection):
model.transcribe(..., vad_filter=True, vad_parameters=dict(min_silence_duration_ms=500)) Это жестко отрезает куски тишины перед подачей в нейронку.
2. CUDA Out Of Memory
Если вы закинете слишком длинный файл или поставите большой beam_size на слабой карте, скрипт упадет. Решение:
- Используйте
compute_type="int8". Качество почти не страдает, памяти ест на 30-40% меньше. - Уменьшайте
batch_size(если используете батчинг).
3. Неверное определение языка
Иногда Whisper думает, что русский — это болгарский, и выдает абракадабру. Решение: Всегда явно передавайте language="ru" (или другой нужный) в метод transcribe, если вы заранее знаете язык исходника. Не надейтесь на автодетект.
Заключение
Поднять свой Whisper — это задача на пару часов, включая настройку Docker. Взамен вы получаете полный контроль над данными, отсутствие лимитов по RPM (requests per minute) и существенную экономию на объемах.
Для экспериментов хватит и домашней игровой карты. Но если вы строите SaaS, которому нужно отвечать пользователю мгновенно, или обрабатываете архивы терабайтами — смотрите в сторону профессиональных карт с большим объемом памяти. Правильно подобранная инфраструктура окупается в первый же месяц активной работы.
Не хватает VRAM для Whisper Large-v3?
Перестаньте мучить процессор. Арендуйте сервер с RTX A6000 (48GB) и обрабатывайте аудио в 60 раз быстрее реального времени. Docker и драйверы уже на борту.
Запустить Whisper на GPU