https://d226lax1qjow5r.cloudfront.net/blog/blogposts/build-a-breakout-room-application-in-javascript-with-vonage-video-api/breakoutroom.jpg

Erstellen einer Breakout-Room-Applikation in JavaScript mit der Vonage Video API

Zuletzt aktualisiert am May 24, 2022

Lesedauer: 5 Minuten

Dieser Artikel wurde geschrieben in Zusammenarbeit mit Yinping Ge

Der "Breakout Room" ist eine Funktion, die von vielen Kunden, insbesondere im Bildungsbereich, gewünscht wird. Sie ermöglicht häufig die "Aufteilung des Hauptbesprechungsraums in separate Räume", die "Aufteilung der Teilnehmer in diese Nebenräume" und die "Möglichkeit für die Teilnehmer, Nachrichten an den Gastgeber zu senden, unabhängig davon, in welchem Raum sie sich gerade befinden", usw.

Mit Vonage Video APIgibt es mehr als eine Möglichkeit, eine solche Breakout Room-Funktion für Ihre Anwendung zu implementieren.

Eine Möglichkeit ist die Erstellung einer großen Video-Sitzung mit einer Logik, die steuert, welche Streams für jeden Nutzer abonniert werden sollen. Eine andere Möglichkeit besteht darin, "Breakout-Räume als separate Sitzungen zu implementieren" und dann "die Teilnehmer mit diesen verschiedenen Sitzungen zu verbinden, die für jeden Breakout-Raum erstellt wurden".

Dieses Tutorial erklärt, wie man die getrennte Sitzungen um die Funktion "Breakout Room" in unsere Demo-Anwendung einzubauen, die die Signalisierungs-API verwendet, um die Verwaltung von Breakout Rooms zu implementieren und das Publisher-Objekt beim Hin- und Herwechseln zwischen Räumen wiederverwendet

Ich hoffe, die folgenden Diagramme können Ihnen einen ersten Überblick verschaffen. Zu Beginn verbinden sich alle Teilnehmer mit der Sitzung im Hauptraum:

Graph showing all participants connect to the main-room’s session

Nachdem der Gastgeber auf die Schaltfläche zum Erstellen von Nebenräumen geklickt hat, ruft der Anwendungsserver die Vonage Video API auf, um eine Sitzung für jeden Nebenraum zu erstellen, und gibt diese Sitzungs-IDs an jeden Teilnehmer zurück.

Graph showing application connects participants to breakout rooms

Anschließend verbindet die Anwendung die Teilnehmer mit den Sitzungen dieser Nebenräume, indem sie die Teilnehmer einen Raum auswählen lässt, dem sie beitreten möchten, oder indem sie die Teilnehmer automatisch in verschiedene Räume aufteilt, je nachdem, welche Option der Gastgeber bei der Erstellung der Nebenräume ausgewählt hat (der Gastgeber kann zwischen "automatisch zuweisen" und "Teilnehmer einen Raum auswählen lassen" wählen).

Voraussetzungen

Ein Vonage Video API Account. Klicken Sie auf . Anmelden um eines zu erstellen, wenn Sie noch keines haben. ReactJS Version >= 16.8 Node.js Version >= 16.13 PostgreSQL 14 als Datenbank, Sie können einen beliebigen Speicher wählen

Sie sollten in der Lage sein, alle Abhängigkeiten in der GitHub-Repositorium und wir empfehlen Ihnen, immer die neueste Version des Vonage SDK zu verwenden. Die hier aufgeführten Versionen wurden verwendet, als wir an dieser Demo-App gearbeitet haben.

Server- und Datenbankdesign der Anwendung

Der Anwendungsserver erstellt Räume, erstellt Sitzungen, erzeugt Token, verwaltet die Räume und Teilnehmer und sendet Signalisierungsnachrichten an Räume.

Der Anwendungsserver fungiert als "Relais", indem er die Signalisierungs-REST-API für die Weiterleitung von Nachrichten zwischen verschiedenen Räumen/Sitzungen für Szenarien, in denen ein Teilnehmer dem Gastgeber, der sich in einem anderen Raum befindet (d. h. mit einer anderen Sitzung verbunden ist), die Hand heben muss, und für die Hauptfunktion: die Verwaltung von Nebenräumen. Wir werden später im Detail erklären, wie wir die Signalisierungsnachrichten bei der Verwaltung von Pausenräumen verwenden.

Wenn der Anwendungsserver läuft, wird die Raumtabelle erstellt, falls sie nicht vorhanden ist. Ich verstehe, dass die Raumtabelle im wirklichen Leben etwas komplexer sein könnte. Hier listen wir nur die grundlegenden Daten auf, die wir benötigen. Das Skript zur Erstellung der Raumtabelle sieht wie folgt aus:

