
Partager:
Michael est un ingénieur logiciel polyglotte qui s'attache à réduire la complexité des systèmes et à les rendre plus prévisibles. Travaillant avec une variété de langages et d'outils, il partage son expertise technique avec des publics du monde entier lors de groupes d'utilisateurs et de conférences. Au quotidien, Michael est un ancien défenseur des développeurs chez Vonage, où il a passé son temps à apprendre, enseigner et écrire sur toutes sortes de technologies.
Call Whisper avec commandes audio sélectives
Temps de lecture : 5 minutes
Nexmo est depuis longtemps un choix populaire pour les solutions de centres de contact, mais avec la sortie aujourd'hui des contrôles audio sélectifs, nous passons à la vitesse supérieure. Les contrôles audio sélectifs résolvent un cas d'utilisation courant - un superviseur écoutant un appel mais n'étant entendu que par son employé et non par le client - d'une manière intuitive.
Chaque participant à une conversation sur la plateforme Nexmo se voit attribuer un identifiant. En utilisant ces identifiants et l'action action de conversation vous pouvez créer une application qui contrôle les participants qu'un nouveau participant à la conversation peut entendre. Dans ce billet, nous allons construire le cas d'utilisation d'un superviseur écoutant un employé.
Le code de cette application est disponible sur Github
Démarrage d'une application
Pour construire ce flux d'appels, nous devons écrire une petite application node.js. Créons un nouveau projet et installons express pour servir notre answer_url.
Une fois que vous avez fait cela, vous devez créer une instance de expressenregistrer un answer_url et écouter sur un port. Pour ce faire, créez index.js avec le contenu suivant :
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({"extended": true}));
app.use(bodyParser.json());
app.get('/webhooks/answer', (req, res) => {
return res.json([]);
});
app.listen(3000, () => {
console.log('Listening');
});
Création de l'URL de votre réponse
Maintenant que nous avons une application bootstrapped, il est temps de commencer à ajouter notre logique d'entreprise. Il y a trois participants à notre appel :
Alice, superviseur du centre de contact
Bob, l'agent du centre de contact
Charlie, le client
Dans le monde réel, nous utiliserions une base de données pour stocker toutes les informations nécessaires à cette opération, mais pour ce billet, nous nous contenterons d'utiliser un objet en mémoire. La clé est le numéro de téléphone du participant, qui renvoie à un objet contenant des informations le concernant. Pour l'instant, il s'agit uniquement de leur rôle. Ajoutez le code suivant après app.use(bodyParser.json());en veillant à mettre à jour le code ci-dessous, en remplaçant les clés par vos vrais numéros de téléphone.
const conversationName = 'selective-audio-demo';
const participants = {
"<supervisor_phone_number>": {
"role": "supervisor",
},
"<agent_phone_number>": {
"role": "agent",
},
"<customer_phone_number>": {
"role": "customer",
}
};Une fois que vous avez fait cela, vous devez mettre à jour votre /webhooks/answer afin qu'elle renvoie un NCCO valide. Comme nous aurons besoin d'un NCCO différent pour chaque type d'appelant, ajoutons une déclaration switch et appelons une méthode qui renvoie un NCCO pour chaque type d'appelant :
app.get('/webhooks/answer', (req, res) => {
const caller = participants[req.query.from];
if (!caller) {
return res.status(400).json("Unknown caller type: " + req.query.from);
}
// Generate an NCCO based on role
let ncco;
switch (caller.role) {
case 'supervisor':
ncco = createSupervisorNcco(caller);
break;
case 'agent':
ncco = createAgentNcco(caller);
break;
case 'customer':
ncco = createCustomerNcco(caller);
break;
default:
return res.status(400).json("Unknown caller type: " + caller.type);
}
return res.json(ncco);
});
Ce code appelle createSupervisorNcco, createAgentNcco ou createCustomerNcco en fonction du type d'appelant fourni. Nous devons créer ces fonctions et renvoyer NCCO.
Le client NCCO
Commençons par le NCCO du client. Lorsque le client s'inscrit, nous voulons qu'il puisse entendre l'agent, mais pas le superviseur, et qu'il puisse parler à la fois à l'agent et au superviseur. En outre, lorsque le client appelle, nous voulons qu'il soit mis en attente jusqu'à ce qu'un agent prenne part à la conversation.
Ajoutez ce qui suit à la fin de votre fichier pour générer le NCCO du client. Nous utilisons l'action conversation nous donnons à la conversation un namepour spécifier que l'appel ne doit pas démarrer automatiquement et que l'utilisateur doit être mis en attente. Il s'agit de paramètres existants pour l'API Voice de Nexmo.
Ce qui rend ce BCN intéressant, ce sont les canSpeak et canHear . Ces deux paramètres acceptent une liste d'UUIDs qui identifient les autres participants. Ces deux paramètres acceptent une liste d'UUID qui identifient les autres participants et contrôlent la personne qui se connecte à l'appel et qui peut lui parler et l'entendre. Si l'UUID d'un participant n'est pas fourni, l'utilisateur qui se connecte ne pourra pas parler à ce participant ni l'entendre.
Dans cet exemple, notre client peut parler à l'agent et à son superviseur, mais il ne peut entendre que l'audio de l'agent. Ajoutez ce qui suit au bas de votre fichier :
function createCustomerNcco(caller){
// Customer can hear agent, and speak to everyone
return [
{
"action": "conversation",
"name": conversationName,
"startOnEnter": false,
"musicOnHoldUrl": ["https://nexmo-community.github.io/ncco-examples/assets/voice_api_audio_streaming.mp3"],
"canSpeak": findParticipants('agent').concat(findParticipants('supervisor')),
"canHear": findParticipants('agent')
}
]
} L'agent NCCO
Vient ensuite le BCN de l'agent. Les agents doivent pouvoir s'adresser à tous les participants et être entendus par tous les participants. Il est le propriétaire de cette conférence téléphonique, c'est pourquoi nous fixons la valeur de startOnEnter à true pour indiquer que la conférence devient active lorsqu'ils la rejoignent. En outre, nous définissons record à true pour que l'appel soit enregistré.
Comme l'agent peut parler à tout le monde et entendre tout le monde, nous trouvons tous les clients et tous les superviseurs et fournissons leurs UUID à l'action. conversation action.
Dans ce cas, nous pourrions omettre
canSpeaketcanHeardans le NCCO, car les valeurs par défaut autorisent l'audio entre tous les participants. Dans l'intérêt d'un contrôle total sur les participants, j'ai choisi de les fournir quand même.
function createAgentNcco(caller){
// Agent can hear everyone, and speak to everyone
return [
{
"action": "conversation",
"name": conversationName,
"startOnEnter": true,
"record": true,
"canSpeak": findParticipants('customer').concat(findParticipants('supervisor')),
"canHear": findParticipants('customer').concat(findParticipants('supervisor'))
}
]
} Le superviseur NCCO
Enfin, nous avons le superviseur NCCO. Le superviseur peut entendre tout le monde, mais ne peut parler qu'à l'agent (c'est l'inverse du client). Comme précédemment, il n'est pas propriétaire de l'appel, donc startOnEnter est mis à faux.
Nous fournissons canSpeak et canHear une liste d'UUIDs comme nos précédents NCCOs, ce qui garantit que le superviseur ne peut parler qu'à l'agent, mais qu'il entendra à la fois l'agent et le client.
function createSupervisorNcco(caller){
// Supervisor can hear everyone, but only speak to agents
return [
{
"action": "conversation",
"name": conversationName,
"startOnEnter": false,
"musicOnHoldUrl": ["https://nexmo-community.github.io/ncco-examples/assets/voice_api_audio_streaming.mp3"],
"canSpeak": findParticipants('agent'),
"canHear": findParticipants('customer').concat(findParticipants('agent'))
}
]
} Faire en sorte que tout fonctionne
Nous y sommes presque ! Il ne reste plus que deux choses à faire pour que notre application fonctionne. La première consiste à implémenter notre méthode findParticipants . Ajoutez la fonction suivante au bas de votre fichier :
function findParticipants(callerType) {
let legs = [];
Object.entries(participants).forEach(([number, participant]) => {
if (participant.role == callerType && participant.legId) {
legs.push(participant.legId);
}
});
return legs;
}
Cette opération permet de rechercher le rôle fourni parmi tous les participants. Si le rôle correspond, l'UUID de la jambe est inséré dans un tableau et renvoyé.
La deuxième chose à faire est de s'assurer que nous stockons l'UUID de la jambe de l'appelant lorsqu'une requête est faite à /webhooks/answer. Mettez à jour votre code pour enregistrer l'identifiant de la jambe après avoir vérifié si l'appelant actuel peut être trouvé :
if (!caller) {
return res.status(400).json("Unknown caller type: " + req.query.from);
}
// Add their leg ID to the caller
caller.legId = req.query.uuid;À ce stade, votre application devrait fonctionner. Assurez-vous que votre answer_url est accessible (peut-être en utilisant ngrok si elle se trouve sur votre machine locale) et appelez un numéro qui pointe vers l'application que vous venez de créer. Si vous avez besoin de créer une application Numbers et de louer un numéro, jetez un coup d'œil à nos Concepts d'applications sur notre portail de développement.
Partager:
Michael est un ingénieur logiciel polyglotte qui s'attache à réduire la complexité des systèmes et à les rendre plus prévisibles. Travaillant avec une variété de langages et d'outils, il partage son expertise technique avec des publics du monde entier lors de groupes d'utilisateurs et de conférences. Au quotidien, Michael est un ancien défenseur des développeurs chez Vonage, où il a passé son temps à apprendre, enseigner et écrire sur toutes sortes de technologies.