
Partager:
Karl est un défenseur des développeurs pour Vonage, qui se concentre sur la maintenance de nos SDK de serveur Ruby et sur l'amélioration de l'expérience des développeurs pour notre communauté. Il aime apprendre, fabriquer des objets, partager ses connaissances et tout ce qui a trait à la technologie du web.
Vidéo + IA : traitement audio configurable pour les applications Video
Temps de lecture : 6 minutes
Plus tôt cette année, j'ai écrit sur une application Node que j'ai construite pour transcrire l'audio d'un appel vidéo en utilisant la fonction Audio Connector de l'API Video de Vonage. L'objectif principal de l'application et du billet de blog qui l'accompagnait était de démontrer un cas d'utilisation de base de l'Audio Connector. Lorsque l'on pense au traitement audio, la transcription est probablement l'une des premières choses qui vient à l'esprit, il était donc logique de se concentrer sur ce cas d'utilisation en guise d'introduction à la fonctionnalité. Cependant, comme vous l'avez peut-être déjà vu dans d'autres articles de cette série, il est possible de faire beaucoup plus avec le traitement audio. J'ai donc pensé qu'il serait intéressant d'intégrer d'autres fonctionnalités dans cette application afin de démontrer d'autres cas d'utilisation. Vous pouvez voir l'application mise à jour sur GitHub.
Dans cet article, je décrirai brièvement les fonctionnalités ajoutées avant de fournir une explication de haut niveau de la mise en œuvre dans le code. L'article ne couvrira pas l'architecture globale ou la mise en œuvre de l'itération initiale de l'application. cet article en premier lieu. Vous pouvez également examiner le code (tel qu'il était à ce moment de l'histoire) sur notre site de la Communauté Vonage GitHub org.
Avant de présenter les nouvelles fonctionnalités de l'application, rappelons brièvement ce qu'est l'Audio Connector. Le connecteur audio est une fonction de l'API Video de Vonage qui vous permet d'envoyer un ou plusieurs flux audio bruts (individuellement ou mélangés) d'une session Video de Vonage, via votre propre serveur WebSocket, à des services externes pour un traitement ultérieur.
Audio Connector process flow diagram
Vous l'utilisez en effectuant un appel API REST à l'API Video de Vonage, en détaillant le ou les flux pour lesquels vous voulez l'audio, ainsi que l'adresse WebSocket à laquelle les envoyer. Essentiellement, la fonction du connecteur audio est d'extraire les données audio d'un appel vidéo et de les envoyer à une WebSocket. Ce que vous faites ensuite avec ces données audio dépend entièrement de vous.
Vous pouvez en savoir plus sur l'Audio Connector dans la documentation de l documentation Video API.
Dans la première itération de l'application, nous avons utilisé le Symbl.ai JavaScript SDK pour envoyer les données audio à l API de streaming de Symbl pour la transcription. Voyons maintenant quelques-unes des nouvelles fonctionnalités de traitement audio dans l'itération actuelle de l'application.
Quoi de neuf ?
Outre la transcription, l'appli de démonstration fournit désormais un certain nombre d'informations spécifiques basées sur l'audio d'un appel vidéo.
Questions : Les questions sont extraites de l'audio lorsqu'un participant à l'appel vidéo dit quelque chose dans le cadre de la conversation qui est formulé comme une question, par exemple, "quand est le budget pour ce projet ?"
Actions : Semblables à des questions, elles sont extraites d'une conversation lorsque quelque chose est présenté comme une tâche spécifique à accomplir, par exemple "Je terminerai l'article de blog avant la fin du sprint en cours".
Sujets : Les sujets sont extraits d'une conversation lorsqu'un mot ou une phrase est détecté comme étant un mot-clé important.
Flux d'applications
Les nouvelles fonctionnalités ont été mises en œuvre de manière à fournir des options configurables pour les parties de l'audio que l'utilisateur final souhaite traiter.
Le flux de l'application commence par un formulaire contenant une série de cases à cocher, chacune correspondant à une option de traitement. L'utilisateur sélectionne les options qu'il souhaite et clique sur le bouton "Appel vidéo avec traitement audio".
Application Config Options Screen
Ils accèdent alors à l'écran d'appel principal, où ils peuvent entrer leur nom et commencer l'appel. Il y a un bouton pour lancer le traitement audio et des liens vers des pages montrant l'audio traité pour les options sélectionnées.
Main call screen
En cliquant sur le lien "Obtenir des questions", par exemple, l'utilisateur accède à une page répertoriant toutes les questions détectées au cours de l'appel vidéo.
Questions output screen
Explication du code
Dans l'itération initiale de l'application, le traitement de la transcription a été effectué par l'intermédiaire de l'API API de streamingde Symbl.ai, plus précisément en utilisant le SDK JavaScript pour faire une requête à l'API en utilisant sa méthode sendAudio méthode. Il y avait deux aspects principaux à la mise en œuvre de cette méthode :
Définition d'un gestionnaire pour la détection de la parole par l'invocation d'une méthode du SDK Symbl
startRealtimeRequestde Symbl SDK.Faire quelque chose avec les données renvoyées (ce qui, dans ce cas, signifie les stocker dans un
transcriptionstableau). Ce tableau est disponible via l'objetapp.contextde sorte que son contenu puisse être rendu plus tard selon les besoins.
Les nouvelles fonctionnalités de traitement (questions, actions et sujets) sont également disponibles via l'API de flux de Symbl, mais nécessitent des gestionnaires supplémentaires. J'ai également décidé de stocker les données de réponse pour les différents gestionnaires dans des tableaux séparés (bien que j'aurais pu les stocker dans le même tableau et les filtrer lors du rendu).
Un autre aspect des nouvelles fonctionnalités est le fait qu'elles sont configurables. Ainsi, lorsque j'ai invoqué startRealtimeRequestje n'ai voulu ajouter que les gestionnaires nécessaires.
La logique de gestion de tout cela a été extraite dans une classe SymblProcessor et plutôt que de définir un transcriptions n'est pas défini sur app.context dans le fichier index.js un objet SymblProcessor est instancié et ajouté au contexte :
app.context.symblProcessor = new SymblProcessor();Une grande partie de la nouvelle mise en œuvre est gérée par cette SymblProcessor classe.
class SymblProcessor {
constructor() {
this.messages = [];
this.insights = [];
this.topics = [];
this.config = {
transcription: false,
actionItems: false,
questions: false,
topics: false
};
}
setConfig(config) {
config.forEach(option => this.config[option] = true);
}
sethandlers() {
let handlers = {};
if (this.config.transcription) { handlers.onMessageResponse = this.onMessageResponseHandler; }
if (this.config.actionItems || this.config.questions) { handlers.onInsightResponse = this.onInsightResponseHandler; }
if (this.config.topics) { handlers.onTopicResponse = this.onTopicResponseHandler; }
return handlers;
}
setInsightTypes() {
let insightTypes = [];
if (this.config.actionItems) { insightTypes.push('action_item'); }
if (this.config.questions) { insightTypes.push('question'); }
return insightTypes;
}
getTranscriptions() {
return this.messages.map(message => ({id: message[0].from.id, name: message[0].from.name, transcription: message[0].payload.content}));
}
getActionItems() {
let actionItems = this.insights.filter(insight => insight[0].type == 'action_item');
return actionItems.map(item => item[0].payload.content);
}
getQuestions() {
let questions = this.insights.filter(insight => insight[0].type == 'question');
return questions.map(question => question[0].payload.content);
}
getTopics() {
return this.topics.map(topic => topic[0].phrases);
}
onMessageResponseHandler = (data) => {
this.messages.push(data);
}
onInsightResponseHandler = (data) => {
this.insights.push(data);
}
onTopicResponseHandler = (data) => {
this.topics.push(data);
}
}
La classe définit un constructor avec des tableaux distincts pour messages (transcriptions), insights (qui contient à la fois des questions et des actions), et topicsainsi que la définition d'un tableau par défaut config.
Il dispose ensuite de trois méthodes (setConfig, sethandlers, et setInsightTypes) pour mettre à jour l'objet config (en fonction des options choisies par l'utilisateur) et d'utiliser cette mise à jour pour déterminer la valeur de l'objet config pour déterminer les handlers et insightTypes pour l'appel symblSdk.startRealtimeRequest l'appel.
Les méthodes restantes sont les définitions des gestionnaires eux-mêmes (qui se contentent de transférer les données renvoyées dans le tableau approprié) et les méthodes permettant d'extraire les données des tableaux et de les filtrer et/ou de les mettre en correspondance si nécessaire afin qu'elles soient ensuite affichées dans les vues appropriées.
L'application a subi d'autres modifications, telles que des mises à jour du postSymblCall contrôleur, postSymblProcessing des routes supplémentaires, des gestionnaires de routes et des vues, ainsi qu'une restructuration et un renommage des fichiers, des fonctions, etc. Je n'entrerai pas dans les détails de ces changements, puisqu'ils sont principalement destinés à faciliter l'extraction d'une grande partie de la logique de traitement vers la classe SymblProcessor classe.
Connecteur audio : Flux individuels ou combinés
En guise de conclusion, je voulais juste souligner un aspect de l'utilisation de la fonctionnalité Audio Connector, qui pourrait déterminer la façon dont vous mettez en œuvre une application qui l'utilise.
Le /connect point de terminaison de l'API Video de Vonage, qui est utilisé pour démarrer une connexion WebSocket de connecteur audio, vous donne la possibilité de passer un streams dans le corps de la demande, contenant les ID des flux pour lesquels l'audio doit être envoyé au WebSocket.
{
"sessionId": "Vonage Video API session ID",
"token": "A valid Vonage Video API token",
"websocket": {
"uri": "wss://service.com/ws-endpoint",
"streams": [
"streamId-1",
"streamId-2"
],
"headers": {
"headerKey": "headerValue"
},
"audioRate" : 8000
}
}Si cette propriété est omise, l'audio combiné de tous les flux de la session est envoyé. streams est omise, l'audio combiné de tous les flux de la session est envoyé.
Étant donné que la mise en œuvre initiale de cette application était axée sur la transcription, et que je voulais que des morceaux spécifiques de l'audio transcrit soient attribués à des locuteurs individuels identifiés au sein de l'appel vidéo, l'application a été mise en œuvre en effectuant plusieurs requêtes à ce point de terminaison, chacune spécifiant un flux unique, et en définissant un socket web différent pour chaque flux.
Toutefois, si les exigences de votre application ne vous obligent pas à attribuer l'audio transcrit à des orateurs identifiés (par exemple, si vous souhaitez rassembler les questions soulevées lors de l'appel mais que vous n'avez pas besoin de savoir qui a posé la question), il serait probablement plus judicieux de combiner l'audio et de l'envoyer à un seul point d'extrémité de socket web.
Prochaines étapes
Nous espérons que cet article vous a donné quelques idées sur les types de fonctionnalités que vous pouvez créer avec Audio Connector et qu'il vous a peut-être donné envie de créer quelque chose de génial !
Si vous avez des commentaires ou des questions, ou si vous voulez simplement partager un projet que vous avez construit avec Audio Connector, n'hésitez pas à nous contacter dans notre Slack des développeurs de Vonage.
Partager:
Karl est un défenseur des développeurs pour Vonage, qui se concentre sur la maintenance de nos SDK de serveur Ruby et sur l'amélioration de l'expérience des développeurs pour notre communauté. Il aime apprendre, fabriquer des objets, partager ses connaissances et tout ce qui a trait à la technologie du web.