Architektur¶
ASR Transcription ist als eigenständiger Anwendungs-Container ausgelegt, der als Vermittler zwischen Browser und Inferenz-Server arbeitet. Die Audiodaten werden lokal in der Anwendung vorverarbeitet, segmentiert und nach der Transkription qualitätsbereinigt; die eigentliche Spracherkennung läuft auf einem separat betriebenen vLLM-Server. Diese Trennung erlaubt es, Frontend und Modell unabhängig voneinander zu betreiben und das ASR-Modell durch Konfigurationsänderung zu wechseln.
Auf einen Blick¶
- Drei-Schichten-Modell: Browser (Oberfläche) → Anwendung (Audio-Pipeline und Orchestrierung) → vLLM (Inferenz)
- Zustandslos gegenüber dem Backend; einziger anwendungsseitiger Zustand ist der Live-Buffer pro Session
- Streaming im Live-Modus über Gradio-Stream-Events; Datei- und Batch-Modus arbeiten request-basiert
- Audio-Pipeline: Resampling auf 16 kHz Mono, optionale Vorverarbeitung, Segmentierung mit VAD, Inferenzaufruf, Halluzinations-Bereinigung
- Zwei nutzbare Backend-Endpoints:
/v1/audio/transcriptions(Standard) und/v1/chat/completions(mit System-Prompt) - Konfiguration vollständig über Umgebungsvariablen und
.env-Datei - Containerisierte Auslieferung mit nicht-privilegiertem Laufzeit-User und integriertem Healthcheck
Architekturbeschreibung¶
Die Anwendung gliedert sich in eine Frontend-Schicht (Gradio 6 mit vier Tabs für Live, Datei, Batch, Test), eine Verarbeitungsschicht (Audio-Hilfsfunktionen, Vorverarbeitung, Segmentierung, Dispatcher, Post-Processing) und einen externen Inferenz-Layer (vLLM-Server). Das Frontend wird vom Anwendungs-Prozess selbst gerendert; der Browser kommuniziert über Gradio-eigene Protokolle (HTTP-Requests und Stream-Events) mit der Anwendung. Die Verarbeitungsschicht wandelt eingehendes Audio in das vom ASR-Server erwartete Format (PCM16, 16 kHz, Mono), wendet bei Bedarf Vorverarbeitung an, segmentiert lange Aufnahmen, leitet die einzelnen Segmente per HTTP an den vLLM-Server weiter und bereinigt die Antwort.
flowchart LR
subgraph Client["Browser"]
Mic[Mikrofon-Stream]
Upload[Datei-Upload]
Out[Transkript / Download]
end
subgraph App["ASR Transcription Container"]
UI[Gradio-Oberfläche<br/>Live · Datei · Batch · Test]
Buf[Session-Buffer<br/>Live-Modus]
Pre[Audio-Vorverarbeitung<br/>Normalisierung · Denoise · Hochpass]
Seg[Segmentierung mit<br/>VAD-Stille-Erkennung]
Disp{API-Dispatcher}
Post[Halluzinations-<br/>Bereinigung]
end
subgraph Backend["Inferenz-Backend"]
vLLM[vLLM-Server<br/>OpenAI-kompatible API]
end
Mic --> UI
Upload --> UI
UI --> Buf
UI --> Pre
Buf --> Disp
Pre --> Seg
Seg --> Disp
Disp -->|Transcriptions-API| vLLM
Disp -->|Chat-API| vLLM
vLLM --> Post
Post --> UI
UI --> Out
Workflow¶
Im Live-Modus sendet der Browser numpy-Audio-Chunks im Sekundentakt an die Anwendung. Pro Session existiert ein Buffer, in den die Chunks geschrieben werden; sobald die akkumulierte Dauer das eingestellte Verarbeitungsfenster (Standard 3 Sekunden) erreicht, wird der Buffer geleert, in WAV (16 kHz, Mono, PCM16) konvertiert und an den Inferenz-Server gesendet. Die Antwort wird halluzinations-bereinigt und an das Transkriptionsfeld angehängt. Beim Stoppen der Aufnahme wird der Restbuffer ein letztes Mal verarbeitet und der Session-Zustand verworfen.
Im Datei-Modus wird die hochgeladene Datei zunächst — falls aktiviert — vorverarbeitet (Hochpass-Filter, spektrales Denoising, Peak-Normalisierung) und anschließend geprüft, ob sie die maximale Segmentlänge überschreitet. Kürzere Dateien gehen unverändert an den Server; längere werden in überlappende FLAC-Segmente geschnitten, jeweils einer VAD unterzogen (stille Segmente werden übersprungen) und nacheinander transkribiert. Die Teilergebnisse werden mit Zeitstempeln versehen und im Ergebnisfeld zusammengeführt; das Feld aktualisiert sich nach jedem Segment, sodass der Fortschritt sichtbar bleibt.
Der Batch-Modus wendet denselben Verarbeitungsweg auf mehrere Dateien sequenziell an. Jede Datei wird einzeln vorverarbeitet, segmentiert, transkribiert und mit ihrem Ergebnis-Block in die Gesamtausgabe aufgenommen.
Der Test-Tab ruft die Modelliste am Inferenz-Server ab, sendet einen kurzen Stille-Test an die Transcriptions- und Chat-API und gibt Statuscodes und Antwort-Auszüge in einem Status-Block aus; ergänzt wird die Anzeige um die aktiven Konfigurationswerte.
API-Methoden¶
Der Dispatcher entscheidet anhand einer Auswahl in der Oberfläche, ob ein Segment über /v1/audio/transcriptions oder über /v1/chat/completions an den Server geht. Die Transcriptions-Variante übergibt Audio als Multipart-Upload und reicht Sprache, Temperature und einen optionalen Prompt als Formularfelder mit. Die Chat-Variante kodiert das Audio als Base64-Data-URI in einem Chat-Message-Objekt und versieht den Aufruf mit einem System-Prompt, der das Modell anweist, ausschließlich den transkribierten Text zurückzugeben und vorgegebene Eigennamen und Fachbegriffe exakt zu schreiben. Bei der Chat-Variante wird die Antwort zusätzlich auf eine ASR-typische Hülle (<asr_text>…) geprüft und entsprechend reduziert.
Audio-Pipeline¶
Die Audio-Pipeline ist auf das vom Modell erwartete Format ausgerichtet (16 kHz, Mono, PCM16). Eingangs wird das Browser-Audio-Array auf den Bereich [-1, 1] normalisiert, bei Bedarf gemischt und resampelt. In der optionalen Vorverarbeitung wird zunächst ein Butterworth-Hochpass bei 80 Hz angewendet, danach ein spektrales Gating gegen stationäres Rauschen und abschließend eine Peak-Normalisierung auf -1 dB. Die Segmentierung verwendet eine energiebasierte VAD (RMS pro 25-ms-Frame mit konfiguriertem Schwellenwert und Mindest-Sprachanteil) und erzeugt FLAC-Segmente mit zwei Sekunden Überlappung.
Post-Processing¶
Die Antworten des Servers werden vor der Anzeige durch eine Halluzinations-Bereinigung geführt. Erkannt werden zwei Muster: Wiederholungen kurzer Zeichenfolgen, wie sie bei CJK-Halluzinationen auftreten, und mehrfach wiederholte kurze Phrasen. Beide werden durch den ersten Treffer und ein Auslassungszeichen ersetzt. Wird durch die Bereinigung mehr als 80 % des Originaltextes entfernt, gilt die Antwort als vollständig halluziniert und wird durch einen Hinweistext ersetzt.
Nebenläufigkeit und Robustheit¶
Live-Buffer werden pro Session in einem zentralen Dictionary gehalten und durch Locks geschützt; beim Beenden einer Session werden sie über einen Cleanup-Callback freigegeben. Beim Anwendungsstart wird parallel ein Warm-up-Request an die Chat-API gesendet, damit die erste produktive Anfrage nicht durch die Initialisierung des Inferenz-Handlers verzögert wird. Fehler in einzelnen Segmenten unterbrechen die Verarbeitung nicht: HTTP-Statuscode und ein Auszug der Antwort werden in das Ergebnis aufgenommen, die Verarbeitung läuft weiter.
Konfiguration und Deployment¶
Die Anwendung wird als Docker-Image auf Basis von python:3.11-slim ausgeliefert. Im Image enthalten sind die Audio-Systembibliotheken (libsndfile, FFmpeg) und die Python-Abhängigkeiten. Der Prozess läuft als nicht-privilegierter Benutzer; ein Healthcheck prüft die Erreichbarkeit des Gradio-Ports. Sämtliche Laufzeitparameter — Backend-URL, API-Key, Modelltyp und Modell-ID, Default-Werte für Temperature, Antwortformat und Verarbeitungsfenster, maximale Segmentlänge, Server-Bind und Reverse-Proxy-Pfad — werden über Umgebungsvariablen oder eine .env-Datei gesetzt.
Technologie-Übersicht¶
- Frontend — Gradio 6 (Streaming-Audio-Komponente, Tabs, State-Verwaltung, Theme ohne externe Schriftarten)
- Backend-API — vLLM ≥ 0.17.0 mit OpenAI-kompatibler Audio-API (
/v1/audio/transcriptions) und Chat-API mit Audio-Input - ASR-Modelle — Qwen/Qwen3-ASR-1.7B oder mistralai/Voxtral-Mini-4B-Realtime-2602, Auswahl über Konfiguration
- Audio-Verarbeitung — librosa (Decoding, Resampling, RMS, Preemphasis), soundfile (WAV/FLAC), noisereduce (spektrales Gating), scipy (Butterworth-Hochpass)
- HTTP — requests mit optionalem Bearer-Auth
- Konfiguration — python-dotenv, Umgebungsvariablen
- Containerisierung — Docker (python:3.11-slim, FFmpeg, libsndfile, nicht-privilegierter User, Healthcheck)