Tobias Scheible Cyber Security & IT-Forensik Dozent
Skyline - Kommunikation

Mehrere Jitsi Meet Varianten per API

Sollen mehrere Jitsi Meet Varianten mit unterschiedlichen Konfigurationen betrieben werden, ist es nicht notwendig, jeweils eine neue Instanz zu installieren. Über die sehr flexible sowie funktionsreiche API von Jitsi Meet können mehrere Modifikationen mit verschiedenen Funktionen oder einem eingeschränkten Interface für reine Zuhörer leicht realisiert werden.

Sonntag, 15. November 2020
3 Kommentare

06.01.2021 Update: Screenshots ergänzt und kleinere Änderungen.

Die Jitsi Meet API ist sehr umfangreich und bietet viele Möglichkeiten. Es ist zum Beispiel möglich, eine Hauptinstallation von Jitsi Meet zu betreiben und mit der API angepasste Unterinstallationen mit unterschiedlichen Funktionen zu realisieren. Die Unterinstanzen können dann zum Beispiel angepasste Logos oder Fußzeilen mit den Links zum Impressum bekommen. Somit kann man sich den Betrieb von mehreren Instanzen sparen und die Ressourcen auf einer leistungsfähigen Jitsi Meet Instanz konzentrieren.

Zur Nutzung der Jitsi Meet API muss als Erstes ein DIV-Element mit einer eindeutigen ID deklariert werden:

<div id="jitsi-meet"></div>

Anschließend wird die JavaScript-Datei external_api.js eingebunden. Sie liegt im Hauptverzeichnis jeder Jitsi Meet Installation.

<script src="https://meet.jit.si/external_api.js"></script>

Im eigentlichen JavaScript-Code wird ein Objekt mit verschiedenen Parametern definiert. Als Werte werden mindestens roomName für den Namen des Raumes und parentNode für das zu verwendende DIV-Element benötigt. Bei diesem Beispiel wird zusätzlich noch die Höhe und Breite mit definiert.

const options = {
   roomName: "TestRoomAPIExample",
   parentNode: document.querySelector("#jitsi-meet"),
   height: 600,
   width: 800
};

Als letzter Schritt erfolgt der Aufruf der Funktion JitsiMeetExternalAPI mit zwei Parametern, dem Domainnamen und die Optionen.

const api = new JitsiMeetExternalAPI("meet.jit.si", options);

Hier der komplette Code des Jitsi Meet API-Minimalbeispiels:

<div id="jitsi-meet"></div>
<script src="https://meet.jit.si/external_api.js"></script>
<script>
   const options = {
      roomName: "TestRoomAPIExample",
      parentNode: document.querySelector("#jitsi-meet"),
      width: 800,
      height: 600
   };
   const api = new JitsiMeetExternalAPI("meet.jit.si", options);
</script>

Jitsi Meet API-Beispiele

Das Besondere und Mächtige an der Jitsi Meet API ist, dass die in der config.js (Github) und interface_config.js (Github) gesetzten Optionen mit den Methoden configOverwrite bzw. interfaceConfigOverwrite überschrieben werden können. Welche Parameter überschrieben werden können, kann in der Datei configWhitelist.js (Github) definiert werden.

Hintergrundfarbe ändern

Als erstes Beispiel wird die Anpassung der Hintergrundfarbe gezeigt. Dazu wird der Option interfaceConfigOverwrite der Wert DEFAULT_BACKGROUND: „#ff0000“ übergeben und der Hintergrund erstrahlt in einem hellen Rot.

const options = {
    roomName: "TestRoomAPIExample",
    parentNode: document.querySelector("#jitsi-meet"),
    interfaceConfigOverwrite: {DEFAULT_BACKGROUND: "#ff0000"}
};
const api = new JitsiMeetExternalAPI("meet.jit.si", options);

Demo starten
Jitsi Meet Hintergrundfarbe
Angepasste Hintergrundfarbe mit der Jitsi Meet API
Jitsi Meet Hintergrundfarbe Angepasste Hintergrundfarbe mit der Jitsi Meet API

Auflösung anpassen

