https://d226lax1qjow5r.cloudfront.net/blog/blogposts/stream-video-chat-with-texting-using-vonage-video-api-dr/Dev_Stream-Video_Texting_1200x600.png

Video-Chat mit Texting über die Vonage Video API

Zuletzt aktualisiert am May 5, 2021

Lesedauer: 4 Minuten

In dieser Reihe von Tutorials werden wir die Vonage Video API (ehemals TokBox OpenTok) und was Sie damit bauen können. Die Video API ist sehr robust und in hohem Maße anpassbar. In jedem Beitrag zeigen wir Ihnen, wie Sie eine bestimmte Funktion mithilfe der API implementieren können. Diesmal sehen wir uns an, wie Sie eine Option bereitstellen, mit der Teilnehmer einen Stream Ihres Video-Chats ansehen und über einen Text-Chat miteinander interagieren können.

Da diese Anwendung etwas serverseitigen Code erfordert, werden wir Glitch um die Einrichtung zu erleichtern. Sie können den Code auch herunterladen von diesem Glitch-Projekt herunterladen und auf dem Server oder der Hosting-Plattform Ihrer Wahl einsetzen (je nach den Anforderungen Ihrer Plattform müssen Sie möglicherweise einige Konfigurationsänderungen vornehmen).

In dieser Serie werden wir keine Front-End-Frameworks verwenden, sondern nur Vanilla Javascript, um den Schwerpunkt auf die Video API selbst zu legen. Am Ende dieses Tutorials werden Sie in der Lage sein, dem Video-Chat entweder als Betrachter oder als Teilnehmer. Der Unterschied zwischen diesen beiden Rollen besteht darin, dass Betrachter alle veröffentlichten Video-Streams sehen und mit anderen über einen Text-Chat interagieren können, während Teilnehmer zusätzlich ihr Video im Chat veröffentlichen können.

Screenshot of viewer page with text chat open

Den endgültigen Code für diese Anwendung finden Sie in diesem GitHub-Repository oder neu gemischt auf Glitch.

Voraussetzungen

Bevor wir loslegen, benötigen Sie einen Vonage Video API Account, den Sie kostenlos erstellen können hier. Sie benötigen außerdem Node.js installiert haben (wenn Sie nicht Glitch verwenden).

Dieses Tutorial baut auf einem früheren Tutorial auf: Texting-Funktionalität zu einem Video-Chat hinzufügen. Es behandelt die Verwendung der Signalisierungs-API für Texting-Funktionen in Ihrem Video-Chat.

Wenn Sie die Video API zum ersten Mal verwenden, empfehlen wir Ihnen, den ersten einführenden Beitrag der Serie durchzuarbeiten: Aufbau eines einfachen Video-Chatszu lesen, da dort die folgenden grundlegenden Einstellungen behandelt werden:

  • Erstellen eines Vonage Video API-Projekts

  • Einrichten auf Glitch

  • Grundlegende Projektstruktur

  • Initialisierung einer Sitzung

  • Verbinden mit der Sitzung, Abonnieren und Veröffentlichen

  • Grundlegende Layout-Stile für einen Video-Chat

Erstmalige Einrichtung

Da wir auf einen grundlegenden Video-Chat mit Texting-Funktionen aufbauen, beginnen wir mit dem Remix des im vorherigen Tutorial erstellten Projekts. Klicken Sie dazu auf die große Schaltfläche Remix unten. 👇

Remix this

Ihre Ordnerstruktur sollte in etwa so aussehen:

Folder structure of the project

Wie eingangs erwähnt, ist TokBox OpenTok jetzt Vonage Video API. Wir haben keine Änderungen an unseren Paketnamen vorgenommen, so dass Sie in Ihrem Code weiterhin auf OpenTok verweisen werden.

Um den Video-Chat zum Laufen zu bringen, gehen Sie zur .env und geben Sie Ihren API-Schlüssel und das Geheimnis für Ihr Projekt ein, die Sie im dem Vonage Video API-Dashboard. Sobald das erledigt ist, werden wir einige Ergänzungen am Projekt vornehmen, um eine Schnittstelle für die Betrachter bereitzustellen.

Fügen Sie das erforderliche Markup hinzu

Unsere Anwendung wird aus drei Seiten bestehen: einer Landing Page, auf der die Nutzer eine Sitzung erstellen oder ihr beitreten können und auswählen können, ob sie Zuschauer oder Teilnehmer sein wollen, und den beiden Video-Chat-Seiten für jede Rolle.

Wir müssen eine zusätzliche Seite für den Betrachter erstellen. Fügen wir eine viewer.html Datei in den Ordner views Ordner eine Datei hinzu, indem wir auf die Schaltfläche Neue Datei in der linken Seitenleiste klicken. Benennen Sie die Datei views/viewer.html und fügen Sie das folgende Markup in die Seite ein. Diese Seite ist fast identisch mit der index.html Datei, außer dass sie kein div für den Herausgeber.

Add a viewer.html to the views folder

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Stream your video chat (enhanced)</title>
    <meta
      name="description"
      content="Stream a basic audio-video chat plus texting with Vonage Video API in Node.js"
    />
    <link
      id="favicon"
      rel="icon"
      href="https://tokbox.com/developer/favicon.ico"
      type="image/x-icon"
    />
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <link rel="stylesheet" href="/style.css" />
  </head>

  <body>
    <header>
      <h1>Viewer</h1>
    </header>

    <main>
      <div id="subscriber" class="subscriber"></div>
    </main>

    <footer>
      <p>
        <small
          >Built on <a href="https://glitch.com">Glitch</a> with the
          <a href="https://tokbox.com/developer/">Vonage Video API</a>.</small
        >
      </p>
    </footer>

    <script src="https://static.opentok.com/v2/js/opentok.min.js"></script>
    <script src="/client.js"></script>
  </body>
</html>

Außerdem müssen wir eine Reihe von Optionsfeldern hinzufügen, über die die Benutzer ihre Rollen auf der landing.html Seite auswählen können.

<form id="registration" class="registration">
  <label>
    <span>Room</span>
    <input
      type="text"
      name="room-name"
      placeholder="Enter room name"
      required
    />
  </label>

  <!-- Add the user type radio buttons -->
  <p>Select your role:</p>
  <fieldset>
    <label>
      <input type="radio" name="user-type" value="viewer" checked />
      <span>Viewer</span>
    </label>

    <label>
      <input type="radio" name="user-type" value="participant" />
      <span>Participant</span>
    </label>
  </fieldset>

  <label>
    <span>User name</span>
    <input
      type="text"
      name="user-name"
      placeholder="Enter your name"
      required
    />
  </label>

  <button>Enter</button>
</form>

Das neue Feldset gestalten

Sie können die folgenden Stile hinzufügen, um das Standard-Layout der Felder und Optionsfelder etwas zu verbessern. Oder Sie können sie alle zusammen nach Ihren Wünschen umgestalten.

fieldset {
  border: 0;
  display: flex;
  justify-content: space-between;
  margin-bottom: 1em;
}

fieldset label {
  padding: 0.25em 0em;
  cursor: pointer;
}

Refaktorieren Sie das Client-seitige Javascript

Das Skript am unteren Ende der Landing Page muss so geändert werden, dass die Benutzer je nach ausgewähltem Benutzertyp auf die richtige Seite weitergeleitet werden.

const form = document.getElementById("registration");
form.addEventListener("submit", event => {
  event.preventDefault();
  const isViewer = form.elements["user-type"].value === "viewer";

  if (isViewer) {
    location.href = `/session/viewer/${form.elements["room-name"].value}?username=${form.elements["user-name"].value}&type=viewer`;
  } else {
    location.href = `/session/participant/${form.elements["room-name"].value}?username=${form.elements["user-name"].value}&type=participant`;
  }
});

Wie bei der client.js Datei müssen die oben in der Datei deklarierten Variablen ebenfalls etwas angepasst werden, da das URL-Format in diesem Lernprogramm etwas anders ist.

let session;
const url = new URL(window.location.href);
// Room name is now the fourth item
const roomName = url.pathname.split("/")[3];
const userName = url.searchParams.get("username");
// Additional variable for user type
const userType = url.searchParams.get("type");

Verschiedene Funktionen in der server.js Datei werden Abonnenten- und Herausgeber-Token generiert, so dass diese Informationen in der POST Anfrage aufgenommen, wenn die Seite geladen wird.

fetch(location.pathname, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ username: userName, type: userType })
})
  .then(res => {
    return res.json();
  })
  .then(res => {
    const apiKey = res.apiKey;
    const sessionId = res.sessionId;
    const token = res.token;
    const streamName = res.streamName;
    initializeSession(apiKey, sessionId, token, streamName);
  })
  .catch(handleCallback);

Die letzte Änderung betrifft die initializeSession() Funktion, da nur die Teilnehmer einen Herausgeber erstellen und in der Sitzung veröffentlichen müssen.

