https://a.storyblok.com/f/270183/1368x665/dea46e8442/customer-voicemail_node-express-socket.png

Crear un buzón de voz personalizado con Node.js, Express y Socket.io

Publicado el May 14, 2024

Tiempo de lectura: 9 minutos

Introducción

En este tutorial, aprenderás a crear tu buzón de voz. Usaremos Express.js y Socket.io.

Puede encontrar el código completo en GitHub.

Esquema y requisitos previos

  • Node.js instalado

  • Ngrok se instala para exponer su servidor de desarrollo local a Internet.

  • Conocimientos básicos de JavaScript y Node.js

  • Una cuenta API de Vonage para acceder a nuestra Voice API

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.

Estructura del proyecto

Como referencia, este es el aspecto que tendrá el directorio del proyecto:

[node_modules] [public] [voicemails] // Voicemail mp3 files here index.html .env index.js package-lock.json package.json private.key

Inicializar el proyecto

  1. Cree un directorio para su aplicación y cambie a él.

  2. Ejecute npm init -y para inicializar el proyecto.

Configurar Ngrok

Para que los puntos finales de nuestro servidor local sean accesibles desde Internet sin desplegar nuestra aplicación en un entorno de producción, expondremos nuestra máquina local utilizando ngrok.

Abra una nueva ventana de terminal o de símbolo del sistema e inicie ngrok en el puerto 3000 con el siguiente comando: ngrok http 3000.

Crea una aplicación de Vonage y agrega la clave privada

  1. Inicia sesión/ Regístrate en tu Panel de API de Vonage y ve a "Tus aplicaciones" en Crear y administrar.

  2. Haz clic en "+ Crear una nueva aplicación". Dale un nombre a tu aplicación y selecciona "Generar clave pública y privada". A continuación, descarga la clave privada generada.

  3. En la sección "Capacidades", activa "Voice" y proporciona las URL del evento y los puntos finales del webhook de respuesta. Utilice su URL Ngrok ${NGROK_URL}/event para la URL del evento y ${NGROK_URL}/answer para la URL de respuesta.

  4. Guarde su aplicación. Tenga en cuenta que se proporcionan el ID de la aplicación y la clave API.

  5. Añade la clave privada descargada al directorio de tu proyecto.

Echa un vistazo a nuestra guía ngrok para obtener ayuda con los puntos finales webhook

Adquirir un número virtual

A continuación, obtendremos un número virtual que servirá como punto de contacto para las llamadas entrantes. Este número estará asociado a nuestra aplicación de Vonage. Este es el proceso para obtener uno:

Instalar la CLI de Vonage: npm install @vonage/cli -g Busca los Numbers disponibles en tu región deseada: vonage numbers:search US (reemplaza US por el código de tu país si es necesario). Compra un número: vonage numbers:buy 12079460000 US.

Recuerde que algunos Numbers no pueden adquirirse a través de la línea de comandos, por lo que deberá comprarlos a través del panel de control. Puedes hacerlo ingresando al Panel de Vonage y a la página Página Comprar Numbers. Marca 'Voice' en el filtro de búsqueda y selecciona el país donde deseas comprar un número.

Vincular un número de teléfono virtual a la aplicación

Una vez que hayamos seleccionado nuestro número, debemos vincularlo a nuestra aplicación de Vonage. Esto puede hacerse directamente a través del panel de Vonage o usando la CLI. Al vincular el número, nos aseguramos de que las llamadas se dirijan correctamente a nuestra aplicación.

vonage apps:link --number=12079460000 VONAGE_APPLICATION_ID

También puedes hacerlo desde el salpicadero. Vaya a la Página de aplicaciones y haz clic en la aplicación que creaste anteriormente. Haz clic en el botón "Vincular" situado junto al número que quieras vincular en la sección Voice.

Crear variables de entorno

Cree un .env en la raíz del proyecto con lo siguiente, rellenando los datos del Panel de Vonage: Consulta esta publicación del blog si no estás familiarizado con Cómo usar variables de entorno en Node.js.