Im nächsten Beispiel wird die maximale Auflösung von Jitsi Meet auf FullHD (1920×1080) erhöht. In der Konfiguration von Jitsi Meet wird die Höhe der Auflösung angegeben. Die Breite ergibt sich aus dem Seitenverhältnis der Webcam, meist 16:9 oder 4:3. Die Modifikation geschieht mit der Option configOverwrite und den Werten resolution und constraints, wobei letzterer verschachtelt wird.

const options = {
    roomName: "TestRoomAPIExample",
    parentNode: document.querySelector("#jitsi-meet"),
    configOverwrite: {resolution: 1080, constraints: {video: {height: {ideal: 1080,max: 1080,min: 1080}}}}
};
const api = new JitsiMeetExternalAPI("meet.jit.si", options);

Demo starten
Jitsi Meet Auflösung
Angepasste Auflösung mit der Jitsi Meet API
Jitsi Meet Auflösung Angepasste Auflösung mit der Jitsi Meet API

Eingeschränktes Interface

Im letzten Beispiel werden möglichst viele Elemente deaktiviert, damit die Teilnehmer als reine Zuhörer ein eingeschränktes Interface haben. Der Trick dabei ist, dass der Moderator den Raum über den normalen Link (hier: https://meet.jit.si/TestRoomAPIExample) betritt und alle Funktionen hat. Die Zuhörer bekommen dann einen anderen Link zu einer HTML-Datei mit der Konfiguration. Leider lassen sich nicht alle Elemente deaktivieren. So wird der Zuhörer immer noch nach den Zugriffsrechten für das Mikrofon gefragt und die Vorschaubilder aller Teilnehmer werden angezeigt.

const options = {
    roomName: "TestRoomAPIExample",
    parentNode: document.querySelector("#jitsi-meet"),
    configOverwrite: {startWithAudioMuted: true, startWithVideoMuted: true, enableNoAudioDetection: false, requireDisplayName: false, enableWelcomePage: false},
    interfaceConfigOverwrite: {TOOLBAR_BUTTONS: [], DISABLE_JOIN_LEAVE_NOTIFICATIONS: true, HIDE_INVITE_MORE_HEADER: true, FILM_STRIP_MAX_HEIGHT: 0, VIDEO_QUALITY_LABEL_DISABLED: true, RECENT_LIST_ENABLED: false} 
};
const api = new JitsiMeetExternalAPI("meet.jit.si", options);

Demo starten
Jitsi Meet Interface
Eingeschränktes Interface mit der Jitsi Meet API
Jitsi Meet Interface Eingeschränktes Interface mit der Jitsi Meet API

Externe Steuerung

Neben den Eigenschaften bei der Initialisierung eines Jitsi Meet Raumes können mit der API auch viele Funktionen während eines Meetings gesteuert werden. Eine Übersicht der Funktionen gibt es auf der offiziellen API-Seite. Das nachfolgende Beispiel zeigt einen extra Button, der es dem Moderator erlaubt, alle anderen Teilnehmer stumm zu schalten.

<div id="jitsi-meet"></div>
<script src="https://meet.jit.si/external_api.js"></script>
<script>
   const options = {
      roomName: "TestRoomAPIExample",
      parentNode: document.querySelector("#jitsi-meet")
   };
   const api = new JitsiMeetExternalAPI("meet.jit.si", options);
</script>
<button onclick="api.executeCommand(\'muteEveryone\')">mute</button>

Demo starten
Jitsi Meet Buttons
Externe Steuerung mit der Jitsi Meet API
Jitsi Meet Buttons Externe Steuerung mit der Jitsi Meet API

Anpassungen per CSS

Im obigen Beispiel wurden die Parameter width und height definiert, um die Größe des Jitsi Meet Elements festzulegen. Dies ist allerdings sehr unpraktisch und unflexibel. Eine anpassungsfähige Lösung bietet hier CSS.

Flexible Größe

Im ersten Beispiel wird das Element in der Größe 16:9 mit einer flexiblen Breite ausgerichtet. Um das eigentliche DIV-Element wird ein weiteres eingefügt, das als Wrapper fungiert.

<div id="wrapper">
    <div id="jitsi-meet"></div>
</div>

Mit CSS wird eine Breite von 100% für das Wrapper Element definiert und ein Innenabstand von oben mit 56.25% für das 16:9 Formatverhältnis (100/16*9), angegeben. Das eigentliche DIV-Element wird absolut positioniert und alle vier Parameter für die Ausrichtung auf null gesetzt, wodurch es die volle Größe des Elternelements einnimmt.

#wrapper{
    width: 100%; 
    padding-top: 56.25%;  
    position: relative;
}
#jitsi-meet{
    position: absolute; 
    top: 0;  
    left: 0; 
    bottom: 0; 
    right: 0;"
}