function initializeSession(apiKey, sessionId, token, streamName) {
  // Create a session object with the sessionId
  session = OT.initSession(apiKey, sessionId);
  
  // Check if user type is participant
  if (userType === 'participant') {
    // If so, create a publisher
    const publisher = OT.initPublisher(
      "publisher",
      {
        insertMode: "append",
        width: "100%",
        height: "100%",
        name: streamName
      },
      handleCallback
    );
    
    // Connect to the session
    session.connect(token, error => {
      // If the connection is successful, initialize the publisher and publish to the session
      if (error) {
        handleCallback(error);
      } else {
        session.publish(publisher, handleCallback);
      }
    });
  } else {
    // Connect to the session as a viewer
    session.connect(token, error => handleCallback(error));
  }

  initiateSessionListeners(session);
}

Routes auf dem Server handhaben

In der server.js müssen wir einige zusätzliche Änderungen vornehmen, um die richtigen Dateien für Betrachter und Teilnehmer bereitzustellen.

app.get("/session/participant/:room", (request, response) => {
  response.sendFile(__dirname + "/views/index.html");
});

app.get("/session/viewer/:room", (request, response) => {
  response.sendFile(__dirname + "/views/viewer.html");
});

Da wir uns nun um zwei Seiten kümmern müssen, verschieben wir die POST Handler-Funktionalität in eine separate Funktion, die userType als Parameter annimmt, damit wir sie während der Token-Generierung verwenden können.

app.post("/session/participant/:room", (request, response) => {
  initSession(request, response, "publisher");
});

app.post("/session/viewer/:room", (request, response) => {
  initSession(request, response, "subscriber");
});

function initSession(request, response, userType) {
  const roomName = request.params.room;
  const streamName = request.body.username;
  const isExistingSession = checkSession(roomName);

  isExistingSession.then(sessionExists => {
    if (sessionExists) {
      sessionDb
        .get(roomName)
        .then(sessionInfo => {
          generateToken(roomName, streamName, userType, sessionInfo, response);
        })
        .catch(error => error);
    } else {
      OT.createSession((error, session) => {
        if (error) {
          console.log("Error creating session:", error);
        } else {
          const sessionInfo = {
            _id: roomName,
            sessionId: session.sessionId,
            messages: []
          };
          sessionDb.put(sessionInfo);
          generateToken(roomName, streamName, userType, sessionInfo, response);
        }
      });
    }
  });
}

Die Funktion generateToken() Funktion übernimmt nun userType um das Token-Tele für Zuschauer und Teilnehmer zu unterscheiden.

function generateToken(roomName, streamName, userType, sessionInfo, response) {
  const tokenOptions = {
    role: userType,
    data: `roomname=${roomName}?streamname=${streamName}`
  };
  let token = OT.generateToken(sessionInfo.sessionId, tokenOptions);
  response.status(200);
  response.send({
    sessionId: sessionInfo.sessionId,
    token: token,
    apiKey: process.env.API_KEY,
    streamName: streamName
  });
}

Wenn alles gut gelaufen ist, können Sie den Raum als Teilnehmer betreten und einen Video-Chat mit anderen Teilnehmern führen sowie mit den Zuschauern per Text-Chat kommunizieren. Wenn Sie den Raum als Zuschauer betreten haben, sollten Sie einen laufenden Video-Chat verfolgen können (vorausgesetzt, es findet einer statt) und mit allen Teilnehmern der Sitzung per Text-Chat chatten können.

Screenshot of viewer page with text chat open

Sehen Sie sich den endgültigen Code auf Glitch oder GitHub und fühlen Sie sich frei, den Code zu remixen oder zu klonen und selbst damit herumzuspielen.

Was kommt als Nächstes?

Es gibt noch weitere Funktionen, die wir mit der Vonage Video API erstellen können und die in zukünftigen Tutorials behandelt werden. Aber in der Zwischenzeit können Sie mehr erfahren auf unserer umfassenden Dokumentationsseite. Wenn Sie auf Probleme stoßen oder Fragen haben, wenden Sie sich an uns auf unserem Gemeinschaft Slack. Vielen Dank fürs Lesen!

Teilen Sie:

https://a.storyblok.com/f/270183/384x384/46621147f0/huijing.png
Hui Jing ChenVonage Ehemalige

Hui Jing ist Developer Advocate bei Nexmo. Sie hat eine übermäßige Liebe zu CSS und Typografie und ist allgemein leidenschaftlich über alle Dinge im Web.