Aller au contenu

Compatibilité BBB et Jitsi (compat)

Le module compat rend une instance Vuisio compatible avec deux écosystèmes, sur un seul module :

  • BigBlueButton (/bigbluebutton/api/) : une API HTTP compatible BBB pour qu’un LMS comme Moodle ou Greenlight crée et pilote des réunions.
  • Jitsi (/jitsi/{salle}) : une passerelle pour que les applications qui intègrent déjà Jitsi Meet (Moodle mod_jitsi, Rocket.Chat, Mattermost, Element…) pointent sur Vuisio sans toucher à leur code.
Fenêtre de terminal
vuisio module add compat

Disponible en runtime Docker comme en natif. Les deux surfaces sont servies par le même module, sur un port unique.

Chaque surface s’active dès que son secret est renseigné : la surface BBB quand COMPAT_API_SHARED_SECRET est défini, la surface Jitsi quand COMPAT_JITSI_APP_SECRET est défini (ou que les salles ouvertes sont activées). Vous pouvez donc n’utiliser qu’une des deux, ou les deux.

Avec le multi-locataires, chaque client ou intégration peut avoir sa propre clé : un secret BBB par locataire (via vuisio tenant add <id> --bbb-secret <secret>), ou son propre couple app_id/secret Jitsi. Une clé ne voit et ne pilote alors que les réunions qu’elle a créées. Sans multi-locataires configuré, le secret unique décrit ci-dessous vaut pour tout le serveur (locataire primaire).


Dans votre LMS, configurez le connecteur BigBlueButton avec :

  • URL de l’API : https://<votre-domaine>/bigbluebutton/api/

  • Secret partagé : la valeur de COMPAT_API_SHARED_SECRET, obtenue avec :

    Fenêtre de terminal
    vuisio secrets show --reveal COMPAT_API_SHARED_SECRET

Les requêtes sont authentifiées par une somme de contrôle SHA-256, exactement comme avec BigBlueButton.

Chaque appel porte un paramètre checksum, haché à partir de action + paramètres + secret partagé, où :

  • action est le nom de l’endpoint (create, join…) ;
  • paramètres est la query string sans le checksum, dans l’ordre exact envoyé ;
  • le secret partagé est COMPAT_API_SHARED_SECRET.

Le hachage est en SHA-256 (ou SHA-1 selon la longueur fournie). Un checksum absent ou invalide renvoie messageKey=checksumError. C’est exactement le mécanisme BigBlueButton : un LMS ou API Mate le calcule pour vous.

Toutes les réponses sont en XML (HTTP 200, même en cas d’erreur), avec un <returncode>SUCCESS</returncode> ou <returncode>FAILED</returncode>.

GET ou POST /bigbluebutton/api/create

ParamètreRequisDescription
meetingIDouiIdentifiant de la salle. Refusé s’il contient /, ? ou #.
namenonNom affiché. Par défaut, égal à meetingID.
attendeePWnonMot de passe participant (vide par défaut).
moderatorPWnonMot de passe modérateur (vide par défaut).
recordnonAutoriser l’enregistrement. Par défaut, le réglage serveur default_record.
maxParticipantsnonLimite de participants. 0 (défaut) = illimité.
durationnonFin automatique après N minutes. 0 (défaut) = sans limite.
welcomenonMessage d’accueil.
logoutURLnonURL de sortie, ajoutée au lien de connexion.
muteOnStart, lockSettingsDisableMicnonCouper ou verrouiller les micros à l’arrivée.
lockSettingsDisableCamnonVerrouiller les caméras.
webcamsOnlyForModeratornonRéserver les caméras aux modérateurs.
meta_*nonMétadonnées libres (le préfixe meta_ est retiré).

Réponse : <meetingID>, <internalMeetingID>, <createTime>, <createDate>, <attendeePW>, <moderatorPW>, <duration>. Créer deux fois la même salle est idempotent (pas d’erreur idNotUnique).

En POST, le corps peut contenir des présentations pré-téléversées au format BigBlueButton ; les documents sont importés sur le tableau blanc si le module est installé. Les options lockSettings* et guestPolicy sont acceptées et mémorisées, mais seules micro, caméra et « caméras pour modérateurs » sont appliquées par le SFU.

GET /bigbluebutton/api/join

ParamètreRequisDescription
meetingIDouiSalle à rejoindre.
fullNameouiNom affiché du participant.
rolenonMODERATOR ou VIEWER. Prioritaire sur le mot de passe.
passwordnonDétermine le rôle quand role est absent.
userID, avatarURLnonRepris dans le lien de connexion.
createTimenonS’il est fourni, doit correspondre à la salle.
redirectnontrue par défaut. false renvoie l’URL en XML au lieu de rediriger.

join ne contacte pas le SFU : il renvoie une redirection vers le client web (/room/<id>?...). Il n’y a pas de salle d’attente, guestPolicy n’est pas appliqué.

GET /bigbluebutton/api/end. Paramètres : meetingID (requis) et password (vérifié si la salle a un mot de passe modérateur). Termine la salle côté SFU.

GET /bigbluebutton/api/isMeetingRunning. Paramètre : meetingID. Réponse <running>true|false</running>. Une salle inexistante renvoie false.

GET /bigbluebutton/api/getMeetingInfo. Paramètre : meetingID. Renvoie l’état de la salle (compteurs, et un bloc <attendees> avec, par participant, le rôle, l’audio et la vidéo). Les mots de passe sont masqués (***).