Beim eigentlichen Jitsi Meet API-Aufruf in JavaScript können die Parameter width und height weggelassen werden.

<script src="https://meet.jit.si/external_api.js"></script>
<script>
   const domain = "meet.jit.si";
   const options = {
      roomName: "TestRoomAPIExample",
      parentNode: document.querySelector("#jitsi-meet")
   };
   const api = new JitsiMeetExternalAPI(domain, options);
</script>

Vollbild

Wird Jitsi Meet per API auf einer Seite ohne weitere Elemente eingebunden und soll die Webkonferenz im Vollbild angezeigt werden, funktioniert dies ähnlich. Hier wird nur das äußere DIV-Element durch den das Element für den Body-Tag ersetzt.

<body>
    <div id="jitsi-meet"></div>
</body>

Bei den CSS-Definitionen müssen die Elemente html und body auf eine Höhe von 100% gesetzt werden.

html, body{
    height: 100%; 
}
body{
    width: 100%; 
    position: relative;
}
#jitsi-meet{
    position: absolute; 
    top: 0;  
    left: 0; 
    bottom: 0; 
    right: 0;"
}

Und damit kann Jitsi Meet mit der API im Vollbildmodus genutzt werden.

Schutz vor Missbrauch

Die hier im Artikel gezeigten Beispiele verdeutlichen, wie einfach mit der Jitsi Meet API eine eigene Variante erstellt werden kann. Da die JavaScript-Datei lib-jitsi-meet.min.js bei allen Installationen vorhanden ist, lässt sich damit die API von prinzipiell allen Jitsi Meet Instanzen nutzen. Früher war es sogar möglich, eine fremde Installation unter eigenem Logo zu betreiben. Dies wurde mit einem Update geändert.

Gegenmaßnahme

Die Einbindung erfolgt per iFrame, wodurch diese mit einem HTTP-Header-Eintrag blockiert werden kann. Mit dem x-frame-options Befehl wird der Webbrowser angewiesen, einen Aufruf einer Website in einem Frame zu blockieren. Dazu muss der folgende Eintrag am Ende des Blocks server für die HTTPS-Verbindung (typischerweise der Zweite) hinzugefügt werden:

// /etc/nginx/sites-available/meet.example.com.conf
server{
  …
  add_header X-Frame-Options "DENY";
}

Wird dieser Header-Eintrag gesetzt, ist keine Teilnahme an einer Konferenz mit der Jitsi Meet Electron App mehr möglich.

Der HTTP-Header Eintrag verhindert komplett die Nutzung der Jitsi Meet API. Soll selbst die API genutzt werden, kann in der Datei configWhitelist.js definiert werden, welche Parameter überschrieben werden können.

Hauptinstanz

Zusätzlich sollte immer im Hinterkopf behalten werden, dass ein Benutzer mit entsprechendem Know-how die Original-URL der Jitsi Meet Instanz und den Raum über den Seitenquelltext herausfinden kann. Damit ist es möglich, über die normale URL den Raum aufzurufen und alle Funktionen zu nutzen. Zwar kann der JavaScript-Code mittels Obfuscation unleserlich gestaltet werden, allerdings ist das nur eine geringe Hürde. Durch die integrierten Web-Entwickler Tools können die Aufrufe der URL bequem eingesehen werden.

Jitsi Meet Artikelserie

Dieser Blogbeitrag ist Teil der Artikelserie „Videokonferenzen mit Jitsi Meet“, die sich mit dem Open-Source-Webkonferenzsystem Jitsi für Video-, Web- und Telefonkonferenzen beschäftigt. Die Artikelserie zu Jitsi Meet umfasst die folgenden Themen:


Jitsi Meet Artikel für Anwender


Jitsi Meet Artikel für Administratoren

Changelog

06.01.2021Screenshots ergänzt und kleinere Änderungen.

Über Tobias Scheible

Tobias Scheible

