#!/bin/sh set -eu model=${WHISPER_MODEL:-/models/ggml-small.bin} model_url=${WHISPER_MODEL_URL:-https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin} model_dir=$(dirname "$model") mkdir -p "$model_dir" chown 10004:10004 "$model_dir" if [ ! -s "$model" ]; then partial="${model}.part" echo "Downloading Whisper model to persistent storage" # All writes below must use the volume owner. The container deliberately # drops CAP_DAC_OVERRIDE, so even uid 0 cannot rename a file in the # whisper-owned directory after capabilities have been removed. if [ ! -s "$partial" ]; then gosu whisper rm -f "$partial" gosu whisper curl --fail --location --retry 5 --retry-delay 5 \ --output "$partial" "$model_url" fi gosu whisper mv "$partial" "$model" fi server_port=${WHISPER_SERVER_PORT:-8085} server_log=/tmp/whisper-server.log gosu whisper /opt/whisper.cpp/build/bin/whisper-server \ --model "$model" \ --threads "${WHISPER_THREADS:-8}" \ --language "${WHISPER_LANGUAGE:-de}" \ --host 127.0.0.1 \ --port "$server_port" \ --inference-path /inference \ --no-gpu >"$server_log" 2>&1 & server_pid=$! worker_pid="" cleanup() { [ -z "$worker_pid" ] || kill "$worker_pid" 2>/dev/null || true kill "$server_pid" 2>/dev/null || true } trap cleanup EXIT INT TERM # Der Modell-Load dauert beim Containerstart kurz. Der HTTP-Wrapper wird erst # freigegeben, wenn whisper-server tatsächlich Antworten annimmt. i=0 until curl --fail --silent "http://127.0.0.1:${server_port}/" >/dev/null; do i=$((i + 1)) if ! kill -0 "$server_pid" 2>/dev/null; then cat "$server_log" exit 1 fi if [ "$i" -ge 180 ]; then echo "whisper-server did not become ready" >&2 cat "$server_log" exit 1 fi sleep 1 done export WHISPER_SERVER_URL="http://127.0.0.1:${server_port}" gosu whisper python /app/stt_worker.py & worker_pid=$! wait "$worker_pid"