URL=YOUR_NGROK_URL API_KEY=Your Vonage API key is used to authenticate API requests. API_SECRET=Your Vonage API secret VONAGE_APPLICATION_ID= The ID of your Vonage application. Vonage applications allow you to manage your communication services and define how they interact with your web application. PRIVATE_KEY=private.key

Instalar dependencias

Vamos a utilizar las siguientes dependencias en nuestro proyecto: Express Socket.io @vonage/server-client) body-parser dotenv

Puede instalarlos ejecutando el siguiente comando:

npm install express socket.io @vonage/server-sdk body-parser dotenv

Configuración del servidor

Cree el archivo index.js e inicializa tu servidor con los paquetes necesarios. Configura un cliente de Vonage utilizando las variables de .env y esboza las /answer, /eventy /voicemail rutas.

require("dotenv").config();

const express = require("express");
const app = express();
const http = require("http").Server(app);
const io = require("socket.io")(http);

const bodyParser = require("body-parser");
const { FileClient } = require("@vonage/server-client");

// Ensure these environment variables are correctly set in your .env file
const fileClient = new FileClient({
  applicationId: process.env.VONAGE_APPLICATION_ID,
  privateKey: process.env.PRIVATE_KEY,
});

app.use(express.static("public"));
app.use(bodyParser.json());

app.get('/answer', (req, res) => {});

app.post('/event', (req, res) => {});

app.post('/voicemail', (req, res) => {});

http.listen(3000, () => console.log("Server is running on port 3000"));

Definir la lógica de gestión de llamadas

En la /answer ruta, configuramos un flujo de llamadas utilizando un NCCO (Objeto de Control de Llamada) para interactuar con las personas que llaman. Este script saluda a la persona que llama, le pide que deje un mensaje tras un pitido y finaliza la grabación cuando se pulsa la tecla "#", seguida de un mensaje de despedida. La línea res.send(ncco); envía este conjunto de instrucciones a Vonage y lo ejecuta durante la llamada.

app.get("/answer", (req, res) => {
  const ncco = [
    {
      action: "talk",
      voiceName: "Ivy",
      text: "Please record your message for me after the beep. Press # to end.",
    },
    {
      action: "record",
      eventUrl: [`${process.env.URL}/voicemail`],
      endOnKey: "#",
      beepStart: true,
    },
    {
      action: "talk",
      voiceName: "Ivy",
      text: "Message recorded. Bye!"
    }
  ];
  res.send(ncco);
});

Personalice el saludo para que la llamada sea más personal. Muchas opciones de voz le permiten ajustar el tono vocal, el tono y el estilo para que coincidan con sus preferencias o la identidad de su marca. Explore diferentes estilos de voz para encontrar el que mejor se adapte a su aplicación. Tenga en cuenta que algunos estilos de voz pueden no ser compatibles con SSML (Speech Synthesis Markup Language), por lo que merece la pena comprobar la lista de idiomas y estilos compatibles.

Gestión de eventos y mensajes de voz

El punto final /event procesa varios eventos enviados por la API de Vonage. Cuando ocurre un evento, como una llamada contestada o un correo de voz grabado, la API de Vonage envía datos relacionados con ese evento a este punto final. Nuestro servidor registra estos datos de eventos en la consola para su visibilidad y devuelve un 204 (respuesta Sin contenido) para acusar recibo. Este manejo mínimo es suficiente para muchas aplicaciones, aunque podrías ampliarlo para realizar acciones específicas basadas en tipos de eventos.

Implementar la lógica en /event para procesar eventos.

app.post("/event", (req, res) => {
  console.log("Event received:", req.body);
  res.sendStatus(204);
});

Cuando alguien deja un mensaje de voz, la API de Vonage envía una solicitud POST a nuestro punto final /voicemail con detalles sobre la grabación, incluida una URL donde se puede acceder al archivo de audio grabado.

Nuestro servidor simula guardar esta grabación creando un nombre de archivo basado en la marca de tiempo actual y simulando guardar el archivo en una ruta especificada. Esta simplificación es para fines de demostración; es probable que descargue la grabación desde la URL proporcionada y la almacene de forma más segura en una aplicación real.

Tras "guardar" el archivo, el servidor emite un evento de buzón de voz a todos los clientes conectados a través de Socket.io, pasando el nombre del archivo y la fecha y hora actuales.

