commit 2b9442f33e4e9a86d77b81571c9026a6224b11e3 Author: enne2 Date: Thu Aug 13 22:29:30 2026 +0200 stt-server: FastAPI whisper.cpp Vulkan ASR + pyannote diarization, containerizzato diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b6cf5f0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..da883b9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,64 @@ +# syntax=docker/dockerfile:1 +# ============================================================================ +# stt-server containerizzato (whisper.cpp Vulkan ASR + pyannote diarization) +# ---------------------------------------------------------------------------- +# GPU: AMD/Intel via Mesa RADV (/dev/dri/renderD128). Il driver kernel resta +# sull'host; il container monta solo il device node. +# +# Build: docker build -t stt-server:vulkan . +# Run: docker compose up -d (vedi docker-compose.yml) +# ============================================================================ + +# ------------------------------------------------------------- Vulkan build +# glslc (shader compiler) è impacchettato solo dal repo LunarG su Ubuntu 22.04 +FROM ubuntu:22.04 AS build-vulkan + +RUN apt-get update -qq && apt-get install -y -qq --no-install-recommends \ + git ca-certificates cmake g++ make wget gnupg \ + > /dev/null && rm -rf /var/lib/apt/lists/* + +RUN wget -qO- https://packages.lunarg.com/lunarg-signing-key-pub.asc | gpg --dearmor -o /usr/share/keyrings/lunarg.gpg && \ + echo "deb [signed-by=/usr/share/keyrings/lunarg.gpg] https://packages.lunarg.com/vulkan/1.3.296 jammy main" \ + > /etc/apt/sources.list.d/lunarg-vulkan.list && \ + apt-get update -qq && apt-get install -y -qq --no-install-recommends vulkan-sdk \ + > /dev/null && rm -rf /var/lib/apt/lists/* + +# whisper.cpp: commit verificato con build Vulkan su Radeon 780M +RUN git clone https://github.com/ggerganov/whisper.cpp.git /build/whisper.cpp && \ + cd /build/whisper.cpp && git checkout 592feef + +WORKDIR /build/whisper.cpp +# GGML_NATIVE=OFF: binario portabile tra CPU diverse +RUN cmake -B build -DGGML_VULKAN=ON -DGGML_NATIVE=OFF -DCMAKE_BUILD_TYPE=Release && \ + cmake --build build --config Release -j"$(nproc)" --target whisper-cli + +# ------------------------------------------------------------------ runtime +FROM python:3.11-slim AS runtime + +RUN apt-get update -qq && apt-get install -y -qq --no-install-recommends \ + libgomp1 libvulkan1 mesa-vulkan-drivers libsndfile1 curl ca-certificates \ + > /dev/null && rm -rf /var/lib/apt/lists/* + +WORKDIR /app +COPY --from=build-vulkan /build/whisper.cpp/build/bin/whisper-cli /build/whisper.cpp/build/bin/*.so* ./ + +# torch CPU (niente CUDA) prima di requirements, per evitare il wheel CUDA +RUN pip install --no-cache-dir torch==2.9.1 --index-url https://download.pytorch.org/whl/cpu + +COPY requirements.txt ./requirements.txt +RUN pip install --no-cache-dir -r requirements.txt + +COPY server.py transcribe.py entrypoint.sh ./ +RUN chmod +x ./entrypoint.sh + +# Le librerie ggml copiate fuori dall'albero di build hanno RPATH interno: +# serve il path esplicito. +ENV LD_LIBRARY_PATH=/app +ENV GGML_BACKEND=Vulkan0 +ENV WHISPER_CLI=/app/whisper-cli +ENV MODELS_DIR=/models +ENV STT_PYTHON=python3 +ENV HF_HOME=/hf-cache + +EXPOSE 8883 +ENTRYPOINT ["./entrypoint.sh"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..60498ff --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,41 @@ +# ============================================================================ +# stt-server (whisper.cpp Vulkan + pyannote) — docker compose +# ---------------------------------------------------------------------------- +# Uso: +# export RENDER_GID=$(getent group render | cut -d: -f3) # GID gruppo render +# docker compose up -d --build +# +# GPU: AMD/Intel via Mesa RADV (/dev/dri/renderD128). Su host dove il node +# è world-writable (es. Fedora) group_add non è necessario ma innocuo. +# +# Variabili utili: +# MODELS_DIR : dir con ggml-large-v3-turbo.bin + ggml-silero-v6.2.0.bin +# HF_CACHE : cache HuggingFace (pyannote Community-1, gated) +# HF_TOKEN : token HF (solo se la cache non contiene i modelli) +# PORT : porta host (default 8883) +# ============================================================================ +services: + stt-server: + build: + context: . + dockerfile: Dockerfile + image: stt-server:vulkan + container_name: stt-server + devices: + - /dev/dri/renderD128:/dev/dri/renderD128 + group_add: + - "${RENDER_GID:-44}" + environment: + GGML_BACKEND: Vulkan0 + WHISPER_CLI: /app/whisper-cli + MODELS_DIR: /models + STT_PYTHON: python3 + HF_HOME: /hf-cache + HF_TOKEN: ${HF_TOKEN:-} + PORT: "8883" + volumes: + - "${MODELS_DIR:-/home/enne2/dev/whisper.cpp/models}:/models:ro" + - "${HF_CACHE:-/home/enne2/.cache/huggingface}:/hf-cache:ro" + ports: + - "${PORT:-8883}:8883" + restart: unless-stopped diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..4608c9a --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Entrypoint stt-server: avvia il server FastAPI (uvicorn via server.py). +# Tutti i parametri sono configurabili via variabili d'ambiente. +set -e + +echo "[stt] avvio stt-server (whisper-cli=$WHISPER_CLI models=$MODELS_DIR port=$PORT)" +exec python3 /app/server.py diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a9c5646 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +fastapi==0.128.0 +uvicorn>=0.30 +python-multipart==0.0.21 +pyannote.audio==4.0.7 +numpy==2.3.5 +soundfile==0.14.0 +huggingface_hub==1.15.0 diff --git a/server.py b/server.py new file mode 100644 index 0000000..92380e5 --- /dev/null +++ b/server.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +"""STT Server persistente (frigate.vpn:8883). +ASR: whisper.cpp (Vulkan) | Diarization opzionale: pyannote Community-1 (CPU) + +Endpoints: + GET /health → {"status": "ok", "model": ...} + POST /transcribe → multipart: file=