Neuigkeiten von trion.
Immer gut informiert.

Telefonkonferenzen mit FreeSWITCH auf Kubernetes: Transkript, Protokoll und Suche mit lokaler KI

Ein alter Seemann am hölzernen Steuerrad mit blauer Nabe, um ihn herum vier Personen im Gespräch an Deck eines Segelschiffs

Wir haben unsere Telefonanlage auf Kubernetes umgezogen. Dabei kam eine Funktion hinzu, die im Alltag schnell unverzichtbar wurde: Telefonkonferenzen werden transkribiert, zusammengefasst und durchsuchbar. Jeder Teilnehmer wird auf einer eigenen Spur aufgezeichnet, Whisper erstellt daraus das Transkript und ein lokales Sprachmodell das Protokoll mit Entscheidungen und Aufgaben. Gesucht wird in OpenSearch per Volltext und nach Bedeutung, so findet man auch Gespräche, in denen ein Begriff nicht wörtlich gefallen ist.

Alle Daten bleiben dabei im eigenen Cluster, auch die KI-Modelle laufen auf eigener Hardware. Dieser Beitrag beschreibt den Aufbau und die Punkte, an denen wir nachjustieren mussten. Zum Schluss geht es darum, was vor einer Aufzeichnung rechtlich zu beachten ist.

FreeSWITCH auf Kubernetes

Die Telefonie übernimmt FreeSWITCH, betrieben in einem Talos-Kubernetes-Cluster auf Servern bei Hetzner. Wie so ein Cluster entsteht, beschreibt der Beitrag Talos Kubernetes auf Hetzner Cloud einfach einrichten.

SIP und RTP vertragen sich schlecht mit dem üblichen Kubernetes-Netzwerk. Beide Protokolle tragen Adressen im Inhalt, und RTP braucht große Portbereiche in beide Richtungen. Ein Service vom Typ LoadBalancer mit NAT davor hilft hier wenig.

Wir geben dem FreeSWITCH-Pod deshalb eine öffentliche IP-Adresse direkt am Pod. Ein Init-Container legt dazu ein macvlan-Interface im vSwitch-VLAN des Rechenzentrums an, eine Firewall auf diesem Interface lässt nur SIP, RTP und WireGuard herein. Die Telefone an den Standorten erreichen den Pod über WireGuard unter einer festen internen Adresse. Weil das VLAN auf allen Nodes anliegt, nimmt der Pod seine Adressen mit, wenn er auf einen anderen Node verschoben wird. Laufende Gespräche enden dabei, für eine Telefonanlage dieser Größe ist das vertretbar.

Bei größeren Anlagen würde man das anders lösen. Mehrere FreeSWITCH-Instanzen arbeiten dann hinter einem SIP-Proxy wie Kamailio oder OpenSIPS, der neue Anrufe auf die Instanzen verteilt. Vor einer Wartung nimmt man eine Instanz aus der Verteilung und wartet, bis ihre Gespräche beendet sind. In Kubernetes lässt sich das mit einem preStop-Hook abbilden, der per fsctl pause keine neuen Anrufe mehr annimmt, zusammen mit einer ausreichend langen terminationGracePeriodSeconds. Sollen auch ungeplante Ausfälle laufende Gespräche nicht beenden, kann FreeSWITCH den Gesprächszustand mit track-calls in einer gemeinsamen Datenbank ablegen. Eine Ersatzinstanz übernimmt dann die IP-Adresse und stellt die Gespräche mit sofia recover wieder her.

FreeSWITCH selbst bleibt fast ohne eigene Konfiguration. Benutzer, Dialplan und Gateways liefert ein Spring Boot Service über mod_xml_curl zur Laufzeit aus der Datenbank. Über den Event Socket verfolgt derselbe Service Anrufe und steuert die Aufzeichnung.

Aufzeichnung pro Teilnehmer

Eine Konferenz wird nicht als eine gemischte Tonspur aufgezeichnet, sondern als eine Spur pro Teilnehmer. FreeSWITCH streamt jede Spur mit mod_audio_stream per WebSocket live an den Service, 16 kHz mono. Der Service verschlüsselt die Audiodaten blockweise (Tink, Streaming AEAD) und legt sie in einem S3-kompatiblen Objektspeicher im Cluster ab.

Getrennte Spuren haben zwei Vorteile. Im Player lässt sich jeder Teilnehmer einzeln lauter oder leiser stellen. Vor allem aber ist klar, wer gerade spricht, ohne dass ein Modell Sprecher an der Stimme unterscheiden muss.

Transkript mit Whisper

Für die Spracherkennung läuft Whisper (large-v3-turbo) auf einem eigenen GPU-Rechner hinter llama-swap. llama-swap stellt mehrere Modelle unter einer OpenAI-kompatiblen API bereit und lädt sie bei Bedarf. Über Gruppen bleibt Whisper dauerhaft geladen, ohne die Sprachmodelle zu verdrängen. Der GPU-Rechner rechnet nur, er speichert und protokolliert weder Audio noch Text.

Whisper verarbeitet lange Aufnahmen nicht in einem Stück. Schneidet man stur alle zehn Minuten, trifft der Schnitt oft ein Wort. Der Service sucht deshalb in der Nähe der Schnittgrenze die leiseste Stelle und gibt jedem Abschnitt den Text des vorherigen als Prompt mit, damit Schreibweisen und Kontext erhalten bleiben. Anschließend werden die Spuren über ihre Zeitstempel zu einem gemeinsamen Transkript zusammengeführt.

