https://d226lax1qjow5r.cloudfront.net/blog/blogposts/enable-live-captions-in-vonage-video-using-symbl-ai/live-captions_video-api-1.png

Aktivieren Sie Live-Untertitel in Vonage Videos mit Symbl.ai

Zuletzt aktualisiert am December 13, 2021

Lesedauer: 8 Minuten

In diesem Blogbeitrag möchte ich Ihnen zeigen, wie Sie Ihrer Vonage Video-Anwendung Transkription/Untertitelung hinzufügen können. Wir werden Folgendes nutzen Symbl.ai web SDK um dies zu erreichen. Das Audio wird von der Client-Seite an Symbl.ai gesendet, daher sind keine Änderungen auf der Server-Seite erforderlich. Symbl.ai ermöglicht es Ihnen, Ihre Voice- und Video-Applikationen mit einer Reihe von APIs und Entwickler-Tools mit Konversationsintelligenz auszustatten.

Warum brauchen Sie Untertitel?

Barrierefreiheit war eine der wichtigsten Anforderungen, als die Kommunikation während der Pandemie online ging. Haben Sie Kunden mit unterschiedlichen Akzenten, die Sie manchmal nur schwer verstehen können? Möchten Sie sehen, was Ihre Nutzer beschäftigt, was sie wollen, womit sie Probleme haben? Oder möchten Sie einfach nur die Transkription eines Anrufs speichern, um sie später analysieren zu können? Wir haben alles für Sie. Bleiben Sie dran. Wenn Sie sich lieber ein Video der fertigen Anwendungkönnen Sie es sich gerne ansehen.

In diesem Blogbeitrag zeige ich Ihnen, wie Sie Untertitel in einem Einzelgespräch hinzufügen können. Sehen Sie sich das GitHub-Repository für den vollständigen Quellcode, der Beispiele für Stimmungsanalysegraphen zeigt. Zusätzlich zu den Untertiteln erhalten Sie Einblicke und eine Zusammenfassung Ihres Gesprächs.

Ich werde mit ReactJS bauen, aber Sie können Vanilla JS oder jedes Framework/Bibliothek Ihrer Wahl verwenden.

Anforderungen

Um diese Beispielanwendung ausführen zu können, benötigen Sie einige Dinge:

Architektur

Das folgende Diagramm zeigt, was wir heute bauen werden. Der Einfachheit halber wird dieser Blogbeitrag die Integration mit Symbl.ai auf der Client-Seite behandeln. Für eine ausführlichere Erklärung der Architektur der Anwendung können Sie die Readme Datei der Anwendung.

Das Vonage Client SDK steuert unsere Video-Anwendung. Wie Sie im folgenden Diagramm sehen können, kommuniziert das Client SDK mit dem Symbl.ai SDK, indem es eine bidirektionale Verbindung über einen WebSocket öffnet. Die Audiodaten der Teilnehmer werden an das Symbl.ai SDK weitergeleitet und wir erhalten das Transkript der Audiodaten.

Um die Authentifizierung der Vonage-Sitzung und der Symbl.ai-Verbindung auf der Client-Seite zu ermöglichen, haben wir eine API in unserem Node.js-Server um Anmeldeinformationen zu generieren. Diese API wird auf dem Vonage Node.js SDK und der Symbl.ai API basieren.

Diagram of Vonage Video application connecting to Symbl.ai

Benutzernamen erstellen

Für einen Einzelanruf öffnet das Symbl.ai SDK eine Verbindung mit der Symbl.ai-Infrastruktur, über die zwei Benutzer Audio senden. Sobald wir die Ausgabe der Transkription erhalten, müssen wir wissen, zu welchem Benutzer die Untertitel gehören. Aus diesem Grund wird unsere App das Konzept der Benutzer mit Benutzernamen haben. Auf diese Weise können wir, wenn wir die connectionConfig in der useSymblai Hakenerstellen, können wir Symbl.ai mitteilen, wer spricht und wann. Die Ausgabe von Symbl.ai enthält den Namen des Sprechers zusammen mit dem Transkript, so dass wir jederzeit wissen, zu wem das Transkript gehört.

Für den Anfang habe ich einen Einstellungskontext erstellt, um auf den Benutzernamen und conversationId überall in unserer Anwendung zugreifen zu können. Die conversationId ist ein eindeutiger Bezeichner für eine bestimmte Konversation, die innerhalb der Symbl.ai Infrastruktur stattfindet. Sie kann einen oder mehrere Benutzer haben. Es ist nicht notwendig, die Untertitelung zu aktivieren, aber wir werden die conversationId um API-Aufrufe an Symbl.ai zu tätigen, um Informationen über die Stimmungsanalyse und eine Gesprächszusammenfassung zu erhalten. Wir werden diese Themen im Abschnitt Bonus.

import { createContext } from 'react';
 
export const PreferencesContext = createContext();
const [preferences, setPreferences] = useState({
   userName: null,
   conversationId: null,
 });
 
 const preferencesValue = useMemo(
   () => ({ preferences, setPreferences }),
   [preferences, setPreferences]
 );

Jetzt müssen wir unsere App nur noch mit dem ContextProvider umhüllen, damit wir überall in unserer App auf die Einstellungen zugreifen können.

     <Router>
       <PreferencesContext.Provider value={preferencesValue}>
         <Switch>
    <ProtectedRoute exact path="/room/:roomName" component={Wrapper} />
           <Route path="/room/:roomName/:conversationId/end">
             <EndCall />
           </Route>
           <Route path="/">
             <WaitingRoom />
           </Route>
         </Switch>
       </PreferencesContext.Provider>
     </Router>

Wie Sie in der Struktur unserer Appsehen können, wird der Benutzer standardmäßig auf die WaitingRoom Komponente weitergeleitet. Dort werden wir den Benutzer auffordern, seinen Benutzernamen und einen Raumnamen einzugeben. Sie können die Implementierung des Wartezimmers sehen Sie hier. Die Protected Route ist eine Komponente, die prüft, ob der Benutzer einen Benutzernamen eingerichtet hat, und die den Benutzer zum Warteraum weiterleitet, wenn dies nicht der Fall ist. Sie können die die Implementierung dieser Route hier. Dies soll verhindern, dass ein Benutzer einem Raum beitritt, ohne einen Namen gewählt zu haben. Wenn der Benutzer bereits einen Benutzernamen eingerichtet hat, leiten wir den Benutzer zur Wrapper Komponente, die eine Header und die Hauptkomponente enthält. Wenn Sie neugierig sind, können Sie können Sie sich diesen Baustein hier ansehen.

So sieht der Warteraum aus:

Waiting Room UI requesting username and room name

UseSymblai-Haken

Wir werden das Web-SDK von Symbl.ai verwenden, um die Komplexität des Öffnens einer WebSocket-Verbindung und der Weiterleitung des Audios zu umgehen. In einer React-Anwendung ist es eine gute Praxis, einen benutzerdefinierten React-Hook zu schreiben, um die Wiederverwendbarkeit unserer Anwendung zu erhöhen und den Code sauberer zu machen. Sie können die die gesamte Implementierung des benutzerdefinierten Hooks hieraber ich werde jeden Schritt im Detail erklären.

Lassen Sie uns das SDK installieren und importieren:

npm i @symblai/symbl-web-sdk

import symbl from '@symblai/symbl-web-sdk';

Wir werden einen benutzerdefinierten Hook erstellen, der den Herausgeber aus der Vonage Video-Sitzung akzeptiert, sowie ein boolesches Flag, das anzeigt, ob der Herausgeber mit dem Senden von Medien begonnen hat. Der benutzerdefinierte Hook gibt unsere Untertitel, die Untertitel der anderen Partei und den Namen des Sprechers zurück.

 
//CODE WILL GO HERE
 
return {
   captions,
   myCaptions,
   name,
 };
 
}
let streamRef = useRef(null);
 const { preferences } = useContext(PreferencesContext);
 const [captions, setCaptions] = useState('');
 const [myCaptions, setMyCaptions] = useState('');
 const [name, setName] = useState(null);
 const [symblToken, setSymblToken] = useState(null);
 let { roomName } = useParams();

Wir erstellen einige Statusvariablen, um unsere eigenen Beschriftungen, die Beschriftungen der anderen Partei, den Namen der sprechenden Person und das Token zu speichern. Wir werden auch einen Verweis auf die streamObject die von Symbl.ai zurückgegeben wird, sobald wir eine Verbindung mit ihnen hergestellt haben. Wir verwenden den Kontext, den wir zuvor erstellt haben.

Wir werden einen useEffect Hook erstellen, der nur beim ersten Rendering ausgeführt wird. Das Ziel dieses Hooks ist es, die Anmeldeinformationen für die Videositzung und ein Token für die Symbl.ai-Verbindung zu erhalten. Die getToken und getSymblToken Funktionen werden hier implementiert. Sie kommunizieren mit einer API auf unserer Serverseite kommunizieren, die die Generierung der Anmeldeinformationen übernimmt. Wir erhalten die roomName aus den URL-Parametern.

 useEffect(() => {
   getToken()
     .then((response) => {
       setSymblToken(response.data.accessToken);
       symbl.init({
         accessToken: response.data.accessToken, 
       });
     })
     .catch((e) => console.log(e));
 }, []);

Wir machen weiter und definieren einen weiteren useEffect Hook, der ausgeführt wird, sobald wir die Sitzung veröffentlicht und die Verbindung mit Symbl.ai gestartet haben. Wir erhalten eine mediaStreamTrack vom Publisher, sobald wir in der Session publizieren. Wir nutzen dann die Web Audio API um eine MediaStreamSource zu erstellen zu erstellen, die als Quelle in der connectionConfig für Symbl.ai verwendet wird.

Wenn Sie nicht die mediaStream vom Vonage-Publisher abrufen und nur den Ton vom Mikrofon erhalten möchten, können Sie dies tun, indem Sie keine Quelle in der Datei connectionConfig. Standardmäßig wird das Symbl.ai Web SDK den Audiokontext und die Quellknoten selbst verwalten.

In unserer Anwendung ordnen wir der Einfachheit halber id den Wert von roomNamezu, der ein eindeutiger Bezeichner ist, der von den Clients verwendet wird, um sich mit der Konversation zu verbinden und Audio an Symbl.ai zu übertragen. In einer realen Anwendung müssen Sie sicherstellen, dass dieser id eindeutig ist und nach Beendigung der Konversation nicht wiederverwendet wird.

Sie können sehen, dass es eine userId Zeichenkette in dem speaker Objekt der connectionConfig. Wenn Sie dort eine gültige E-Mail-Adresse eingeben, erhalten Sie eine E-Mail mit einigen Informationen aus der Unterhaltung. Wenn Sie das Feld leer lassen, wird Ihnen keine E-Mail zugesandt. Wir wollen jedoch den Namen des Sprechers festlegen, damit wir wissen, wessen Sprache es ist, wenn wir die Ausgabe von Symbl.ai erhalten. Wie Sie sehen können, hören wir auf den onSpeechDetected Rückruf:

useEffect(() => {
   if (isPublishing && publisher) {
     const audioTrack = publisher.getAudioSource();
     const stream = new MediaStream();
     stream.addTrack(audioTrack);
     const AudioContext = window.AudioContext;
     const context = new AudioContext();
     const source = context.createMediaStreamSource(stream);
     const id = roomName;
 
     const connectionConfig = {
       id,
       insightTypes: ['action_item', 'question'],
       source: source,
       config: {
         meetingTitle: 'My Test Meeting ' + id,
         confidenceThreshold: 0.5, // Offset in minutes from UTC
         encoding: 'LINEAR16',
         languageCode: 'en-US',
       speaker: {
         // Optional, if not specified, will simply not send an email in the end.
         userId: '', // Update with valid email
         name: preferences.userName || uuidv4(),
       },
       handlers: {
         /**
          * This will return live speech-to-text transcription of the call.
          */
         onSpeechDetected: (data) => {
           if (data) {
             if (data.user.name !== preferences.userName) {
               setCaptions(data.punctuated.transcript);
               setName(data.user.name);
             } else {
               setMyCaptions(data.punctuated.transcript);
             }
           }
         },
        
       },
     };
 
     const start = async () => {
       try {
         const stream = await symbl.createStream(connectionConfig);
         streamRef.current = stream;
         await stream.start();
         conversationId.current = await stream.conversationId;
         preferences.conversationId = conversationId.current;
       } catch (e) {
         console.log(e);
       }
     };
     start();
   }
 }, [
   isPublishing,
   roomName,
   preferences,
   publisher,
 ]);

Wir haben am Ende unseres Hooks eine asynchrone Funktion definiert, die aufgerufen wird, um eine Verbindung mit Symbl.ai herzustellen. Dies ist notwendig, weil der WebSocket in einem nicht-verarbeitenden Zustand gestartet wird, so dass wir Symbl.ai anweisen müssen, wann wir die Verbindung starten wollen.

Jetzt können wir unseren benutzerdefinierten Haken in der Komponente unserer Wahl verwenden. In dieser Anwendung wird er in der Hauptkomponente. Zunächst müssen wir ihn importieren:

import { useSymblai } from '../../hooks/useSymblai';

Und dann können wir die Daten destrukturieren, indem wir den benutzerdefinierten Hook aufrufen und ihm den Publisher und die isPublishing boolesche Variable übergeben:

const { captions, name, myCaptions} =
   useSymblai({
     publisher,
     isPublishing,
   });

An dieser Stelle können Sie die Beschriftungen einfach in Ihrer Benutzeroberfläche anzeigen oder eine beliebige Logik ausführen. Sie können einen Blick auf die Implementierung der Hauptvideokomponente hier ansehen. Um es noch einmal zusammenzufassen, captions sind die Untertitel der anderen Partei, myCaptions sind Ihre eigenen Untertitel, und name ist nur der Name der anderen Person.

Bonus

Symbl.ai bietet Ihnen nicht nur Untertitelungsfunktionen, sondern auch Stimmungsanalyse, Extraktion von Erkenntnissen, Zusammenfassung des Anrufs, Analysen und vieles mehr. Ich habe eine Beispielanwendung erstellt, die diese Funktionen vorstellt.

Weitere Informationen über die in der App enthaltenen Funktionen finden Sie in der API-Referenz:

Das folgende Video zeigt Ihnen, wie die Anwendung aussieht. An dem Gespräch sind zwei Nutzer beteiligt, Javier und Binoy. Wie Sie oben links sehen können, gibt es ein Diagramm, das Ihnen die Stimmungsanalyse für die Rede der anderen Partei anzeigt (von -1 bis 1, wobei 1 sehr positiv und -1 sehr negativ ist). In diesem Fall können wir sehen, dass Binoy sehr positiv war, als ich mit ihm über die coolen Funktionen von Symbl.ai gesprochen habe.

Unten links sehen Sie einige action_items die von der Symbl.ai-API aufgegriffen werden. Sie enthält den Namen des Beauftragten, sofern verfügbar. In diesem Fall sehen wir einige Fragen, wie z. B. die Frage von Binoy an Javier, ob Symbl.ai einfach in unsere Video APIs zu integrieren ist, und ein Handlungselement, das Binoy braucht, um "sie zu überprüfen" (mit Bezug auf Symbl.ai).

Wenn Sie auf "Gespräch beenden" klicken, leitet die App Sie auf die Analyseseite weiter, auf der Sie Metriken zur Aufschlüsselung der einzelnen Sprecher (Sprech- und Ruhezeit) und Metriken für das gesamte Meeting sehen können. In diesem Fall können wir die Statistiken für Javier und Binoy sehen. Eine weitere coole Funktion, die Symbl.ai bietet, ist die Möglichkeit, das Gespräch mithilfe der Verarbeitung natürlicher Sprache zusammenzufassen. So erhalten Sie ein paar Sätze mit einer kurzen Zusammenfassung des Gesprächs. Auf diese Weise können Sie sich einen Eindruck davon verschaffen, worum es in dem Gespräch ging, indem Sie einige Highlights lesen.

Dies ist sehr hilfreich, da es helfen kann, lange Follow-up-E-Mails mit einer Zusammenfassung und Aktionspunkten nach einem Anruf zu vermeiden. Das Erkennen von Markennamen ist immer eine Herausforderung, aber wir können sehen, wie Javier in diesem Fall bereits eine Integration mit einem KI-Unternehmen vorgenommen hat, die es Ihnen ermöglicht, Live-Untertitelung, Stimmungsanalyse und mehr zu aktivieren. Bedenken Sie, dass dies ein sehr kurzes Treffen war, aber je länger das Treffen ist, desto genauer wird die Zusammenfassung sein.

Wie geht es weiter?

Hoffentlich wissen Sie jetzt, wie Sie Live-Untertitel in Ihrer Vonage Video-Anwendung aktivieren können und weitere Einblicke in Ihre Videoanrufe erhalten. Das fertige Projekt ist auf GitHub verfügbar,

Teilen Sie uns auf Twitter mit welche Projekte Sie mit der Vonage Video API erstellen!

Außerdem, werden Sie Mitglied unserer Community auf Slack.

Teilen Sie:

https://a.storyblok.com/f/270183/384x384/6007824739/javier-molina-sanz.png
Javier Molina Sanz

Javier studied Industrial Engineering back in Madrid where he's from. He is now one of our Solution Engineers, so if you get into trouble using our APIs he may be the one that gives you a hand. Out of work he loves playing football and travelling as much as he can.