Audio und Video lokal transkribieren mit Whisper (Docker)
Aufnahmen lokal in Text und Untertitel umwandeln: Whisper ASR Box 1.10 mit faster-whisper per Docker Compose auf der CPU betreiben, Dateien per API transkribieren, SRT und VTT exportieren und den Zugang absichern.
Geprüft am 14.10.2026 · für whisper-asr-webservice 1.10.0
WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Besprechungen, Interviews und Schulungsvideos lassen sich mit Whisper, dem Spracherkennungsmodell von OpenAI, zuverlässig in Text und Untertitel umwandeln. Wer Aufnahmen mit personenbezogenen Inhalten nicht zu einem Cloud-Dienst hochladen will, betreibt die Erkennung auf dem eigenen Server. Diese Anleitung nutzt dafür die Whisper ASR Box (Projekt ahmetoner/whisper-asr-webservice): einen Docker-Container mit REST-Schnittstelle, der Audio- und Videodateien annimmt und Text, SRT oder WebVTT zurückgibt. Sie läuft ohne GPU auf einem gewöhnlichen Linux-Server und wurde für diese Anleitung auf 2 CPU-Kernen getestet.
Voraussetzungen
- Server: Linux x86_64 oder ARM64 mit Docker Engine und Compose-Plugin, etwa Debian 12 oder Ubuntu 24.04. Das CPU-Image gibt es für beide Architekturen.
- CPU: mindestens 2 Kerne, besser 4 oder mehr. Die Erkennung skaliert mit der Kernzahl.
- RAM: 4 GB für die Modelle
baseundsmall(im Test belegte der Container mitsmallrund 1,3 GB), 8 GB oder mehr fürmediumundturbo. - Speicher: mindestens 12 GB frei. Das CPU-Image belegt entpackt 8,2 GB, dazu kommen die Modelle (
small: 464 MB). - GPU (optional): NVIDIA-Karte mit NVIDIA Container Toolkit. Laut OpenAI braucht
smalletwa 2 GB VRAM,medium5 GB,turbo6 GB undlarge10 GB.
Grundlagen zu Compose-Projekten finden Sie in Docker Compose: Multi-Container-Stacks aufbauen. Wer Whisper lieber am Arbeitsplatz-PC mit grafischer Oberfläche nutzt, findet den Weg in Whisper lokal mit GUI installieren.
Schritt 1: Lösung und Version festlegen
Whishper, das in der ersten Fassung dieser Anleitung beschrieben war, hat seit Version 3.1.4 vom 17.09.2024 kein Release mehr erhalten, laut README bekommt der Hauptzweig keine Updates. Für einen Dienst, der vertrauliche Aufnahmen verarbeitet, ist das kein tragfähiger Stand. Die Whisper ASR Box ist die schlankere, aktiv gepflegte Alternative:
| Merkmal | Whisper ASR Box |
|---|---|
| Version | 1.10.0 vom 09.08.2026, MIT-Lizenz |
| Image | onerahmet/openai-whisper-asr-webservice:v1.10.0 (CPU), :v1.10.0-gpu (NVIDIA) |
| Engines | openai-whisper, faster-whisper 1.2.1, WhisperX 3.4.5 |
| Port | 9000 (REST-API und Swagger-Oberfläche unter /docs) |
| Ausgabe | text, json, vtt, srt, tsv |
| Anmeldung | keine eingebaute |
Der Dienst bringt keine Benutzerverwaltung und keine Aufgabenliste mit. Das ist gewollt: Sie rufen ihn per Skript, aus einer Automatisierung oder über die Swagger-Seite auf. Die Engine faster_whisper ist auf der CPU deutlich sparsamer als das Original und unterstützt als einzige den VAD-Filter, der Stille vor der Erkennung entfernt.
Verifizieren: Rufen Sie https://github.com/ahmetoner/whisper-asr-webservice/releases auf und prüfen Sie, ob 1.10.0 noch das neueste Release ist. Gibt es ein neueres, übernehmen Sie dessen Tag in Schritt 2.
Schritt 2: Projektordner und Compose-Datei anlegen
sudo mkdir -p /opt/whisper
cd /opt/whisper
sudo nano compose.yaml
services:
whisper:
image: onerahmet/openai-whisper-asr-webservice:v1.10.0
container_name: whisper-asr
restart: unless-stopped
ports:
- "127.0.0.1:9000:9000"
environment:
ASR_ENGINE: faster_whisper
ASR_MODEL: small
ASR_DEVICE: cpu
ASR_QUANTIZATION: int8
ASR_MODEL_PATH: /data/whisper
MODEL_IDLE_TIMEOUT: 600
volumes:
- whisper-models:/data/whisper
volumes:
whisper-models:
| Variable | Wert | Bedeutung |
|---|---|---|
ASR_ENGINE | faster_whisper | Voreinstellung wäre openai_whisper |
ASR_MODEL | small | tiny, base, small, medium, large-v3, turbo |
ASR_QUANTIZATION | int8 | nur float32, float16 oder int8 erlaubt |
ASR_MODEL_PATH | /data/whisper | Modellablage im Volume |
MODEL_IDLE_TIMEOUT | 600 | Modell nach 10 Minuten ohne Anfrage entladen, spart RAM |
Die Portbindung an 127.0.0.1 ist wichtig: Der Dienst nimmt ohne Anmeldung jede Datei an und rechnet damit auf Ihrer CPU. Im Internet erreichbar wäre er ein offenes Rechenwerk für jeden. Das Volume hält die Modelle über Neustarts hinweg vor, sonst lädt der Container sie bei jedem Start erneut von Hugging Face. Das Projekt weist darauf hin, dass ein festes Modellverzeichnis Modellaktualisierungen verhindert; bei Whisper-Modellen ist das in der Praxis erwünscht.
Verifizieren: docker compose config -q endet ohne Ausgabe. Eine Meldung weist auf einen Einrückungsfehler in der YAML-Datei hin.
Schritt 3: Dienst starten und Modell laden
docker compose pull
docker compose up -d
docker compose logs -f
Der erste Pull dauert je nach Leitung einige Minuten, das CPU-Image ist komprimiert rund 2,7 GB groß (amd64). Beim ersten Start lädt der Container das Modell herunter. Die Meldung You are sending unauthenticated requests to the HF Hub ist ein Hinweis und kein Fehler; ein Hugging-Face-Token brauchen Sie nur für WhisperX mit Sprechertrennung. Ebenso harmlos sind mehrere SyntaxWarning: invalid escape sequence aus einer mitgelieferten Bibliothek. Im Test war der Dienst nach rund 40 Sekunden bereit.
Verifizieren: Im Log erscheint Uvicorn running on http://0.0.0.0:9000, und curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:9000/docs liefert 200. docker compose ps zeigt den Container als Up.
Schritt 4: Erste Datei transkribieren
Der Endpunkt /asr erwartet die Datei im Formularfeld audio_file. FFmpeg im Container wandelt gängige Audio- und Videoformate (MP3, M4A, OGG, WAV, MP4, MKV) selbst um. Die wichtigsten Parameter:
language=de: Sprache vorgeben. Ohne Angabe erkennt der Dienst die Sprache aus den ersten 30 Sekunden.output=srt: Ausgabeformat, möglich sindtext,json,vtt,srtundtsv.vad_filter=true: Stille entfernen, nur mit faster-whisper.task=translate: statt Transkription eine englische Übersetzung erzeugen.
curl -s -F "audio_file=@besprechung.mp3" \
"http://127.0.0.1:9000/asr?task=transcribe&language=de&output=srt&vad_filter=true" \
-o besprechung.srt
head besprechung.srt
Im Test lieferte eine Minute gesprochener Wikipedia-Text (freie Aufnahme von Wikimedia Commons) nach 14 Sekunden eine saubere SRT-Datei mit korrekter Zeichensetzung und Umlauten:
1
00:00:00,000 --> 00:00:06,640
Der Name Wikipedia ist ein Kofferwort, das sich zusammensetzt aus wiki, der mit dem
2
00:00:06,640 --> 00:00:12,840
hawaiischen Wort für schnell bezeichneten Technik zur kollektiven Erstellung von Internetseiten
Für einzelne Dateien ohne Kommandozeile öffnen Sie http://127.0.0.1:9000/docs über einen SSH-Tunnel oder den Reverse Proxy aus Schritt 6, klappen /asr auf und nutzen „Try it out“.
Verifizieren: Die SRT-Datei beginnt mit 1 und einer Zeitangabe im Format 00:00:00,000 --> …, der Text ist in der richtigen Sprache. Die Spracherkennung prüfen Sie mit curl -s -F "audio_file=@besprechung.mp3" http://127.0.0.1:9000/detect-language; im Test kam {"detected_language":"german","language_code":"de","confidence":0.948…} zurück.
Schritt 5: Mehrere Dateien automatisch verarbeiten
Im Alltag fallen Aufnahmen gesammelt an. Ein kurzes Skript arbeitet einen Ordner ab und legt Text und Untertitel neben jede Datei. Die Anfragen laufen nacheinander, weil parallele Aufträge auf einer kleinen CPU nur um die Kerne konkurrieren.
#!/usr/bin/env bash
# /opt/whisper/transkribieren.sh: alle Aufnahmen in einem Ordner verarbeiten
set -euo pipefail
ORDNER="${1:-/srv/aufnahmen}"
API="http://127.0.0.1:9000/asr?task=transcribe&language=de&vad_filter=true"
for f in "$ORDNER"/*.{mp3,m4a,wav,ogg,mp4}; do
[ -e "$f" ] || continue
ziel="${f%.*}"
[ -e "$ziel.srt" ] && continue
echo "Verarbeite $f"
curl -sf -F "audio_file=@$f" "$API&output=srt" -o "$ziel.srt"
curl -sf -F "audio_file=@$f" "$API&output=text" -o "$ziel.txt"
done
sudo chmod +x /opt/whisper/transkribieren.sh
/opt/whisper/transkribieren.sh /srv/aufnahmen
Das Skript überspringt Dateien, für die schon eine SRT-Datei existiert, und lässt sich daher per Cron regelmäßig starten. Es sendet jede Datei zweimal; bei langen Aufnahmen ist output=json sparsamer, weil die Antwort Volltext und Segmente mit Zeitstempeln enthält.
Verifizieren: Nach dem Lauf liegt neben jeder Aufnahme eine .srt- und eine .txt-Datei. Ein zweiter Aufruf gibt keine Zeile „Verarbeite“ mehr aus.
Schritt 6: Zugriff absichern und aktualisieren
Sollen Kolleginnen und Kollegen die Swagger-Seite im Browser nutzen, stellen Sie einen Reverse Proxy mit HTTPS und Anmeldung davor. Mit Caddy genügt ein Block mit Basic-Auth; den Passwort-Hash erzeugen Sie mit caddy hash-password:
whisper.example.de {
basic_auth {
team $2a$14$ERSETZEN-DURCH-HASH
}
request_body {
max_size 500MB
}
reverse_proxy 127.0.0.1:9000
}
Die Einrichtung von Caddy selbst beschreibt Caddy als Reverse Proxy einrichten. Lange Aufnahmen brauchen auf der CPU mehrere Minuten; setzen Sie bei anderen Proxys die Lese-Timeouts entsprechend hoch.
Für ein Update tragen Sie den neuen Tag in compose.yaml ein, danach:
docker compose pull
docker compose up -d
docker rmi onerahmet/openai-whisper-asr-webservice:v1.10.0 # alten Tag entfernen
Eine Datensicherung im engeren Sinn ist nicht nötig: Der Dienst speichert weder Dateien noch Ergebnisse. Sichern Sie compose.yaml, das Skript und die erzeugten Texte.
Verifizieren: Ohne Anmeldung liefert curl -s -o /dev/null -w '%{http_code}\n' https://whisper.example.de/docs den Wert 401, mit -u team:PASSWORT den Wert 200. Nach einem Update zeigt curl -s http://127.0.0.1:9000/openapi.json im Feld version die neue Versionsnummer.
Typische Fehler
Container startet in einer Schleife neu
docker compose ps zeigt Restarting (1), im Log steht ValueError: Invalid MODEL_QUANTIZATION. Choose 'float32', 'float16', or 'int8'. Das passiert im Test mit dem Wert int4. Nur die drei genannten Werte sind zulässig; auf der CPU ist int8 richtig.
HTTP 422 mit „Field required“
Die Anfrage enthielt keine Datei im Feld audio_file, etwa wegen eines Tippfehlers im Feldnamen oder -d statt -F. Die Antwort lautet dann {"detail":[{"type":"missing","loc":["body","audio_file"],"msg":"Field required",…}]}.
Unbekanntes Ausgabeformat liefert trotzdem Text
Ein nicht unterstützter Wert wie output=docx wird nicht abgelehnt: Der Dienst antwortet mit HTTP 200 und reinem Text. Skripte, die eine SRT-Datei erwarten, sollten deshalb den Inhalt prüfen und nicht nur den Statuscode.
Transkription dauert sehr lange
Auf der CPU bestimmen Modell und Kernzahl die Dauer. Wechseln Sie auf base oder aktivieren Sie vad_filter=true, wenn Aufnahmen viele Pausen enthalten. Prüfen Sie, dass ASR_ENGINE auf faster_whisper steht.
Speicherplatz reicht beim Pull nicht
Das CPU-Image belegt 8,2 GB, das GPU-Image deutlich mehr. Prüfen Sie vorher mit df -h /var/lib/docker.
Häufige Fragen
Werden Daten an OpenAI oder andere Dienste gesendet?
Nein. Die Erkennung läuft vollständig im Container. Nach außen verbindet sich der Dienst nur, um Modelle von Hugging Face zu laden; mit dem Volume geschieht das einmalig.
Welches Modell eignet sich für Besprechungen?
Auf der CPU ist small ein guter Ausgleich aus Qualität und Tempo. Mit GPU liefert turbo, eine optimierte Fassung von large-v3, bessere Ergebnisse bei Fachbegriffen und Dialekt.
Kann der Dienst Sprecher unterscheiden?
Mit der Engine whisperx, einem Hugging-Face-Token in HF_TOKEN und dem Parameter diarize=true kennzeichnet er Sprecher. Das braucht deutlich mehr Speicher.
Wie nutze ich eine NVIDIA-GPU?
Verwenden Sie das Image :v1.10.0-gpu, entfernen Sie ASR_DEVICE und ASR_QUANTIZATION (Standard auf der GPU ist float32) und reservieren Sie die Karte im Compose-Dienst unter deploy.resources.reservations.devices mit driver: nvidia. Voraussetzung ist das NVIDIA Container Toolkit auf dem Host.
Fazit
Die Whisper ASR Box ersetzt die eingestellte Oberfläche Whishper durch einen kleinen, gepflegten Dienst, der genau eine Aufgabe erfüllt: Dateien annehmen und Text zurückgeben. Mit faster-whisper und dem Modell small reichen zwei CPU-Kerne für gelegentliche Besprechungsprotokolle, eine GPU lohnt sich erst bei vielen Stunden Material pro Woche. Weil der Dienst keine Anmeldung kennt, bleibt er an 127.0.0.1 gebunden und ist nur über einen Reverse Proxy mit Zugangsschutz erreichbar.


