voice-bridge

Verbindet Gruppen in Simple Voice Chat mit Voice-Channels in TeamSpeak und Discord („Crosstalk“). Jede Seite hört die beiden anderen: Discord und TeamSpeak bekommen je einen gemischten Stream, im Spiel kommt jeder externe Sprecher einzeln an (Lautstärke-Kategorie „Discord/TeamSpeak“).

Modul Läuft als Inhalt
plugin plugins/voice-bridge.jar auf Paper legt die Gruppen an, schickt/spielt Audio, Hinweis beim Beitritt
bridge eigener Dienst (voice-bridge.jar) Discord-Bots (JDA + JDave), TeamSpeak-Clients (ts3j), Mischer (Concentus)
protocol in beiden UDP-Nachrichten Plugin ↔ Bridge (Standard: 127.0.0.1:24470)

third_party/ts3j ist ein Git-Submodul (git submodule update --init), JitPack hat keinen aktuellen Build.

Bauen

./gradlew build
  • Plugin: plugin/build/libs/voice-bridge.jar
  • Bridge: bridge/build/libs/voice-bridge.jar (Fat-Jar), starten mit java --enable-native-access=ALL-UNNAMED -jar voice-bridge.jar config.yml

Verhalten

  • Ein Raum ist aktiv, sobald auf mindestens zwei Seiten jemand ist.
  • Bots verbinden sich nur, wenn der Raum aktiv ist und auf ihrer Seite jemand sitzt; danach bleiben sie lingerSeconds (Standard 15) verbunden.
  • TeamSpeak: eine ServerQuery über SSH (Port 10022) sieht alle Clients und Channels und belegt keinen Slot. Raum-Clients verbinden sich nur bei Bedarf. Fehlende Channels legt die Query unter parentChannel an.
  • Rechte: Servergruppe „Bridge“ (Kopie von „Normal“) plus b_channel_create_permanent, b_channel_create_child, b_channel_create_modify_with_codec_opusvoice, b_client_ignore_antiflood, i_client_talk_power 75. Darin: die Identität des Query-Logins und alle Raum-Identitäten. Kein Serveradmin nötig.
  • Discord: ein Bot pro Raum (ein Bot kann pro Server nur in einem Voice-Channel sein). Fehlende Channels legt der Bot in category an. Einladen mit https://discord.com/oauth2/authorize?client_id=APP_ID&scope=bot&permissions=70255632 (Kanäle sehen, verbinden, sprechen, Kanäle verwalten, Nickname ändern).

Config

Vorlage: bridge/config.example.yml. Die echte config.yml enthält Bot-Tokens und gehört nicht ins Repo.

teamspeakChannel und discordChannel pro Raum dürfen ein Name oder eine ID sein. Einen Namen löst die Bridge beim Start auf (oder legt den Channel an) und schreibt die ID in die config.yml zurück, nur diese Zeile, mit dem alten Namen als Kommentar. Die Datei muss dafür für den Dienst beschreibbar sein.

Stolpersteine

  • glibc ≥ 2.38: Die libdave.so aus JDave (und Discords eigene Builds) brauchen glibc 2.38 und GLIBCXX_3.4.32. Auf Debian 13 kein Problem, auf Ubuntu 22.04 lädt sie nicht („Cannot open library … dave….so“). Lokal hilft ein Debian-13-Loader: glibc und libstdc++ aus den trixie-Paketen entpacken und ld-linux-x86-64.so.2 --library-path <libs>:$JAVA_HOME/lib:$JAVA_HOME/lib/server $JAVA_HOME/bin/java … starten.
  • TeamSpeak 6 (mhsl.eu): verlangt Security-Level 15, Nicknames höchstens 30 Zeichen. Schnelle Reconnects lösen den Flood-Schutz aus (IP-Bann), deshalb Backoff beim Verbinden. Den Bot-Identitäten am besten b_client_ignore_antiflood geben.
  • TeamSpeak-Query-Flood: Die Query sperrt die IP schon nach wenigen schnellen Befehlen (Instanz-Bann, nicht in der Bann-Liste des Servers, läuft nach einigen Minuten ab). Die Bridge hält mindestens 1 s Abstand; sauberer ist es, ihre IP in query_ip_allowlist.txt des TS-Servers einzutragen.
  • UIDs: ts3j rechnet die UID einer Identität anders als der TS6-Server. Eigene Clients erkennt die Bridge deshalb an ihrer Client-ID, nicht an der UID.
  • Discord: Die ersten Pakete nach dem Beitritt schlagen beim Entschlüsseln fehl („Decrypt failed“), bis DAVE die Schlüssel ausgehandelt hat. Das ist normal.
  • Mit -Dvoicebridge.ts3debug=true loggt ts3j das TeamSpeak-Protokoll (Fehlercodes vom Server).
S
Description
No description provided
Readme
276 KiB
0 Stars 5 Watchers 0 Forks
Languages
Java 100%