
Compartilhar:
Michael é um engenheiro de software poliglota, empenhado em reduzir a complexidade dos sistemas e torná-los mais previsíveis. Trabalhando com diversas linguagens e ferramentas, ele compartilha seus conhecimentos técnicos com públicos de todo o mundo em grupos de usuários e conferências. No dia a dia, Michael é ex-representante de desenvolvedores da Vonage, onde dedicava seu tempo a aprender, ensinar e escrever sobre todos os tipos de tecnologia.
Chamada silenciosa com controles seletivos de áudio
Tempo de leitura: 5 minutos
A Nexmo já é, há muito tempo, uma escolha popular para soluções de centrais de atendimento, mas com o lançamento hoje dos Controles Seletivos de Áudio, estamos levando isso a um novo patamar. Os controles seletivos de áudio resolvem um caso de uso comum — um supervisor que ouve uma chamada, mas só é ouvido pelo funcionário e não pelo cliente — de maneira intuitiva.
A cada participante de uma conversa na plataforma Nexmo é atribuído um ID. Utilizando esses IDs e a ação de conversa , você pode criar um aplicativo que controle quais participantes uma pessoa nova na conversa pode ouvir. Nesta postagem, vamos desenvolver o caso de uso em que um supervisor ouve um funcionário.
O código deste aplicativo está disponível no GitHub
Inicialização de um aplicativo
Para criar esse fluxo de chamadas, precisamos escrever um pequeno aplicativo em Node.js. Vamos criar um novo projeto e instalar express para hospedar nosso answer_url.
Depois de fazer isso, você precisará criar uma instância de express, registrar uma answer_url e ficar à escuta em uma porta. Para isso, crie index.js com o seguinte conteúdo:
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');
});
Como criar sua URL de resposta
Agora que já temos um aplicativo inicializado, é hora de começar a adicionar nossa lógica de negócios. Há três participantes em nossa chamada:
Alice, supervisora do centro de atendimento
Bob, o atendente do centro de atendimento
Charlie, o cliente
No mundo real, usaríamos um banco de dados para armazenar todas as informações necessárias para que isso funcionasse, mas, para este post, vamos usar apenas um objeto na memória. A chave é o número de telefone do participante, e ela está associada a um objeto que contém informações sobre ele. Por enquanto, trata-se apenas da função que ele desempenha. Adicione o código a seguir após app.use(bodyParser.json());, certificando-se de atualizar o código abaixo, substituindo as chaves pelos seus números de telefone reais.
const conversationName = 'selective-audio-demo';
const participants = {
"<supervisor_phone_number>": {
"role": "supervisor",
},
"<agent_phone_number>": {
"role": "agent",
},
"<customer_phone_number>": {
"role": "customer",
}
};Depois de fazer isso, você precisa atualizar sua /webhooks/answer URL para que ela retorne um NCCO válido. Como precisaremos de um NCCO diferente para cada tipo de chamador, vamos adicionar uma switch instrução e chamar um método que retorne um NCCO para cada tipo de chamador:
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);
});
Este código chama createSupervisorNcco, createAgentNcco ou createCustomerNcco dependendo do tipo de chamador fornecido. Precisamos criar essas funções e retornar NCCO.
O Cliente NCCO
Vamos começar com o cliente NCCO. Quando o cliente entrar na chamada, queremos que ele possa ouvir o atendente, mas não o supervisor, e que possa falar tanto com o atendente quanto com o supervisor. Além disso, quando o cliente ligar, queremos que ele seja colocado em espera até que um atendente entre na conversa.
Adicione o seguinte ao final do seu arquivo para gerar o NCCO do cliente. Usamos a conversation ação, atribuímos à conversa um name, especificamos que a chamada não deve iniciar automaticamente e que o usuário deve ser colocado em espera. Todos esses são parâmetros existentes na Voice API da Nexmo.
O que torna esse NCCO interessante são os canSpeak e canHear . Esses dois parâmetros aceitam uma lista de UUIDs que identificam outros participantes e controlam com quem a pessoa que está se conectando à chamada pode falar e de quem pode ouvir. Se o UUID de um participante não for fornecido, o usuário que está se conectando não poderá falar com esse participante nem ouvi-lo.
Neste exemplo, nosso cliente pode falar com o atendente e com o supervisor dele, mas só consegue ouvir o áudio do atendente. Adicione o seguinte ao final do seu arquivo:
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')
}
]
} O Agente NCCO
Em seguida, temos o agente NCCO. Os agentes devem poder falar com todos os participantes e ser ouvidos por todos eles. Como ele é o proprietário desta teleconferência, definimos startOnEnter como “true” para indicar que a teleconferência se torna ativa quando ele entra. Além disso, definimos record para true para que a chamada seja gravada.
Como o agente pode falar com todos e ouvir todos, localizamos todos os clientes e todos os supervisores e fornecemos seus UUIDs à conversation ação.
Nesse caso, poderíamos omitir
canSpeakecanHeardo NCCO, já que os valores padrão permitem a transmissão de áudio entre todos os participantes. Para ter controle total sobre os participantes, optei por fornecê-los mesmo assim
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'))
}
]
} O Supervisor NCCO
Por fim, temos o supervisor NCCO. O supervisor pode ouvir todos, mas só pode falar com o atendente (isso é o oposto do que acontece com o cliente). Assim como antes, ele não é o responsável pela chamada, portanto startOnEnter está definido como “false”.
Oferecemos canSpeak e canHear uma lista de UUIDs, assim como nossos NCCOs anteriores, e isso garante que o supervisor só possa falar com o agente, mas ouça tanto o agente quanto o cliente.
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'))
}
]
} Fazendo tudo funcionar
Estamos quase lá! Faltam apenas duas coisas para que nosso aplicativo funcione. A primeira é implementar nosso findParticipants método. Adicione a seguinte função ao final do seu arquivo:
function findParticipants(callerType) {
let legs = [];
Object.entries(participants).forEach(([number, participant]) => {
if (participant.role == callerType && participant.legId) {
legs.push(participant.legId);
}
});
return legs;
}
Isso pesquisa entre todos os participantes a função fornecida. Se a função corresponder, o UUID da etapa é inserido em um array e retornado.
A segunda coisa a fazer é garantir que armazenemos o UUID da etapa do chamador quando for feita uma solicitação para /webhooks/answer. Atualize seu código para armazenar o ID da etapa após verificarmos se o chamador atual pode ser encontrado:
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;Neste momento, seu aplicativo já deve estar funcionando. Certifique-se de que seu answer_url esteja acessível (talvez usando ngrok , caso esteja na sua máquina local) e ligue para um número que aponte para o aplicativo que você acabou de criar. Se precisar criar um aplicativo Nexmo e alugar um número, dê uma olhada em nossos conceitos de aplicativos em nosso portal de desenvolvedores.
Compartilhar:
Michael é um engenheiro de software poliglota, empenhado em reduzir a complexidade dos sistemas e torná-los mais previsíveis. Trabalhando com diversas linguagens e ferramentas, ele compartilha seus conhecimentos técnicos com públicos de todo o mundo em grupos de usuários e conferências. No dia a dia, Michael é ex-representante de desenvolvedores da Vonage, onde dedicava seu tempo a aprender, ensinar e escrever sobre todos os tipos de tecnologia.