CREATE TABLE IF NOT EXISTS rooms(
    id VARCHAR(255) PRIMARY KEY,
    name VARCHAR(255) DEFAULT NULL,
    session_id VARCHAR(255) DEFAULT NULL,
    main_room_id VARCHAR(255) DEFAULT NULL,
    max_participants SMALLINT DEFAULT 0
)

Die session_id speichert die ID einer mit dem Raum verbundenen Sitzung. Die max_participants definiert die maximale Anzahl der Teilnehmer, die der Raum zulässt. Die main_room_id unterscheidet, ob es sich um einen Nebenraum handelt, der zum Hauptraum gehört, oder nur um einen Hauptraum, der Nebenräume haben kann: wenn es auf NULLsteht, handelt es sich um einen Hauptraum; andernfalls handelt es sich um einen Nebenraum, und sein Wert sollte auf die Raum-ID des Hauptraums gesetzt werden.

Zu Beginn wählen alle Benutzer auf der Anmeldeseite einen Raum aus, den sogenannten Hauptraum. Nach Erhalt der Front-End-Anfrage ruft der Anwendungsserver die Video API auf, um eine Sitzung für diesen Hauptraum zu erstellen, und fügt der Raumtabelle einen Datensatz mit session_id auf die ID der erstellten Sitzung gesetzt und main_room_id gesetzt auf NULL. Dann gibt er die session_id an alle angemeldeten Benutzer zurück, damit diese sich mit der Sitzung verbinden können.

Wenn die Besprechung läuft und ein Gastgeber beschließt, Nebenräume zu erstellen, gibt er die unter "Nebenraumkontrolle" aufgeführten Optionen ein, z. B. wie viele Nebenräume erstellt werden sollen", "Teilnehmer können den Raum wählen" oder "automatisch zuweisen" usw. Das Front-End sendet eine createSession Anfrage mit dem Parameter breakoutRooms an den Anwendungsserver, der daraufhin für jeden Nebenraum eine Sitzung erstellt und die Sitzungsnummer und andere Informationen in der Raumtabelle speichert, wobei ein Datensatz für jeden Nebenraum mit main_room_id auf die ID des Hauptraums gesetzt.

Verwendung der Signalisierungs-API zur Implementierung der Verwaltung von Nebenräumen

Das Room-Objekt enthält die Verweise auf die Sitzung, die Nachricht (breakoutRoomSignal) und die Teilnehmer und bietet die Einträge für die Erstellung von Breakout-Räumen und die Verwaltung der Teilnehmer.

Die Anwendung verwendet Signalisierungs-REST-API um Nachrichten an Clients zu senden, die mit allen Sitzungen verbunden sind, die mit einem Hauptraum/Pausenraum zusammenhängen, und um über Raumänderungen, Timer- und Raise-Hand-Anforderungen usw. zu informieren.

Eine Signalisierungsnachricht mit dem unten angegebenen Typ und den unten angegebenen Daten soll z. B. die Benutzer der Anwendung darüber informieren, dass neue Pausenräume eingerichtet wurden und sie einen auswählen können, dem sie beitreten möchten:

{
   "type": "signal:breakout-room",
   "data": {
       "message": "roomCreated (chooseroom)",
       "breakoutRooms": \[], //array of available rooms
   }
}
  • Meldung, dass "alle Räume entfernt wurden":

{
     "type": "signal:breakout-room",
     "data": {
         "message": "allRoomRemoved",
         "breakoutRooms": \[...],
     }
 }
  • einen Teilnehmer informieren, der von einem (Breakout-)Raum in einen anderen verlegt wird:

{
   "type": "signal:breakout-room",
   "data": {
       "message": "'participantMoved'",
       "breakoutRooms": \[...],
   }
}
  • während eine Signalisierungsnachricht mit dem Typ signal:count-down-timer über einen Zeitgeber informieren soll:

{
   "type": "signal:count-down-timer",
   "data": {
       "period": 1,
   }
}

Für diese breakoutRoomSignal Nachrichten führt die App entsprechende Aktionen durch, zum Beispiel für participantMovedbewegt sie den Teilnehmer in den zugewiesenen Raum.

if (mMessage.breakoutRoomSignal.message === 'participantMoved' && roomAssigned && (!currentRoomAssigned || currentRoomAssigned.id !== roomAssigned.id)) {
    setCurrentRoomAssigned(roomAssigned);
    mNotification.openNotification("Room assigned by Host/Co-host", `You will be redirected to Room: ${roomAssigned.name} in 5 seconds.`, () => handleChangeRoom(roomAssigned.name))
}

