https://a.storyblok.com/f/270183/132969/03926c8e7b/social_call-recording_golang_1200x600.png

Baixar gravações da Voice API da Vonage com Golang

Publicado em May 5, 2021

Tempo de leitura: 2 minutos

Nós adoramos a Voice API e todas as coisas legais que você pode fazer com ela. Hoje vou mostrar a vocês um aplicativo em Golang que estou usando para baixar as gravações das chamadas.

Quando faço uma ligação e a gravo, a API envia um webhook ao final da ligação com todas as informações sobre a gravação. Meu aplicativo recebe esse webhook e baixa o arquivo da gravação por conta própria.

Configurar a URL de gravação

Quando eu adiciono um ação de registro a um NCCO da Voice API, posso definir o eventUrl para receber a notificação da gravação. Esse webhook de entrada chega quando a chamada é encerrada e inclui informações sobre a gravação e um link para baixá-la.

Minha ação de registro fica assim:

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

Há duas coisas a serem observadas aqui:

  1. Isso eventUrl na verdade é um array (isso me confunde mais ou menos uma vez a cada três!)

  2. Estou usando o Ngrok para disponibilizar uma URL pública para minha plataforma de desenvolvimento local. Você pode ler sobre o Ngrok no Portal do Desenvolvedor , caso queira saber mais sobre como usar essa abordagem.

Receber o Webhook

O webhook recebido está no formato JSON e tem uma aparência mais ou menos assim:

{
    "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"
}

No meu código em Golang, vou processar uma solicitação recebida para /recording e baixar o arquivo, salvando-o no disco.

Para se autenticar, você precisará de um (JWT)[/Concepts/Guides/Authentication#json-web-tokens-jwt), que pode ser gerado programaticamente ou pela linha de comando. Este exemplo espera que ele esteja em uma variável de ambiente 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)
	}
}

O ponto de entrada aqui é a main() função no final do exemplo de código. Ela registra uma /recording rota e, em seguida, inicia um servidor web rodando na porta 8080.

Quando executo o código pela primeira vez com go run main.go, não acontece quase nada! Isso porque o servidor web está em execução e aguardando a chegada de uma solicitação. Quando ela chega, se a rota corresponder, ele chama a downloadRecording() função e a ação começa!

Este código primeiro analisa os dados recebidos; trata-se de uma POST solicitação com um corpo em JSON, então defini uma estrutura na qual pudesse decodificar os dados. Assim que obtivermos a URL, o programa a exibe.

Baixe e salve a gravação

Se tudo correu bem até aqui, podemos prosseguir e adicionar as etapas para baixar a gravação e salvar o arquivo. Quando estiver concluída, a função completa downloadRecording() função fica assim:

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"))
}

O download de gravações exige credenciais; portanto, este código mostra como adicionar um JWT à solicitação antes de enviá-la.

Por fim, a resposta à solicitação de download é gravada em um arquivo local. Usei o ID da gravação como nome do arquivo, pois sei que ele será único; se fizer mais sentido nomear os arquivos com carimbos de data e hora ou algo semelhante, você certamente poderá fazer isso em seu próprio aplicativo.

Como lidar com gravações em suas próprias Applications

O exemplo de hoje é básico, mas mostra alguns elementos-chave do trabalho com a Voice API: receber webhooks em resposta a eventos e enviar credenciais para baixar as gravações. Se você estiver usando algo semelhante em seus próprios aplicativos ou se estiver desenvolvendo algo com base neste exemplo, conte para a gente! Sempre gostamos de saber no que vocês estão trabalhando.

Compartilhar:

https://a.storyblok.com/f/270183/250x250/e3d3b71060/lornajane.png
Lorna MitchellEx-funcionários da Vonage

Lorna é engenheira de software e tem um vício incurável por escrever em blogs. Ela tenta domar as palavras e o código na mesma medida.