Jitsi Videokonferenzen funktionieren bei geeigneten Einstellungen mit über 100 Teilnehmern. Voraussetzung dafür ist, dass der erste Teilnehmer (der Veranstalter) dafür sorgt, dass der erste Teilnehmer (Moderator des Raumes) in den Settings „Everyone start muted“, „Everyone start hidden“ und „Everyone follows me“ anwählt. Dieses Szenario ist mit über 90 Teilnehmern erfolgreich getestet worden. Dann senden die Zuschauer nicht, können ihre Kamera und Mikrofon aber selber einschalten. Wenn das der Reihe nach getan wird, kann sehr einfach ermittelt werden, wie viele gleichzeitige Teilnehmer funktionieren, da der Teilnehmer mit der geringsten Bandbreite das Nadelöhr darstellt. Für reine Vorlesungsszenarien reicht das aber häufig schon aus.
Jitsi bietet aber auch die Möglichkeit externe Streaming Dienste anzubinden wie z.B, youtube oder einen eigenen nginx-Streamingserver. Wie das technisch realisiert werden kann, wird hier kurz beschrieben. Mir fehlt leider die Zeit das detailliert zu tun, da ich nicht mehr lange für die Uni Duisburg-Essen (UDE) arbeiten werde.
Die Komponente in Jitsi, die Aufzeichnungen und Stream ermöglicht heißt Jibri. https://github.com/jitsi/jibri
Bitte beachten, wenn mehrere Streams oder Aufzeichnung zur gleichen Zeit erfolgen sollen, benötigt man eine ganze Farm von Jibri-Maschinen, die mit einem unterschiedlichen „Nickname“ (siehe unten) konfiguriert werden müssen. Best Practice: Einen jibri konfigurieren und dann klonen. („Nickname“ anpassen nicht vergessen). Das schreit eigentlich nach dynamischen Instanzen, die per Docker oder ähnlich on the fly erzeugt werden können (hier nicht realisiert, nur als Idee angerissen).
Die Installation von Jibri funktioniert, anders als in der Anleitung angegeben, auch unter Ubuntu 18.4LTS (und sehr wahrscheinlich auch 20.4LTS). Wichtig ist aber, dass unbedingt Java8 konfiguriert wird:
$ sudo update-alternatives –config java
Achtung: Anders als in der Anleitung heißen die Jitsi-internen Virtual Hosts für die beiden Control-Kanäle (hier im Beispiel heißt der Jitsi-Server jitsi.zim.uni-due.de, dass muss individuell angepasst werden):
VirtualHost „auth.jitsi.zim.uni-due.de“ (in /etc/prosody/conf.avail )
und
Component „internal.auth.jitsi.zim.uni-due.de“ „muc“
Diese Namen müssen sich in der jibji config.json wiederspiegeln.
Unbedingt sind dann auch die Passwörter für die richtigen „virtuellen“ Domänen (mit Domain meint Jitsi ein eigenes virtuelles Subdomain-Konzept, dass gar nichts mit echten Subdomains zu tun hat) zu setzen:
$ prosodyctl register jibri auth.jitsi.zim.uni-due.de *********
$ prosodyctl register recorder recorder.jitsi.zim.uni-due.de ********
(Mit den vergebenen Passwörtern im Config-File.)
Damit alle Komponenten zusammenspielen, muss auch die Jicofo-Konfiguration angepasst werden:
Man editiere dazu /etc/jitsi/jicofo/sip-communicator.properties, um für die MUC (Multi User Conference, Jitsi basiert ja auf Jabber) die Jitsi-Stream-Brauerei (ein Bier für den Admin 😉 , also die Jibri-Worker bekannt zu machen. Das muss mit dem Eintrag in der jibri’s config.json korrespondieren. Jicofo muss nach der Änderung neu gestartet werden.
org.jitsi.jicofo.jibri.BREWERY=JibriBrewery@internal.auth.yourdomain.com
muss bei unserem Beispiel
org.jitsi.jicofo.jibri.BREWERY=JibriBrewery@internal.auth.jitsi.zim.uni-due.de
sein!
Dann müssen noch in /usr/share/jitsi-meet/interface_config.js
die TOOLBAR_BUTTONS für ‘livestreaming’ aktiviert werden.
Damit kann man dann z.B. schon zu youtube streamen, wenn man dort einen Streaming Account hat. Ich denke auch Wowza würde mit dem /etc/hosts Hack gehen, ich hatte aber keine Zeit mehr das an der UDE auszuprobieren.
Damit die Jibri-Instanzen (Farm) nicht zu youtube sondern auf einen eigenen Server streamen, einfach in /etc/hosts für youtube.com die IP des Streamingservers einsetzen. D.h. die Rechner der Jibri-Farm halten den eigenen Streamingserver für youtube. Das hat den Vorteil, dass nichts im Jitsi-Quellcode geändert werden muss.
Im Beispiel an der UDE heißt der Streamingserver livestream.zim.uni-due.de .
Die JIBRI Farm
Jeweils in /etc/jitsi/jibri/config.json die Nicknamen ändern.
„nickname“: „jibri-nickname2“
siehe: https://github.com/jitsi/jibri/issues/187 (ganz unten)
dann
$ sudo systemctl restart jibri
In den Logfiles sieht man dann, ob sich die Jibri-Instanzen ordentlich am jicofo anmelden.
Ein eigener Open-Source Streaming-Server
Der Streaming-Server, hier ganz in Open Source ist ein nginx mit selbst kompilierten Modul realisiert worden:
Prinzipiell bin ich nach dieser Anleitung vorgegangen
https://obsproject.com/forum/resources/how-to-set-up-your-own-private-rtmp-server-using-nginx.50/
Zum Bauen des nginx:
$ sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev
$ wget http://nginx.org/download/nginx-1.15.1.tar.gz
Das RTMP-Modul:
$ wget https://github.com/sergey-dryabzhinsky/nginx-rtmp-module/archive/dev.zip
$ tar -zxvf nginx-1.15.1.tar.gz
$ unzip dev.zip
$ cd nginx-1.15.1
Build nginx:
$ ./configure –with-http_ssl_module –add-module=../nginx-rtmp-module-dev
$ make
$ sudo make install
Als Ergänzung habe ich auch ein LDAP-Modul in den nginx einkompiliert:
hiermit:
https://github.com/kvspb/nginx-auth-ldap/blob/master/example.conf
mit
$ ./configure –with-http_ssl_module –add-module=../nginx-rtmp-module-dev –add-module=../nginx_ldap_module/nginx-auth-ldap-master
$ make
$ sudo make install
Restart nginx:
$ sudo /usr/local/nginx/sbin/nginx -s stop
$ sudo /usr/local/nginx/sbin/nginx
Der nginx ist selbstkompiliert und lebt nach install unter /usr/local/nginx.
Gestartet wird er bei einem Reboot über einen cronjob:
@reboot root /usr/local/nginx/sbin/nginx
@reboot root /home/zim026/worker.sh 2>/dev/null (für die Playlist, siehe unten)
So wie er nun ist, kann man den Streaming-Server mit OBS-Studio oder Videolan per RTMP füttern und sich den Stream in einem vlc medial player anschauen.
Per OBS-Studio geht das so:
Ein Profil erzeugen mit:
Streaming Service: Custom
Server: rtmp://<your server ip>/live
Play Path/Stream Key: test
Und dann mit VLC (Videolan):
rtmp://<your server ip>/live/test
Das war der einfache Teil ;-).
Ich will aber mehr und den Stream im Browser per Javascript als HLS anschauen. Dazu habe ich folgendes getan:
Der Job /home/zim026/worker.sh (landet in der Crotab) erzeugt eine dynamische Übersichtsseite:
#!/bin/bash #erst mal dauernd while : do cd /tmp/hls #alias proj="cd /tmp/hls" #jhome () { # cd /tmp/hls #touch test.m3u8 #touch test2.m3u8 echo > /usr/local/nginx/html/playlist_cont.html j=0 x=X for i in *.m3u8 ; do if [ "${i:0:1}" != "X" ] then echo "<a href='https://livestream.zim.uni-due.de/stream5.html?s=$i'>Stream: [$i] <base target="_parent"></a><br><br>" >> /usr/local/nginx/html/playlist_cont.html fi j=$(( $j + 1 )) done OUTPUT=`cat /usr/local/nginx/html/playlist_cont.html` if echo "$OUTPUT" | grep -q "*"; then echo "<p>Kein öffentlicher Livestream verfübar.</p>" >/usr/local/nginx/html/playlist_cont.html j=$(( $j - 1 )) fi echo "<p>" >>/usr/local/nginx/html/playlist_cont.html echo $j >> /usr/local/nginx/html/playlist_cont.html echo ' aktive Streams.' >> /usr/local/nginx/html/playlist_cont.html #cat /usr/local/nginx/html/playlist_head.html /usr/local/nginx/html/playlist.txt /usr/local/nginx/html/playlist_footer.html > /usr/local/nginx/html/playlist.html #} # fuer das cd sleep 5 done
Optional können auch verborgene Streams erzeugt werden, denen im Namen ein „X“ vorangestellt wird. Diese tauchen dann nicht auf der Playlist auf, sind aber, wie unten in der Anleitung beschreienen, aufrufbar.
Das passende stream5.html HTML dazu, dass die hls-Videos mit Hilfe des videojs-contrib-hls.js javascript-Library abspielt:
Siehe auch (es klappt bei mir mit Version 7):
https://videojs.com/getting-started/
Da es Umbruchprobleme im Blog gibt, hier die Datei stream5_html.txt auch zum Herunterladen.
<!DOCTYPE html> <html> <head> <meta charset=utf-8 /> <title>ZIM Livestream</title> <!-- Uses the latest versions of video.js and videojs-contrib-hls. To use specific versions, please change the URLs to the form: <link href="video-js.css" rel="stylesheet"> <script src="video.js"></script> <script src="videojs-contrib-hls.js"></script> --> <link href="videojs7/video-js.css" rel="stylesheet"> <script src="videojs7/video.min.js"></script> </head> <body> <!-- onload="myFunction()"> --> <img src="UDE-logo-claim.svg" height="100"><img src="zim.jpg" height="100"> <h1>Livestream - Play Button klicken fC<r Start</h1> <video id="myvideo1" controls preload="auto" width="640" height="360" data-setup='{}'> <!-- <source src="https://livestream.zim.uni-due.de/hls/novideo.m3u8" type="applicat --> </video> <br> <a href="playlist.html">zurC<ck zur Live-Stream Auswahl</a> <script> window.onload = myFunction(); function myFunction(){ function getUrlParam(parameter, defaultvalue){ var urlparameter = defaultvalue; if(window.location.href.indexOf(parameter) > -1){ urlparameter = getUrlVars()[parameter]; } return urlparameter; } function getUrlVars() { var vars = {}; var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key, vars[key] = value; }); return vars; } var mystream = getUrlParam('s','Empty'); var video = document.getElementById('myvideo1'); /*alert(video);*/ var source = document.createElement('source'); var streambase = 'https://livestream.zim.uni-due.de/hls/'; var streamurl = streambase.concat(mystream); source.setAttribute('src', streamurl); source.setAttribute('type', "application/x-mpegURL"); video.appendChild(source); /*let insertedNode = myvideo.insertBefore(insertedNode, source);*/ /* video.play(); */ } </script> </body> </html>
Der Datei wird der Stream-URL durch die Playlist per Parameter übergeben und es wird ein bisschen mit Javascript gezaubert. Die Geschichte mit dem Parameter und der Playlist stammt von mir. Das kann man sicher mit einem beliebigen Framework viel eleganter machen, ist wollte allerdings eine rasche Lösung, da ich erwartet hatte, dass so etwas in Corona-Zeiten an der UDE benötigt wird.
Dieses ist meine fertige nginx.conf. Wer auf LDAP verzichten will, lässt die entsprechenden Konfigurationseintrage füe LDAP und das Modul einfach weg. Das Streaming geht auch ganz ohne LDAP. Das war nur ein Feature für die Uni Duisburg-Essen, um auch hochschulöffentliche Streams zu realisieren, die erst nach Anmeldung angeschaut werden können:
Da es Umbruchprobleme im Blog gibt, hier die Datei nginx_conf.txt auch zum Herunterladen.
#user nobody; worker_processes 10; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 2048; } http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; #LDAP ldap_server test1 { url ldaps://ldap2.uni-duisburg-essen.de/ou=people,dc=uni-duisburg-essen,dc=de?uid?sub?(objectClass=inetOrgPerson); binddn "cn=*******,ou=admin,dc=uni-duisburg-essen,dc=de"; binddn_passwd "********"; #group_attribute uniquemember; group_attribute_is_dn on; require valid_user; } #bis hier LDAP server { #listen 80; listen 443 ssl; #ssl on; ## livestream.zim.uni-due.de-key.pem livestream_cert.pem root@stream:/usr/local/nginx/certs ssl_certificate /usr/local/nginx/certs/livestream_cert.pem; ssl_certificate_key /usr/local/nginx/certs/livestream.zim.uni-due.de-key.pem; server_name livestream.zim.uni-due.de; # server_name localhost; #LDAP # auth_ldap "Anmeldung mit UDE-Unikennung/Passwort"; # auth_ldap_servers test1; #LDAP bis hier #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} # Andreas location /hls/ { root /tmp; add_header Cache-Control no-cache; } # Andreas location ~ /hls/U { root /tmp; add_header Cache-Control no-cache; auth_ldap "Anmeldung mit UDE-Unikennung/Passwort"; auth_ldap_servers test1; } } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} } rtmp { server { listen 1935; chunk_size 4096; application live2 { live on; record off; #Andreas meta copy; wait_key on; wait_video on; idle_streams off; hls on; hls_path /tmp/hls; } } }
Aus der Nutzeranleitung, die ich für die UDE erstellt habe:
Livestreams bzw. Webcasts
Wählen Sie zur Nutzung von Livestreams bzw. Webcasts auf dem Server
jitsi.zim.uni-due.de (nicht auf jitsi.uni-due.de) die Funktion „start live stream“ im Menue rechts unten (drei Punkte übereinander). Vergeben Sie dann im Dialog einen aussagekräftigen Namen für den Stream (ohne Leerzeichen). Der Stream wird nicht zu youtube gesendet, wie es im GUI angezeigt wird, sondern zum Server https://livestream.zim.uni-due.de . Wenn Sie ein großes „X“ dem Stream-Namen voranstellen, wird dieser nicht in der Streamübersicht angezeigt. Ihre Studierenden können den Stream dann unter der URL
https://livestream.zim.uni-due.de/stream5.html?s=X<ihrstreamname>.m3u8
betrachten. Sie müssen Ihren Studierenden den URL dann per Mail oder in Moodle mitteilen. Bitte keine Leer- oder Sonderzeichen im Stream-Namen verwenden.
Wenn Sie dem Stream-Namen mit einem großen „U“ beginnen, z.B. „Utest“, können nur NutzerInnnen der UDE erst nach Eingabe der Unikennung und dem Passwort den Stream ansehen.
Stoppen können Sie den Livetream ebenfalls über das Menue.
Der Livestream kann dann über die Seite livestream.zim.uni-due.de von vielen hundert Teilnehmern angeschaut werden,
Den Streamingserver livestream.zim.uni-due.de können Sie beispielsweise aber auch mit Hilfe von OBS-Studio produzierten Livestreams aus dem Uninetz auf den Port 1935 beschicken. Die beiden Optionen mit dem vorangestellten „X“ bzw. „U“ gelten dann ebenfalls.
Ich hoffe diese Zusammenstellung hilft dem einen oder anderen Admin weiter. Insbesondere für große Veranstaltungen kann das sehr hilfreich sein.