Hallo, mein Name ist Tobias Scheible. Ich bin begeisterter Informatiker und Sicherheitsforscher mit den Schwerpunkten Cyber Security und IT-Forensik. Mein Wissen teile ich gerne anhand von Fachartikeln hier in meinem Blog und in meinem Fachbuch. Als Referent halte ich Vorträge und Workshops für Verbände und Unternehmen u. a. auch offene Veranstaltungen für den VDI und die IHK.

Kommentare

Peter am 21. Januar 2021 um 12:26 Uhr

Hallo,

vorerst wollte ich mich bedanken, für die wirklich tollen Seiten zum Thema Jitsi. Ich konnte viele Dinge dadurch lernen und umdenken beim Thema Datenschutz.
Danke dafür.

Ich habe jedoch auch eine Frage, die ich mir nicht beantworten konnte, obwohl ich die API Dokumente gelesen habe.
Die Wahrscheinlichkeit ist aber sehr hoch, dass ich es einfach überlese oder nicht verstanden habe.

Wenn ich nun einen eigenen Jitsi Server hätte und als Beispiel nehme ich deine URL
https://meet.scheible.it/
Kann ich dann mehrere Einstiegspunkte / Hauptseiten mit anderem Logo, Fußzeile und Layout haben?
Also z.B. https://meet.scheible.it/Team1, https://meet.scheible.it/Team2.

Ich möchte dann aber nicht, wie hier auf der API Seite, direkt einen Raum beitreten, sondern jeder Link soll eine eigene Einstiegsseite mit „Start Meeting“ wie auf https://meet.scheible.it/ haben.
Also eine Trennung per URL oder subdomain?
Für einen Hinweis wäre ich sehr dankbar.
Viele Grüße
Peter

Tobias am 21. Januar 2021 um 18:59 Uhr

Hallo Peter,
das ist mit der API möglich. Dazu muss ein wenig programmiert werden. Einfach ein Eingabefeld mit einem Button. nach dem Klick auf den Button wird der Name ausgelesen und als Wert für roomName gesetzt.
Grüße Tobias

Alvaro am 14. Juli 2021 um 18:52 Uhr

Hallo Tobias,
ich habe gerade eine Lösung für Webinare erstellt, die alle Buttons, bis auf den Chat für Teilnehmer ausblendet. Was ich leider nicht hinbekomme ist, dass sich ein zweiter Moderator mit anmeldet, die Teilnehmer dann aber auch nur die zwei Moderatoren sehen. Leider erscheinen dann alle Teilnehmer, sobald sich eine zweite Person über den Server direkt einwählt. Hast Du eine Idee, wie man so etwas lösen könnte?
Viele Grüße und danke für diese tollen Beispiele!!! Das hat mir sehr geholfen.

Schreibe einen Kommentar!

Hilfe zum Kommentieren und Hiweise

Um kommentieren zu können, geben sie bitte mindestens ihren Namen und ihre E-Mail-Adresse an. Bitte nutzen Sie die Kommentarfunktion nicht dazu, andere zu beleidigen oder Spam zu verbreiten. Trolle und Spammer sind hier unerwünscht! Unangemessene Kommentare, die zum Beispiel gegen geltendes Recht verstoßen, eine Gefährdung anderer Besucher darstellen oder keinen sinvollen Inhalt beinhalten, werden gelöscht oder angepasst.

Name: Ihr Name, der oberhalb des Kommentars steht, gerne auch Ihren echten Namen, das erleichtert die Kommunikation für alle. Sollte ein Spam-Keyword als Name verwendet werden, kann dieses entfernt oder korrigiert werden.

E-Mail: Ihre E-Mail Adresse dient zur Identifizierung weiterer Kommentare und damit ich direkt Kontakt aufnehmen kann. Die E-Mail Adresse wird natürlich nicht veröffentlicht und nicht weitergegeben.

Website: Hier können Sie ihren eigenen Blog bzw. ihre eigene Website eintragen, dadurch wird Ihr Name und Ihr Avatar-Bild verlinkt. Werden rein kommerzielle Angebote offensichtlich beworben, setze ich den Link auf nofollow und unangemessene werden einfach entfernt.

Erlaubte HTML-Tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <hr> <big> <small> <sub> <sup> <u>

Ihre E-Mailadresse wird nicht veröffentlicht. Mit dem Absenden anerkennen Sie die Datenschutzhinweis des Blogs.