GET /bigbluebutton/api/getMeetings. Aucun paramètre. Liste les salles créées via cette API. En multi-locataires, une clé ne voit que ses réunions.

  • sendChatMessage (extension Vuisio) : GET avec meetingID et message, publie un message au nom de « System ».
  • getRecordings, publishRecordings, deleteRecordings, updateRecordings : ne renvoient des données que si le module d’enregistrement est installé, sinon une liste vide (en succès). Les endpoints de modification ne touchent que les métadonnées locales (deleteRecordings retire l’entrée sans supprimer les fichiers).
  • learningDashboard (extension Vuisio) : GET avec meetingID, renvoie en JSON les données de session (présence, temps de parole, webcams, messages), au format du Learning Dashboard BigBlueButton.

Posés via des métadonnées sur create :

  • meta_endCallbackUrl : un GET est envoyé à cette URL quand la salle se termine (?meetingID=<id>).
  • meta_bbb-recording-ready-url : un POST (signed_parameters=<JWT>, signé en HS256 avec le secret partagé) est envoyé quand un enregistrement est prêt.

getDefaultConfigXML, setConfigXML, getRecordingTextTracks, putRecordingTextTrack, insertDocument, setPollXML et signOut ne sont pas implémentées.


Contrairement à BigBlueButton, Jitsi n’a pas d’API REST de gestion de réunions : une conférence est créée implicitement à la première arrivée, et les intégrations reposent sur le script external_api.js (qui embarque une iframe) et un jeton JWT signé avec un secret partagé. Le module fournit exactement cette surface.

Deux réglages suffisent :

  1. Dans votre application, remplacez le domaine Jitsi par celui de votre instance Vuisio (le premier argument de JitsiMeetExternalAPI, ou le domaine de vos liens https://<domaine>/<salle>).
  2. Renseignez les mêmes identifiants que ceux avec lesquels votre application signe déjà ses jetons Jitsi :
    • COMPAT_JITSI_APP_ID : l’identifiant d’application (le iss du JWT, votre ancien JWT_APP_ID) ;
    • COMPAT_JITSI_APP_SECRET : le secret HS256 (votre ancien JWT_APP_SECRET).

Vos jetons existants sont alors acceptés tels quels : rien à re-signer.

Le module sert un external_api.js compatible. Le code d’intégration est identique à Jitsi :

<script src="https://votre-domaine/external_api.js"></script>
<script>
const api = new JitsiMeetExternalAPI("votre-domaine", {
roomName: "MaSalle",
jwt: "<jeton signé par votre application>",
parentNode: document.querySelector("#meet"),
});
api.executeCommand("toggleAudio");
api.addListener("videoConferenceJoined", (e) => console.log(e.roomName));
</script>

Le shim injecte l’iframe, l’authentifie via le module, puis relaie les commandes et les évènements. Le sous-ensemble pris en charge couvre l’usage courant :

  • Commandes : toggleAudio, toggleVideo, toggleShareScreen, hangup, sendChatMessage, setDisplayName.
  • Évènements : videoConferenceJoined, videoConferenceLeft, readyToClose, participantJoined, participantLeft, audioMuteStatusChanged, videoMuteStatusChanged, screenSharingStatusChanged, dominantSpeakerChanged, incomingMessage, outgoingMessage.
  • Accesseurs (promesses) : getNumberOfParticipants, getParticipantsInfo, isAudioMuted, isVideoMuted, getDisplayName, isSharingScreen.

Le module valide des jetons HS256 au format Jitsi. Sont vérifiés la signature, exp/nbf, la présence de sub, l’émetteur iss, l’audience aud et la salle room (* ou correspondance insensible à la casse). L’identité est lue dans context.user :

  • context.user.name : le nom affiché ;
  • context.user.moderator ("true"/"false" ou booléen) : détermine le rôle. Un participant marqué modérateur reçoit un jeton de rôle signé que le SFU vérifie, si bien qu’on ne peut pas se promouvoir en modifiant l’URL ;
  • context.features.recording : autorise l’enregistrement de la salle.

Seul l’algorithme HS256 est accepté (l’en-tête alg est verrouillé : none et RS256 sont refusés).

Par défaut, un jeton valide est requis. Pour reproduire un Jitsi ouvert de type meet.jit.si, activez COMPAT_JITSI_ALLOW_ANONYMOUS : les arrivées sans jeton sont admises comme simples participants, et la première personne dans la salle en devient modératrice.

Les jetons RS256 (offre cloud JaaS de 8x8) et la pile XMPP/Prosody/Jicofo ne sont pas pris en charge : aucune intégration tierce ne les cible.


VariableDéfautRôle
COMPAT_HTTP_ADDR0.0.0.0:8088Adresse d’écoute HTTP (les deux surfaces).
COMPAT_FRONTEND_URLhttp://localhost:3000Base des redirections de connexion.
COMPAT_API_SHARED_SECRET(vide)Secret checksum BBB ; active la surface BBB.
COMPAT_API_DATA_DIR/var/lib/vuisio/compat-apiRépertoire d’état des réunions BBB.
COMPAT_JITSI_APP_ID(vide)Identifiant d’application (JWT iss).
COMPAT_JITSI_APP_SECRET(vide)Secret HS256 ; active la surface Jitsi.
COMPAT_JITSI_ACCEPTED_ISSUERS= app_idÉmetteurs acceptés (liste, * = tous).
COMPAT_JITSI_ACCEPTED_AUDIENCESjitsiAudiences acceptées (liste, * = toutes).
COMPAT_JITSI_ALLOW_ANONYMOUSfalseAutoriser les arrivées sans jeton.
VUISIO_EMBED_ANCESTORS(vide)Origines autorisées à embarquer le client web.

Les secrets et le domaine public sont renseignés à l’installation. Les options BBB (par exemple la politique d’admission des invités) se règlent dans room-defaults.toml sous [modules.compat] ; l’option « salles ouvertes » Jitsi est demandée à l’ajout du module.