Add Docker support with preloaded models and docker-compose
This commit is contained in:
parent
96426a09b4
commit
0931a15d32
60
.dockerignore
Normal file
60
.dockerignore
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
.Python
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# Git
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# Данные пользователя
|
||||||
|
uploads/
|
||||||
|
processed/
|
||||||
|
tmp/
|
||||||
|
output/
|
||||||
|
video/
|
||||||
|
*.mp4
|
||||||
|
*.wav
|
||||||
|
*.docx
|
||||||
|
*.md
|
||||||
|
*.txt
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Логи
|
||||||
|
server.log
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Секреты
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
*.key
|
||||||
|
*.secret
|
||||||
36
Dockerfile
Normal file
36
Dockerfile
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
FROM python:3.11-slim-bookworm
|
||||||
|
|
||||||
|
# Установка системных зависимостей
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
ffmpeg \
|
||||||
|
build-essential \
|
||||||
|
libsndfile1 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Рабочая директория
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Копируем зависимости
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Копируем код проекта
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Предзагрузка моделей (без HF_TOKEN диаризация пропускается)
|
||||||
|
RUN python scripts/download_models.py || echo "Модели будут загружены при первом запуске"
|
||||||
|
|
||||||
|
# Создаём директории для данных
|
||||||
|
RUN mkdir -p uploads processed tmp
|
||||||
|
|
||||||
|
# Открываем порт
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
# Entrypoint скрипт
|
||||||
|
COPY scripts/docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
RUN chmod +x /docker-entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
|
CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
29
docker-compose.yml
Normal file
29
docker-compose.yml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
transcription:
|
||||||
|
build: .
|
||||||
|
container_name: transcription_service
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
environment:
|
||||||
|
- HF_TOKEN=${HF_TOKEN}
|
||||||
|
- PYTHONUNBUFFERED=1
|
||||||
|
volumes:
|
||||||
|
- uploads:/app/uploads
|
||||||
|
- processed:/app/processed
|
||||||
|
- tmp:/app/tmp
|
||||||
|
# Модели кэшируются в контейнере, но можно пробросить для переиспользования:
|
||||||
|
# - model_cache:/root/.cache
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/api/files"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 60s
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
uploads:
|
||||||
|
processed:
|
||||||
|
tmp:
|
||||||
22
scripts/docker-entrypoint.sh
Normal file
22
scripts/docker-entrypoint.sh
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🚀 Transcription Service Docker Container"
|
||||||
|
echo "=========================================="
|
||||||
|
|
||||||
|
# Проверяем HF_TOKEN
|
||||||
|
if [ -z "$HF_TOKEN" ]; then
|
||||||
|
echo "⚠️ Внимание: HF_TOKEN не установлен. Диаризация будет недоступна."
|
||||||
|
echo " Запустите с: docker compose up -e HF_TOKEN=your_token"
|
||||||
|
else
|
||||||
|
echo "✅ HF_TOKEN установлен"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Создаём директории если их нет
|
||||||
|
mkdir -p uploads processed tmp
|
||||||
|
|
||||||
|
echo "📡 Запуск сервера на http://0.0.0.0:8000"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Запускаем uvicorn (worker'ы стартуют через lifespan в backend/main.py)
|
||||||
|
exec "$@"
|
||||||
71
scripts/download_models.py
Normal file
71
scripts/download_models.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
"""Скрипт предзагрузки моделей для Docker образа.
|
||||||
|
|
||||||
|
Запускается во время сборки Docker образа.
|
||||||
|
Загружает все необходимые модели, чтобы при старте контейнера
|
||||||
|
не нужно было ждать скачивания.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Устанавливаем токен HuggingFace из env или placeholder
|
||||||
|
os.environ.setdefault("HF_TOKEN", os.environ.get("HF_TOKEN", ""))
|
||||||
|
|
||||||
|
import whisperx
|
||||||
|
|
||||||
|
|
||||||
|
def download_whisper_model(model_name="large-v3"):
|
||||||
|
"""Загружает модель Whisper."""
|
||||||
|
print(f"[Download] Whisper модель: {model_name}")
|
||||||
|
device = "cpu"
|
||||||
|
compute_type = "int8"
|
||||||
|
model = whisperx.load_model(model_name, device, compute_type=compute_type)
|
||||||
|
print(f"[Download] Whisper {model_name} готова")
|
||||||
|
del model
|
||||||
|
|
||||||
|
|
||||||
|
def download_alignment_model(language="ru"):
|
||||||
|
"""Загружает alignment модель для языка."""
|
||||||
|
print(f"[Download] Alignment модель для {language}")
|
||||||
|
device = "cpu"
|
||||||
|
model_a, metadata = whisperx.load_align_model(language_code=language, device=device)
|
||||||
|
print(f"[Download] Alignment {language} готова")
|
||||||
|
del model_a
|
||||||
|
|
||||||
|
|
||||||
|
def download_diarization_model():
|
||||||
|
"""Загружает модель диаризации."""
|
||||||
|
print("[Download] Модель диаризации")
|
||||||
|
token = os.environ.get("HF_TOKEN", "")
|
||||||
|
if not token:
|
||||||
|
print("[Warning] HF_TOKEN не установлен — модель диаризации не загружена!")
|
||||||
|
print("[Warning] При старте контейнера установите HF_TOKEN через env.")
|
||||||
|
return
|
||||||
|
from whisperx.diarize import DiarizationPipeline
|
||||||
|
device = "cpu"
|
||||||
|
diarize_model = DiarizationPipeline(token=token, device=device)
|
||||||
|
print("[Download] Диаризация готова")
|
||||||
|
del diarize_model
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("=" * 60)
|
||||||
|
print("Предзагрузка моделей для Docker образа")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
download_whisper_model("large-v3")
|
||||||
|
download_alignment_model("ru")
|
||||||
|
|
||||||
|
# Диаризация требует токен, поэтому опционально
|
||||||
|
try:
|
||||||
|
download_diarization_model()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Warning] Диаризация не загружена: {e}")
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print("Предзагрузка завершена")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Reference in New Issue
Block a user