Während eine Konferenz läuft, gibt es zusätzlich ein Live-Transkript. Dafür werden kurze Abschnitte an Sprechpausen abgetrennt und sofort erkannt.

Protokoll mit einem lokalen LLM

Aus dem Transkript erstellt ein lokal betriebenes Sprachmodell ein Protokoll: Titel, Zusammenfassung, wichtige Punkte, Entscheidungen und Aufgaben mit Verantwortlichen und Terminen. Das Modell antwortet über ein JSON-Schema, so lässt sich das Ergebnis ohne Nachbearbeitung strukturiert anzeigen. Welches Modell das Protokoll schreibt, ist konfigurierbar, wir nutzen ein Qwen-Modell mit Thinking. Transkript und Protokoll werden wie die Audiodaten verschlüsselt gespeichert.

Wie man Sprachmodelle selbst betreibt und worauf es dabei ankommt, ordnet der Beitrag Lokale KI betreiben ein.

Suche: Volltext und k-NN

Transkripte und Protokolle landen in OpenSearch. Für die Volltextsuche sorgt ein deutscher Analyzer, Treffer springen im Player direkt an die passende Stelle.

Volltext findet aber nur, was wörtlich gesagt wurde. Wer nach „Preiserhöhung“ sucht, findet ein Gespräch nicht, in dem es hieß, man müsse „die Konditionen anpassen“. Dafür gibt es eine zweite Suche nach Bedeutung.

Das Transkript wird in überlappende Abschnitte von etwa 45 Sekunden geteilt. Ein Embedding-Modell (Qwen3-Embedding) berechnet für jeden Abschnitt und jedes Protokoll einen Vektor, der zusammen mit dem Text im Index liegt. OpenSearch speichert die Vektoren in einem HNSW-Index und findet über k-NN die Abschnitte, die der Suchanfrage inhaltlich am nächsten sind.

Einige Details haben sich als wichtig erwiesen:

  • Das Embedding-Modell ist mit Matryoshka-Verfahren trainiert. Wir nutzen nur die ersten 1024 von 2560 Dimensionen und normalisieren den Vektor neu. Das spart Speicher bei kaum schlechteren Ergebnissen.

  • Ein einzelnes Stichwort ist für die Vektorsuche wenig Kontext. Das LLM formuliert die Anfrage deshalb vorher zu einem Satz um, ohne Thinking, damit es schnell bleibt.

  • Alle Abschnitte sind sich ein wenig ähnlich. Ein fester Schwellwert allein reicht nicht, zusätzlich zählen nur Treffer, die nah am besten Treffer liegen.

  • Volltext- und Vektortreffer werden mit Reciprocal Rank Fusion zu einer Liste zusammengeführt. In der Oberfläche ist markiert, welche Treffer nur sinngemäß passen.

Berechtigungen gelten auch im Index: Jedes Dokument trägt, wer es sehen darf, und die Suche filtert in beiden Verfahren danach.

Vorher informieren

Technisch ist die Aufzeichnung schnell gebaut, rechtlich gilt: Alle Teilnehmer müssen vorher wissen, dass aufgezeichnet wird und was mit den Daten geschieht. Wer das nichtöffentlich gesprochene Wort ohne Einwilligung aufnimmt, macht sich in Deutschland nach § 201 StGB strafbar. Die DSGVO verlangt eine Rechtsgrundlage und eine Information vor der Aufnahme, auch darüber, dass Transkript und Zusammenfassung automatisiert erstellt werden und wie lange alles gespeichert bleibt. Für systematische Aufzeichnung mit automatisierter Auswertung ist in der Regel eine Datenschutz-Folgenabschätzung angebracht. Betrifft es Beschäftigte, kommen Beschäftigtendatenschutz und gegebenenfalls die Mitbestimmung des Betriebsrats hinzu.

Der EU AI Act ist für Transkription und Zusammenfassung nicht der Kern, spielt aber hinein. Betreiber von KI-Systemen müssen für ausreichende KI-Kompetenz der Nutzer sorgen. Emotionserkennung am Arbeitsplatz ist verboten, eine Stimmungsanalyse der Gespräche scheidet damit aus. Wird die Auswertung genutzt, um Leistung oder Verhalten von Beschäftigten zu bewerten, gilt sie als Hochrisiko-Anwendung mit deutlich höheren Anforderungen. Dass die Sprecher bei uns aus getrennten Spuren entstehen und nicht über Stimmerkennung, hält biometrische Fragen außen vor.

Lokaler Betrieb macht vieles davon einfacher, weil sich genau sagen lässt, wo die Daten liegen und wer sie verarbeitet. Er ersetzt aber weder die Information der Teilnehmer noch die Einwilligung.

Wer FreeSWITCH selbst betreiben, Sprachmodelle einsetzen, Kubernetes für solche Workloads aufsetzen oder Suche mit OpenSearch umsetzen möchte, findet dazu passende Schulungen.

Feedback oder Fragen zu einem Artikel - per E-Mail an [email protected] oder über das Kontaktformular. Wir freuen uns auf eine Kontaktaufnahme!

Suche

Los geht's!

Bitte teilen Sie uns mit, wie wir Sie am besten erreichen können.