https://d226lax1qjow5r.cloudfront.net/blog/blogposts/download-vonage-voice-api-recordings-with-golang/Social_Call-Recording_Golang_1200x600.png

Descargar grabaciones de Voice API de Vonage con Golang

Publicado el May 5, 2021

Tiempo de lectura: 2 minutos

Nos encanta la Voice API y todas las cosas divertidas que puedes hacer con ella. Hoy os voy a mostrar una aplicación Golang que estoy usando para descargar las grabaciones de las llamadas.

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.

Cuando hago una llamada y la grabo, la API envía un webhook al final de la llamada con toda la información sobre la grabación. Mi aplicación recibe este webhook y descarga ella misma el archivo de grabación.

Configurar la URL de grabación

Cuando añado una acción de grabación a una OCN de la Voice API, puedo configurar la acción eventUrl para recibir la notificación de grabación. Este webhook entrante llega cuando finaliza la llamada, e incluye información sobre la grabación y un enlace para descargarla.

Mi acción de registro tiene este aspecto:

{
  "action": "record",
  "eventUrl": ["https://76b239af.ngrok.io/recording"]
}

Hay que tener en cuenta dos cosas:

  1. Este eventUrl es en realidad una matriz (¡me pilla una de cada tres veces!)

  2. Estoy usando Ngrok para proporcionar una URL pública a mi plataforma de desarrollo local. Puedes leer sobre Ngrok en el Portal del Desarrollador si desea obtener más información sobre el uso de este enfoque.

Recibir el Webhook

El webhook entrante está formateado en JSON y tiene el siguiente aspecto:

{
    "start_time": "2020-05-06T13:34:21Z",
    "recording_url": "https://api.nexmo.com/v1/files/6d29bd8d-e6ff-45b9-9379-2843fe7b37fe",
    "size": 15822,
    "recording_uuid": "692100cb-e4ef-4f18-ab90-2a09573aecb5",
    "end_time": "2020-05-06T13:34:25Z",
    "conversation_uuid": "CON-55970ffd-a6b7-4d18-b3b6-088c03ea49f1",
    "timestamp": "2020-05-06T13:34:25.771Z"
}

En mi código Golang, voy a manejar una petición entrante a /recording y descargar el archivo, guardándolo en el disco.

Para autenticarse, necesitará un (JWT)[/concepts/guides/authentication#json-web-tokens-jwt) que puede generar mediante programación o desde la línea de comandos. Este ejemplo espera que esté en una variable de entorno JWT.

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
)

type RecordingWebhook struct {
	StartTime        string  `json:"start_time"`
	RecordingURL     string  `json:"recording_url"`
	Size             float64 `json:"size"`
	RecordingUUID    string  `json:"recording_uuid"`
	EndTime          string  `json:"end_time"`
	ConversationUUID string  `json:"conversation_uuid"`
	Timestamp        string  `json:"timestamp"`
}

func downloadRecording(w http.ResponseWriter, r *http.Request) {
	jwt := os.Getenv("JWT")

	// Get data from incoming webhook
	data := RecordingWebhook{}
	err := json.NewDecoder(r.Body).Decode(&data)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	fmt.Println("Recording URL: " + data.RecordingURL)
}

func main() {
	http.HandleFunc("/recording", downloadRecording)
	if err := http.ListenAndServe(":8080", nil); err != nil {
		panic(err)
	}
}

El punto de entrada es la función main() al final del ejemplo de código. Registra una /recording y luego inicia un servidor web que se ejecuta en el puerto 8080.

Cuando ejecuto por primera vez el código con go run main.gono pasa gran cosa. Eso es porque el servidor web está funcionando y esperando a que llegue una petición. Cuando lo hace, si la ruta coincide entonces llama a la función downloadRecording() y empieza lo interesante.

Este código primero analiza los datos entrantes; es una POST con un cuerpo JSON, así que definí una estructura para decodificar los datos. Una vez que tenemos la URL, el programa la emite.

Descargar y guardar la grabación

Si las cosas han ido bien hasta este punto, entonces podemos seguir adelante y añadir los pasos para descargar la grabación y guardar el archivo. Una vez completada, la función downloadRecording() completa tendrá este aspecto:

func downloadRecording(w http.ResponseWriter, r *http.Request) {
	jwt := os.Getenv("JWT")

	// Get data from incoming webhook
	data := RecordingWebhook{}
	err := json.NewDecoder(r.Body).Decode(&data)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	fmt.Println("Recording URL: " + data.RecordingURL)
	// prepare and download the recording, with auth
	req, err := http.NewRequest("GET", data.RecordingURL, nil)
	if err != nil {
		panic(err)
	}

	req.Header.Set("Authorization", "Bearer "+jwt)
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}

	defer resp.Body.Close()

	// now write to a local file
	filename := data.RecordingUUID + ".mp3"
	out, err := os.Create(filename)
	if err != nil {
		panic(err)
	}
	defer out.Close()

	_, fileErr := io.Copy(out, resp.Body)
	if fileErr != nil {
		panic(fileErr)
	}

	// Good! acknowledge it
	w.Write([]byte("OK"))
}

La descarga de grabaciones requiere credenciales, por lo que este código muestra cómo añadir un JWT a la solicitud antes de enviarla.

Por último, la respuesta a la solicitud de descarga se escribe en un archivo local. He utilizado el ID de la grabación como nombre del archivo, ya que sé que será único; si tiene más sentido nombrar con marcas de tiempo o alguna otra cosa, entonces definitivamente podría hacerlo en su propia aplicación.

Manejo de grabaciones en sus propias Applications

El ejemplo de hoy es básico, pero muestra algunos ingredientes clave del trabajo con Voice API: la recepción de webhooks en respuesta a eventos y el envío de credenciales para descargar las grabaciones. Si utilizas algo similar en tus propias aplicaciones o te basas en este ejemplo, ¡háznoslo saber! Siempre nos gusta saber en qué estáis trabajando.

Compartir:

https://a.storyblok.com/f/270183/250x250/e3d3b71060/lornajane.png
Lorna MitchellAntiguos alumnos de Vonage

Lorna es ingeniera de software con un incurable hábito bloguero. Intenta domar las palabras y el código a partes iguales.