https://d226lax1qjow5r.cloudfront.net/blog/blogposts/multitrack-call-transcription-split-recording-voice-dr/MultiTrack-Call-Transcription_1200x675.jpg

Transcripción de llamadas MultiTrack con grabación dividida

Publicado el May 10, 2021

Tiempo de lectura: 6 minutos

En abril anunciamos que grabación dividida estaba disponible como parte de la Voice API de Nexmo. La grabación dividida permite grabar una conversación en estéreo, con un participante en cada canal. Esto hace que los casos de uso comunes, como la transcripción, sean mucho más fáciles de manejar.

Sin embargo, la grabación dividida tiene un inconveniente: si hay más de dos participantes, el primero estará en el canal 0 y todos los demás en el canal 1, lo que significa que se pierde la posibilidad de transcribir lo que ha dicho cada uno por separado.

¿Y si le dijera que Nexmo ahora admite no uno, ni dos, sino tres (¡!) canales independientes en una grabación? ¿Te alegrarías? ¿Y si te dijera que podemos grabar cuatro? ¿cinco? Nos complace anunciar que Nexmo admite hasta 32 canales en cada grabación. Has leído bien: podemos ofrecerte 32 canales de audio independientes, cada uno de ellos con un único participante, para que los proceses como quieras.

Al igual que la última vez, vamos a recorrer juntos un caso de uso sencillo. En este escenario, Alice necesita discutir un proyecto de trabajo con Bob y Charlie, y todos han acordado que sería una buena idea grabar la llamada. Para ello, Alice ha creado una pequeña aplicación Node.js que utiliza Nexmo para conectarse con Bob y Charlie y grabar la conversación.

Todo el código de este post está disponible en Github.

Puesta en marcha de la aplicación

Lo primero que tenemos que hacer es crear una nueva aplicación e instalar todas nuestras dependencias. Para ello, utilizaremos npm para inicializar un proyecto e instalar express y body-parser para manejar nuestras peticiones HTTP, y dotenv para gestionar la configuración de nuestra aplicación. También necesitaremos instalar el cliente nexmo cliente para que podamos acceder a la grabación de nuestra llamada una vez que recibamos una notificación de que está disponible y @google-cloud/speech transcribir el audio .

npm init -y
npm install express body-parser dotenv nexmo @google-cloud/speech --save

Una vez que hayas instalado todas tus dependencias, tendrás que crear una aplicación y alquilar un número al que la gente pueda llamar.

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.

Nexmo envía peticiones HTTP a su aplicación cada vez que se produce un evento dentro de su aplicación. Esto podría ser cuando una llamada comienza a sonar, cuando es contestada o cuando una grabación de llamada está disponible, por nombrar algunos. Para hacer esto Nexmo necesita ser capaz de llegar a su aplicación, lo cual es difícil cuando la aplicación se ejecuta localmente en su ordenador portátil. Para exponer su aplicación local a través de Internet, puede utilizar una herramienta llamada ngrok. Para más información puedes leer nuestra introducción a ngrok en nuestro blog.

Exponga ahora su servidor ejecutando ngrok http 3000. Debería ver un texto similar a http://2afec62c.ngrok.io -> localhost:3000. La primera sección es su URL ngrok, y es lo que necesita para el resto de este post.

Por fin estamos listos para crear una aplicación Nexmo y vincularle un número. Necesitarás reemplazar http://2afec62c.ngrok.io por tu propia URL ngrok en estos ejemplos:

# Create an application
nexmo app:create "MultiTranscription" http://2afec62c.ngrok.io/webhooks/answer http://2afec62c.ngrok.io/webhooks/event --keyfile private.key
# Application created: aaaaaaaa-bbbb-cccc-dddd-0123456789ab <- Make a note of this, you'll need it later

# Purchase a number
nexmo number:buy --country_code GB
# Number purchased: 442079460005 <- You'll need this too

# Link our number to our application
nexmo link:app NUMBER APPLICATION_ID

Si ahora realiza una llamada al número que ha adquirido, Nexmo realizará una solicitud a http://[id].ngrok.io/webhooks/answer para saber cómo gestionar la llamada. Como aún no hemos creado esa solicitud, la llamada fallará.

