Skip to content

[Konzept] Sprach-Plugin für TTS auf Basis von Communication #157

Description

@BechsteinDigital

Worum es geht

Ein eigenständiges Plugin für Sprachsynthese, das auf Communication aufsetzt — wie SipBridge, und aus
demselben Grund: Communication liefert die Mechanik, das Vertical entscheidet, und hier entsteht der
Inhalt.

Ausdrücklich kein Teil von Communication. Ein TTS-Modell ist eine Meinung über Stimme, Sprache,
Lizenz und Modellgröße; die Plattform sollte keine davon erzwingen.

Die Trennung

Wer Was
Communication Bytes im richtigen Takt in einen Anruf schieben (ICallAudioPlayback, eigenes Issue)
Dieses Plugin Aus Text Audio machen
SipBridge / andere Verticals Wissen, dass jetzt „Bitte PIN eingeben" dran ist

Dieses Plugin sendet also nicht selbst in einen Anruf. Täte es das, müsste es die
Taktmaschinerie nachbauen, die Communication für den Konferenz-Downlink schon hat. Es liefert Bytes;
wer sie abspielt, entscheidet der Aufrufer.

Modellwahl: Piper, nicht Kokoro

Kokoro-82M-v1.0-ONNX war der erste Kandidat und fällt für uns aus: kein Deutsch. Der ONNX-Port
führt ausschließlich amerikanische und britische Stimmen; auch das Upstream-Modell kennt Deutsch
nicht (Spanisch, Französisch, Hindi, Italienisch, Portugiesisch, Japanisch, Chinesisch — kein
Deutsch).

Piper passt: MIT-Lizenz, ONNX Runtime, 35 Sprachen
einschließlich Deutsch, Modelle im zweistelligen MB-Bereich und schnell genug für Echtzeit auf CPU.
Deutsche Stimmen unter anderem de_DE-thorsten (in mehreren Qualitätsstufen), de_DE-kerstin,
de_DE-eva_k, de_DE-karlsson, de_DE-ramona, de_DE-pavoque.

Zwei Dinge vor der Festlegung prüfen: Die Stimmen haben eigene Lizenzen, unabhängig von Pipers
MIT — die Thorsten-Stimme ist CC0, andere sind CC-BY und verlangen eine Namensnennung, die dann
irgendwo stehen muss. Und die Aussprache deutscher Fachbegriffe und Eigennamen sollte man an echten
Ansagen hören, bevor man sich bindet.

Modelle gehören nicht ins Repository

Dasselbe Muster wie bei VideoConference und den MediaPipe-Assets: Die Modelldateien werden zur
Bauzeit geholt und liegen in einem gitignorierten Verzeichnis, nicht im Repo. Ein paar hundert MB
Stimmen haben in der Versionsgeschichte nichts verloren, und das Nachladen macht die Stimmenauswahl
zur Deployment-Entscheidung statt zur Compile-Zeit-Festlegung.

Vertragsskizze

public interface ITextToSpeech
{
    Task<SynthesizedAudio> SynthesizeAsync(
        string text,
        SpeechVoice voice,
        AudioFormat format,
        CancellationToken cancellationToken = default);

    IReadOnlyList<SpeechVoice> AvailableVoices { get; }
}

Das Zielformat gehört in den Aufruf, nicht dahinter: Ein Telefon-Leg will G.711 µ-law bei 8 kHz, ein
Browser etwas anderes. Einmal beim Synthetisieren umwandeln ist richtig; bei jedem Abspielen wäre es
Verschwendung.

Zwischenspeichern. Dieselbe Ansage immer wieder zu synthetisieren ist teuer und unnötig — die
Einwahl-Ansagen ändern sich nie. Schlüssel ist (Text, Stimme, Format). Damit wird der
Kaltstart-Aufwand einmalig und die Wiedergabe sofort.

TTS und STT sind nicht dasselbe Paket

TTS ist zustandslos: Text rein, Audio raus. STT und Realtime brauchen einen laufenden Audiostrom aus
einem Anruf und liefern fortlaufend Ergebnisse — andere Lebenszeiten, andere Fehlerfälle, andere
Rückdruck-Fragen. Sie gehören nicht in denselben Vertrag und sollten nicht miteinander ausgeliefert
werden müssen.

Für die Telefon-Einwahl wird ohnehin nur TTS gebraucht; sie läuft über DTMF.

Warum das nichts blockiert

Die Einwahl-Ansagen sind alle statisch. Ein Satz vorproduzierter G.711-Dateien reicht, sobald
Communication sie abspielen kann — SipBridge wird damit fertig, ohne dass dieses Plugin existiert.

Gebraucht wird es erst für dynamische Inhalte: den Raumnamen vorlesen, die Anzahl Wartender ansagen,
eine Fehlermeldung mit Kontext. Das ist die Verbesserung, nicht die Voraussetzung.

Offene Entscheidungen

  • Ein Plugin für TTS und STT mit getrennten Verträgen, oder zwei Plugins?
  • Läuft die Synthese im Host-Prozess (ONNX Runtime als Abhängigkeit des Plugins) oder als Sidecar?
    Im Prozess ist einfacher; ein Sidecar hält native Abhängigkeiten aus dem Host heraus und überlebt
    einen Plugin-Neustart.
  • Wird die Stimme pro Workspace konfiguriert oder pro Aufruf gewählt? Vermutlich beides: eine
    Voreinstellung am Workspace, überschreibbar am Aufruf.

Referenzen

  • Abspiel-Mechanik: separates Communication-Issue
  • Erster Konsument: callora-sipbridge (DialInPrompt)
  • Asset-Muster: callora-videoconference, scripts/fetch-blur-assets.mjs

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions