
Compartir:
Michael es el constructor calvo y barbudo. Aprovechando sus 20 años de experiencia en desarrollo de software y DevOps, este desarrollador con problemas de folclore pasa sus días centrado en ayudar a los demás a tener éxito.
Añadir llamadas SIP a sesiones de Video WebRTC
Tiempo de lectura: 4 minutos
Vivimos en la era de las videoconferencias. Desde la escuela hasta el trabajo y los eventos familiares, las videoconferencias se han convertido en una forma de vida para muchos, pero hay ocasiones en las que unirse desde una computadora no es posible. En este tutorial, veremos cómo permitir que los participantes se unan a tus sesiones de Video API de Vonage a través del teléfono.
¿Quieres saltar hasta el final? Puedes encontrar todo el código fuente de este tutorial en GitHub.
¿Cómo funciona?
Desde la sesión de la Video API, haremos una llamada a la Voice API. Esta llamada activará el webhook de respuesta en nuestra aplicación que creará una conversación de voz. Esa conversación se unirá a la sesión de Video como otro stream.
Cuando los usuarios marquen el número de conferencia, se les pedirá un PIN. Si el usuario proporciona el PIN correcto, se unirá a la conversación de voz. En ese momento, el usuario podrá oír a todos los participantes en la sesión de vídeo y ellos, a su vez, podrán oír la voz de los demás participantes.
Una vez finalizada la sesión, la llamada debe colgarse para evitar cargos adicionales de Voice o Video API.
Requisitos previos
Para seguir este tutorial, necesitarás:
Una cuenta de Video API de Vonage. Haz clic aquí para obtener una gratis.
Opcional: Ngrok para pruebas locales
Vonage API Account
To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.
This tutorial also uses a virtual phone number. To purchase one, go to Numbers > Buy Numbers and search for one that meets your needs.
Construir el frontend
Nuestro frontend utilizará Express con una plantilla EJS. Para este artículo, no cubriremos cómo crear una sesión de Video API, pero puedes revisar el código dentro del repositorio para ver cómo lo estamos haciendo. Nos centraremos únicamente en cómo añadir llamadas SIP a una sesión existente.
En la plantilla de la sesión de Video, añada las dos funciones JavaScript siguientes:
const dialOut = () => {
fetch(`/dial-out?roomId=${roomId}`)
.then(response => response.json())
.then((sipData) => {
connectionId = sipData.connectionId;
}).catch((error) => {
alert(`There was an error dialing-out`);
})
};
const hangUp = () => {
fetch(`/hang-up?roomId=${roomId}`)
.then(response => response)
.then((data) => {
console.log('dial-out-hang-up-complete');
}).catch((error) => {
alert(`There was an error hanging up`);
})
};
Ambas funciones llaman a rutas de nuestro backend Express. El método dialOut iniciará la conferencia de voz y la añadirá como flujo en la sesión de vídeo. La función hangUp se utilizará al final de la sesión para desconectar la conferencia de voz de la sesión. Dentro de nuestro HTML, vamos a querer añadir dos botones para llamar a estos function8s.
<button onclick="dialOut()">Click here to dial-out to the Vonage Conference</button>
<button onclick="hangUp()">Click here to hang-up</button> Vía rápida al backend
Con nuestro frontend listo, configuremos nuestro backend para manejar la conexión a Voice API de Vonage a través de SIP.
Funciones auxiliares
Necesitaremos algunas funciones de ayuda antes de ocuparnos de las llamadas salientes y los cuelgues.
/**
* Generates a random 4 digit PIN
*/
const generatePin = () => {
const pin = Math.floor(Math.random() * 9000) + 1000;
if (app.get(pin)) {
return generatePin();
}
return pin;
};
/**
* Creates a Video API user token
* @param {String} sessionId Id of the Video API session the user wishes to join
* @param {String} sipTokenData Data associated with the SIP connection
*/
const generateToken = (sessionId, sipTokenData = '') => OT.generateToken(sessionId, {
role: 'publisher',
data: sipTokenData,
});
/**
* Properties for the OT.dial API call
* @returns {Object}
*/
const setSipOptions = () => ({
auth: {
username: config.voiceApiKey,
password: config.voiceApiSecret,
},
secure: false
});
La función generatePin genera un PIN aleatorio de 4 dígitos que utilizaremos para crear un PIN único para cada sesión de Video. A las personas que llamen a la sesión se les pedirá ese PIN antes de permitirles unirse a la sesión.
La función generateToken se utiliza para crear un token de Video API con el SIP
La función setSipOptions crea un objeto que utilizaremos cuando marquemos la conexión SIP. Contiene la información de autenticación necesaria para unirse a la conferencia de voz.
Responder al Frontend
Con esas funciones en su lugar, vamos a añadir rutas para responder a nuestro frontend. La ruta dial-out utilizará la Video API para conectarse a una conferencia SIP. Más tarde, vamos a configurar la Voice API para saber cómo responder a estas llamadas.
/**
* When the dial-out get request is made, the dial method of the
* OpenTok Dial API is invoked
*/
app.get('/dial-out', (req, res) => {
const { roomId } = req.query;
const { conferenceNumber } = config;
const sipTokenData = `{"sip":true, "role":"client", "name":"'${conferenceNumber}'"}`;
const sessionId = app.get(roomId);
const token = generateToken(sessionId, sipTokenData);
const options = setSipOptions();
const sipUri = `sip:${conferenceNumber}@sip.nexmo.com;transport=tls`;
OT.dial(sessionId, token, sipUri, options, (error, sipCall) => {
if (error) {
console.dir(error)
res.status(500).send('There was an error dialing out');
} else {
app.set(conferenceNumber + roomId, sipCall.connectionId);
res.json(sipCall);
}
});
});
/**
* When the hang-up get request is made, the forceDisconnect method
* of the OpenTok API is invoked
*/
app.get('/hang-up', (req, res) => {
const { roomId } = req.query;
const { conferenceNumber } = config;
if (app.get(roomId) + app.get(conferenceNumber + roomId)) {
const sessionId = app.get(roomId);
const connectionId = app.get(conferenceNumber + roomId);
OT.forceDisconnect(sessionId, connectionId, (error) => {
if (error) {
res.status(500).send('There was an error hanging up');
} else {
res.status(200).send('Ok');
}
});
} else {
res.status(400).send('There was an error hanging up');
}
});
La ruta hang-up desconecta la conferencia de voz de la sesión de la Video API. Colgar la llamada al final de una reunión es de vital importancia. De lo contrario, la conferencia de Voz permanecerá abierta y conectada a la sesión de Video. Esto provocaría que ambas siguieran incrementando los cargos.
Webhooks de la Voice API
Cuando crees una aplicación de Voz, necesitarás proporcionar una Url de Respuesta y una Url de Evento. Si está ejecutando la aplicación localmente, querrá utilizar ngrok para proporcionar un punto final externo. Proporcione ya sea su Url ngrok o Url Heroku con rutas /voice-answer para la Url de Respuesta y /voice-events para la Url de Eventos.
app.get('/voice-events', (req, res) => {
res.status(200).send();
});
app.post('/voice-answer', (req, res) => {
const { serverUrl } = config;
const ncco = [];
if (req.body['SipHeader_X-OpenTok-SessionId']) {
ncco.push({
action: 'conversation',
name: req.body['SipHeader_X-OpenTok-SessionId'],
});
} else {
ncco.push(
{
action: 'talk',
text: 'Please enter a pin code to join the session'
},
{
action: 'input',
eventUrl: [`${serverUrl}/voice-dtmf`]
}
)
}
res.json(ncco);
});
app.post('/voice-dtmf', (req, res) => {
const { dtmf } = req.body;
let sessionId;
if (app.get(dtmf)) {
sessionId = app.get(dtmf);
}
const ncco = [
{
action: 'conversation',
name: sessionId,
}];
res.json(ncco)
})
La ruta /voice-answer ruta creará una conversación cuando se dispare debido a nuestra marcación. Cuando otros participantes llamen se les pedirá que proporcionen el PIN de 4 dígitos para la sesión. Las entradas de la persona que llama se reenviarán a la /voice-dtmf ruta para unirse potencialmente a la sesión.
Configuración de los ajustes
Empecemos por crear un archivo .env archivo. Puede utilizar el archivo .env-sample del repositorio como plantilla. Su contenido debe ser:
videoApiKey=
videoApiSecret=
voiceApiKey=
voiceApiSecret=
conferenceNumber=
serverUrl=Para ajustar videoApiKey y videoApiSecretcree un nuevo proyecto desde el panel de control de la Video API.
Project created dialog within the Vonage Video API dashboard
Una vez creada, copie la clave y el secreto de la API y péguelos en el archivo .env como los caracteres videoApiKey y videoApiSecret respectivamente.
Ahora cree una aplicación de voz y utilice la Clave API y el Secreto como los parámetros voiceApiKey y voiceApiSecret. Tendrás que comprar un número y asociarlo a tu aplicación de voz. Utiliza ese número como la variable conferenceNumber variable.
Por último, introduce la url de ngrok o Heroku como serverUrl.
Ahora puedes unirte a una sesión de Video y otros pueden marcar tu número e introducir un código PIN para unirse a la sesión. Es importante destacar que tienes que colgar la llamada al final de la sesión de Video para evitar el uso de ambas cuentas de Video y Voice cuando hayas terminado.
Lecturas complementarias
¿Quiere saber más sobre la función de Interconexión SIP de la Video API? A continuación encontrará algunos enlaces que pueden resultarle útiles.