Gestión de una llamada entrante

Construyamos nuestra aplicación para gestionar las llamadas entrantes.

Cree el archivo index.js e introduzca el código que se muestra a continuación. Esto requires todas nuestras dependencias, configura el cliente Nexmo y crea una nueva instancia express instancia:

require("dotenv").config();

const express = require("express");
const bodyParser = require("body-parser");
const Nexmo = require("nexmo");

const nexmo = new Nexmo({
    apiKey: "not_used", // Voice applications don't use the API key or secret
    apiSecret: "not_used", 
    applicationId: process.env.NEXMO_APPLICATION_ID,
    privateKey: process.env.NEXMO_PRIVATE_KEY_PATH
});

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

A continuación, tenemos que crear nuestro /webhooks/answer que devolverá un archivo NCCO y le dirá a Nexmo cómo manejar nuestra llamada. En nuestra NCCO usamos dos acciones connect acciones para marcar automáticamente los números de teléfono de Bob y Charlie y añadirlos a la conversación, y una acción record que le dirá a Nexmo que grabe la llamada.

En record acción es donde ocurre la magia. Le decimos a Nexmo que divida el audio en canales separados configurando split: conversation y que el audio debe ser dividido en tres canales estableciendo channels: 3.

app.get('/webhooks/answer', (req, res) => {
    return res.json([
        {
            action: 'connect',
            endpoint: [{
                type: 'phone',
                number: process.env.BOB_PHONE_NUMBER
            }]
        },
        {
            action: 'connect',
            endpoint: [{
                type: 'phone',
                number: process.env.CHARLIE_PHONE_NUMBER
            }]
        },
        {
            "action": "record",
            "eventUrl": [`${req.protocol}://${req.get('host')}/webhooks/recording`],
            "split": "conversation",
            "channels": 3,
            "format": "wav"
        }
    ]);
});

Tendremos que proporcionar los números de teléfono de Bob y Charlie para que esto funcione, pero vamos a terminar de crear nuestros puntos finales antes de configurar nuestra aplicación.

Cree el /webhooks/event endpoint que será informado cuando se produzcan eventos de la llamada. Por ahora, todo lo que vamos a hacer es registrar los parámetros que recibimos y reconocer que lo recibimos enviando de vuelta una 204 respuesta.

app.post('/webhooks/event', (req, res) => {
    console.log(req.body);
    return res.status(204).send("");
});

Por último, tenemos que implementar nuestro/webhooks/recording endpoint. Esta URL se definió en nuestra OCN en la acción record y recibirá una notificación cuando haya una grabación disponible. Vamos a transcribir automáticamente el audio más tarde, pero por ahora vamos a registrar los parámetros de la solicitud para que podamos ver lo que está disponible.

app.post('/webhooks/recording', (req, res) => {
    transcribeRecording(req.body);
    return res.status(204).send("");
});

function transcribeRecording(params) {
    console.log(params);
}

app.listen(3000, () => console.log(`Listening`))

En este punto sólo queda una cosa por hacer - rellenar nuestro archivo .env para proporcionar la información que necesita nuestra aplicación. Necesitarás tu application_idasí como algunos números de teléfono de Bob y Charlie para ayudarte a hacer la prueba. Crea un archivo .env y añade lo siguiente, asegurándote de sustituir el ID de la aplicación y los números de teléfono por tus propios valores:

NEXMO_APPLICATION_ID="aaaaaaaa-bbbb-cccc-dddd-0123456789ab"
NEXMO_PRIVATE_KEY_PATH="./private.key"

BOB_PHONE_NUMBER="442079460000"
CHARLIE_PHONE_NUMBER="442079460001"

GOOGLE_APPLICATION_CREDENTIALS="./google_creds.json"

Asegúrate de añadir la línea de credenciales de Google, aunque todavía no hemos creado ese archivo. Lo crearemos en la siguiente sección

Una vez hecho esto, puede probar su aplicación ejecutando node index.js y llamando al número Nexmo que ha adquirido. Debería llamar automáticamente a los dos números que ha añadido al archivo .env y una vez que todos cuelguen, su /webhooks/recording debe recibir una URL de grabación.

Conexión a Google