En /voicemailse simula el almacenamiento de mensajes de voz y se emite un voicemail evento al cliente.

app.post("/voicemail", (req, res) => {
  const filename = `voicemail-${Date.now()}.mp3`;
  const path = `${__dirname}/public/voicemails/${filename}`;

  fileClient
    .downloadFile(req.body.recording_url, path)
    .then(() => {
      io.emit("voicemail", {
        date: new Date().toISOString(),
        file: filename,
      });
      res.sendStatus(200);
    })
    .catch((err) => {
      console.error("Error saving file:", err);
      res.status(500).send(err);
    });
});

http.listen(3000, () => console.log("Server is running on port 3000"));

La interfaz de usuario

En public/index.htmlañadiremos un elemento <audio> para reproducir los mensajes del buzón de voz y un contenedor para listar los buzones de voz, permitiendo que la recepción del buzón de voz reproduzca o borre los mensajes recibidos.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Voicemail</title>
</head>
<body>
    <audio>Sorry, your browser does not support this audio.</audio>
    <div id="voicemails" class="voicemails">
        <h2>New Voicemails</h2>
        <!-- Voicemails will be dynamically added here -->
    </div>
</body>
</html>

Visualización de los mensajes de Voice Mail recibidos

Nuestro JavaScript enriquece la interfaz de usuario conectándose con el servidor a través de Socket.io para obtener actualizaciones en tiempo real, como cuando llegan nuevos mensajes de voz. Añade automáticamente estos mensajes de voz a una lista, mostrando su fecha y proporcionando botones para reproducirlos o eliminarlos. Mientras que el botón de reproducción utiliza un elemento <audio> para la reproducción, el botón de borrado sólo elimina el buzón de voz de la pantalla, no del servidor. Mejorar la aplicación para eliminar los mensajes de voz del servidor también sería una mejora valiosa, ya que requeriría una lógica adicional del lado del servidor para gestionar las eliminaciones de archivos de forma segura.

Añada el siguiente código a su archivo index.html:

  <script src="/socket.io/socket.io.js"></script>
  <script>
    const voicemailsDiv = document.getElementById("voicemails");
    const audio = document.querySelector("audio");

    document.addEventListener("click", function (e) {
      let el = e.target;
      if (el.classList.contains("play_btn")) {
        audio.src = el.getAttribute("data-src");
        audio.play();
        console.log("Playing audio from:", audio.src);
      }
      if (el.classList.contains("del_btn")) {
        el.closest(".voicemail-item").remove();
        console.log("Voicemail deleted");
      }
    });

    const socket = io();
    socket.on("connect", () => {
      console.log("Connected to server via Socket.io");
    });
    socket.on("voicemail", (vm) => {
      console.log("Received voicemail event:", vm);
      const voicemailElement = document.createElement("div");
      voicemailElement.classList.add("voicemail-item");
      voicemailElement.innerHTML = `
            <div>Date: ${vm.date}</div>
            <button class="play_btn" data-src="/${vm.file}">Play</button>
            <button class="del_btn">Delete</button>
        `;
      voicemailsDiv.appendChild(voicemailElement);
    });
  </script>
</html>

Póngalo a prueba

Para poner en marcha su servidor, ejecute node index.js en tu terminal desde la raíz de tu directorio, y asegúrate de que ngrok se está ejecutando.

Si llamas al número de teléfono asociado con tu aplicación de Vonage, escucharás el saludo que proporcionaste con las NCCO. Una vez que grabes tu mensaje, debería aparecer en tu página HTML en localhost:3000.

Conclusión

Ha creado un sistema de buzón de voz que permite a los usuarios dejar mensajes en una página web. Aunque la funcionalidad actual no se extiende a la eliminación de archivos del lado del servidor, abordar esta cuestión sería una mejora valiosa.

Chatea con nosotros en nuestra Slack de la comunidad de desarrolladores de Vonage o envíanos un mensaje a X.

Compartir:

https://a.storyblok.com/f/270183/400x400/3f6b0c045f/amanda-cavallaro.png
Amanda CavallaroDefensor del Desarrollador