Innerhalb von handleChangeRoomverlässt die Anwendung den aktuellen Raum (indem sie die Verbindung zu ihrer zugehörigen Sitzung trennt) und tritt dem zugewiesenen Raum bei (indem sie sich mit der zugehörigen Sitzung verbindet).

async function handleChangeRoom(publisher, roomName) {
    const newRooms = \ [...mMessage.breakoutRooms];
    let targetRoom = newRooms.find((room) => room.name === roomName);

    await mSession.session.unpublish(publisher);
    await mSession.session.disconnect();

    const connectionSuccess = await connect(mSession.user, targetRoom ? targetRoom.id : '');

    if (!connectionSuccess) {
        // Force connect to main room;
        targetRoom = null;
        roomName = '';
        await connect(mSession.user);
    }

    let data = {
        fromRoom: currentRoom.name,
        toRoom: roomName ? roomName : mainRoom.name,
        participant: mSession.user.name
    }

    setInBreakoutRoom(targetRoom && targetRoom.name !== mainRoom.name ? targetRoom : null);
}

Wiederverwendung des Publisher-Objekts beim Hin- und Herwechseln zwischen Räumen

Wenn ein Teilnehmer den Hauptraum verlässt und in einen Nebenraum geht (oder anderweitig), ist es empfehlenswert, das Publisher-Objekt wiederzuverwenden wiederzuverwenden, um Ressourcen zu sparen.

Für jede type": "signal:breakout-room Nachricht, die dazu führen kann, dass ein Client einen Raum verlässt und einem anderen Raum beitritt, z. B. roomCreated (automatic)Bei jeder Nachricht, die dazu führt, dass ein Klient einen Raum verlässt und sich einem anderen Raum anschließt, trennt die Anwendung die Verbindung zu einer Sitzung und verbindet sich dann mit einer anderen Sitzung. Bei diesem Vorgang wird der für die vorherige Sitzung veröffentlichte Stream zerstört und das Ereignis streamDestroyed wird an den Publisher-Client weitergeleitet. Um das Publisher-Objekt zur Wiederverwendung zu erhalten, sollte die Methode preventDefault des Ereignisses streamDestroyed aufgerufen werden.

function handleStreamDestroyed(e) {
    if (e.stream.name !== "sharescreen") e.preventDefault();
    if (e.reason === 'forceUnpublished') {
        console.log('You are forceUnpublished');
        setStream({
            ...e.stream
        })
        setPublisher({
            ...e.stream.publisher
        })
    }
}

Die Demoanwendung verwendet dieses Publisher-Objekt erneut, um die mit dem Breakout-Room verbundene Sitzung zu veröffentlichen.

async function publish(
    user,
    extraData
) {
    try {
        if (!mSession.session) throw new Error("You are not connected to session");
        if (!publisher || publisherOptions.publishVideo !== hasVideo || publisherOptions.publishAudio !== hasAudio) {


            if (publisher) resetPublisher();
            const isScreenShare = extraData && extraData.videoSource === 'screen' ? true : false;
            const options = {
                insertMode: "append",
                name: user.name,
                publishAudio: isScreenShare ? true : hasVideo,
                publishVideo: isScreenShare ? true : hasAudio,
                style: {
                    buttonDisplayMode: "off",
                    nameDisplayMode: displayName ? "on" : "off"
                }
            };
            const finalOptions = Object.assign({}, options, extraData);
            setPublisherOptions(finalOptions);
            const newPublisher = OT.initPublisher(containerId, finalOptions);
            publishAttempt(newPublisher, 1, isScreenShare);
        } else {
            publishAttempt(publisher);
        }
    } catch (err) {
        console.log(err.stack);
    }
}

Schlussfolgerung

Durch die Möglichkeit, separate Sitzungen für die Breakout-Room-Funktion zu erstellen, müssen Sie sich nur noch darum kümmern, die Teilnehmer mit der richtigen Sitzung zu verbinden. Werfen Sie einen Blick auf den Code für weitere Details an und hoffen, dass Sie dies für Ihre Breakout-Room-Anwendung aufschlussreich finden.

Teilen Sie:

https://a.storyblok.com/f/270183/400x351/0c294bb1fc/iu-jie-lim.png
Iu Jie Lim

Iu Jie is a Software Engineer who is constantly seeking innovative ways to solve a problem. She is passionate about new technology, especially relating to cloud and AI. Out of work, she likes to spend her time hunting for tasty food with family.