Vamos a utilizar el servicio Speech-To-Text de Google para transcribir la grabación de nuestra llamada. Para empezar, necesitarás generar credenciales de Google Cloud en la consola de Google. Descarga el archivo JSON que proporcionan, cámbiale el nombre a google_creds.json y colócalo junto a index.js. Este es el archivo que el SDK de Google intentará leer para obtener tus credenciales de autenticación.

Para transcribir nuestros datos de audio, vamos a conectarnos a la API de Google Speech, pasando el idioma esperado, el número de canales de la grabación y el propio flujo de audio. Actualiza tu método transcribeRecording para que contenga el siguiente código:

function transcribeRecording(params) {
    const client = new speech.SpeechClient();

    const config = {
        encoding: `LINEAR16`,
        languageCode: params.language,
        audioChannelCount: params.channelCount,
        enableSeparateRecognitionPerChannel: true,
    };

    const request = {
        config: config,
        audio: {
            content: params.audio.toString('base64'),
        }
    };

    return client.recognize(request);
}

Esto devuelve un promise del SDK de voz de Google Cloud que se resolverá cuando la transcripción esté disponible. Antes de que podamos utilizar el SDK de voz, necesitamos requerirlo así que añade lo siguiente a tu sección require en la parte superior del archivo:

const speech = require('@google-cloud/speech').v1p1beta1;

En este punto estamos listos para transcribir nuestro audio. El último paso es obtener la grabación de Nexmo cuando recibamos una solicitud de /webhooks/recording y enviar el audio al servicio de transcripción de Google. Para ello, utilizamos el método nexmo.files.get y pasamos el audio devuelto a nuestro método transcribeRecording método:

app.post('/webhooks/recording', (req, res) => {
    nexmo.files.get(req.body.recording_url, (err, audio) => {
        if (err) { console.log(err); return; }

        transcribeRecording({
            "language": "en-US",
            "channelCount": 3,
            "audio": audio,
        }).then((data) => {
            const response = data[0];
            const transcription = response.results
                .map(
                    result =>
                    ` Channel Tag: ` +
                    result.channelTag +
                    ` ` +
                    result.alternatives[0].transcript
                )
                .join('n');
            console.log(`Transcription: n${transcription}`);
        });
    });
    return res.status(204).send("");
});

Además de pasar el audio como parámetro, le decimos a nuestro método transcribeRecording que hay 3 canales en el audio y que queremos transcribir utilizando el en-US modelo de lenguaje. Una vez que el SDK de voz de Google resuelve la promesa, leemos los resultados y emitimos una transcripción de la conversación, incluyendo de qué canal procede el audio.

Si llamas ahora a tu número Nexmo, te conectarás tanto con Bob como con Charlie. Una vez finalizada la llamada, cuelga y espera a que Nexmo te envíe un webhook de grabación. Una vez que llegue, enviamos ese audio a Google y la transcripción aparecerá en la consola. Así es como se ve para mí:

Transcription:
Channel Tag: 1 this is channel one
Channel Tag: 2 and this is channel two
Channel Tag: 3 and a test from channel three
Channel Tag: 1 great

Conclusión

Acabamos de crear un sistema de multiconferencia con transcripción automática en sólo 76 líneas de código. No sólo transcribe automáticamente la llamada, sino que transcribe cada canal por separado, lo que te permite saber quién dijo qué en la llamada. Para más información sobre las opciones disponibles a la hora de grabar una llamada, puede consultar la sección record action en nuestra NCCO referenciao ver un ejemplo de implementación de la NCCO requerida en varios idiomas.

Compartir:

https://a.storyblok.com/f/270183/384x384/1c8825919c/mheap.png
Michael HeapAntiguos alumnos de Vonage

Michael es un ingeniero de software políglota, empeñado en reducir la complejidad de los sistemas y hacerlos más predecibles. Trabaja con una gran variedad de lenguajes y herramientas, y comparte sus conocimientos técnicos con audiencias de todo el mundo en grupos de usuarios y conferencias. En el día a día, Michael es un antiguo defensor de los desarrolladores en Vonage, donde pasaba su tiempo aprendiendo, enseñando y escribiendo sobre todo tipo de tecnología.