https://a.storyblok.com/f/270183/202840/bed9645a26/stream-audio-into-a-phone-call-with-ruby.png

Reproduzir áudio em streaming durante uma ligação telefônica com Ruby

Publicado em May 12, 2021

Tempo de leitura: 9 minutos

Nesta postagem, vamos abordar como transmitir um arquivo de áudio durante uma chamada telefônica em andamento. Existem muitos casos de uso para a transmissão de arquivos de áudio durante chamadas, e com a Voice API da Vonage e a gem Ruby da Vonage, esse é um processo relativamente simples. Se você quiser compartilhar uma música com alguém pelo telefone ou um trecho de uma reunião de trabalho, é possível fazer isso com apenas algumas linhas de código em Ruby e com a Vonage.

O código-fonte desta postagem do blog está disponível no GitHub.

Pré-requisitos

Para acompanhar este post, você vai precisar de:

Configure sua Account e seu aplicativo da Vonage

Vamos começar comprando um número de telefone que possamos usar para testes. Usaremos a CLI da Vonage para comprar o número.

vonage numbers:buy NUMBER COUNTRYCODE

Aqui, NUMBER representa o número que você deseja comprar, e COUNTRYCODE o código do país desse número.

Se você ainda não sabe qual número deseja comprar, pode primeiro pesquisar um número em um determinado país desta forma (aqui estamos pesquisando números nos EUA usando o US código do país):

vonage numbers:search US

Vá em frente e anote o número de telefone que você acabou de comprar. Vamos usá-lo daqui a pouco no nosso código.

Também usaremos a CLI da Vonage para criar um novo aplicativo. Precisamos criar um aplicativo para usar a Voice API.

vonage apps:create "Test Application 1" --voice_answer_urlhttp://example.com/answer --voice_event_url=http://example.com/event

Ao executar esse comando, criamos agora um novo aplicativo chamado “Test Application 1” e definimos três parâmetros:

  • answer_url: Onde nosso aplicativo fornece o Objeto de Controle de Chamadas da Vonage (NCCO) que controla a chamada

  • event_url: Onde a Vonage envia as informações do evento de forma assíncrona quando o call_status ocorrem alterações

Vamos redefinir tanto o answer_url e o event_url em nosso código. É importante observar que eles precisam estar acessíveis externamente para que a plataforma Vonage possa acessá-los. Para nossa instalação local, podemos usar o ngrok para tornar nosso servidor local disponível externamente. Você pode encontrar mais informações sobre como usar o Vonage com o ngrok nesta esta postagem do blog.

Ao executar o vonage apps:create comando também exibe um ID do aplicativo criado. Usaremos esse ID daqui a pouco em nosso código, juntamente com o novo número de telefone que obtivemos.

Configurando nossas credenciais

Neste momento, já temos as informações necessárias para criar nosso aplicativo. Vamos criar um servidor web Sinatra que atenda a quatro rotas, três GET solicitações e uma POST solicitação. As GET solicitações iniciam a ligação telefônica, fornecem as instruções do NCCO à plataforma da Vonage e transmitem um arquivo de silêncio para manter a ligação aberta. A POST solicitação transmite o áudio para a chamada assim que ela for atendida.

Para acessar nossa conta da Vonage e nos autenticar, precisamos fornecer as credenciais corretas. É importante guardá-las com segurança e evitar incluí-las no controle de versão. Neste exemplo, vamos usar o dotenv gem para armazenar nossas credenciais como variáveis de ambiente e acessá-las em nosso código conforme necessário. Para isso, primeiro criamos um arquivo chamado .env e inserindo o seguinte nele:

VONAGE_API_KEY=
VONAGE_API_SECRET=
VONAGE_APPLICATION_ID=
VONAGE_APPLICATION_PRIVATE_KEY_PATH=private.key
VONAGE_TO_NUMBER=
VONAGE_NUMBER=

Seu VONAGE_API_KEY e VONAGE_API_SECRET foram fornecidos a você quando você se cadastrou para um Account da Vonage no início deste passo a passo. Você pode acessá-los novamente nas suas configurações da conta. Seu VONAGE_APPLICATION_ID é o que foi retornado a você quando criou um novo aplicativo com a CLI do Nexmo. Da mesma forma, seu VONAGE_APPLICATION_PRIVATE_KEY_PATH é o caminho do arquivo para o private.key arquivo criado automaticamente ao inicializar um novo aplicativo com a CLI. No nosso exemplo, é ./private.key. Seu VONAGE_NUMBER é o número de telefone que você adquiriu, e o VONAGE_TO_NUMBER é o número de telefone para o qual você deseja ligar.

Se você estiver enviando isso para o GitHub, certifique-se também de criar um .gitignore arquivo e adicione .env dentro dele para garantir que suas credenciais não sejam publicadas online acidentalmente.

Enviando áudio em streaming para uma chamada com Ruby

Vamos criar um novo arquivo chamado server.rb e vamos garantir que estamos importando as dependências necessárias e carregando nossas dotenv variáveis de ambiente:

require 'sinatra'
require 'vonage'
require 'dotenv'
require 'json'

Dotenv.load

A seguir, vamos inicializar uma nova instância do cliente Vonage utilizando essas credenciais e a gem Vonage.

client = Vonage::Client.new(
  api_key: ENV['VONAGE_API_KEY'],
  api_secret: ENV['VONAGE_API_SECRET'],
  application_id: ENV['VONAGE_APPLICATION_ID'],
  private_key: File.read(ENV['VONAGE_APPLICATION_PRIVATE_KEY_PATH'])
)

Neste momento, já temos uma instância de cliente Vonage com credenciais e nossa transmissão de áudio definida. O que ainda está faltando? A ligação telefônica, é claro!

Primeiro, vamos definir nossa ngrok URL acessível externamente que usaremos para disponibilizar nosso servidor à Vonage, a fim de receber nossas instruções de chamada e enviar atualizações de status de chamada de volta para ela. Depois de instalar ngrok, abra uma nova janela do console e execute ngrok http 4567 na linha de comando. Isso iniciará um novo ngrok servidor na porta 4567 que funciona em paralelo ao nosso servidor Sinatra, que também está rodando na porta 4567. Você verá um status exibido contendo a ngrok URL no parâmetro Forwarding parâmetro. Vá em frente e copie e cole essa URL na BASE_URL variável constante em server.rb.

BASE_URL = 'PASTE URL HERE'

Enquanto definimos nossas variáveis, vamos definir o caminho para o nosso arquivo de áudio em streaming e vamos defini-lo como uma CONSTANT variável.

AUDIO_URL = "#{BASE_URL}/voice_api_audio_streaming.mp3"

Agora podemos criar um caminho de URL para /new que, quando acessado, iniciará a ligação telefônica.

get '/new' do
  response = client.calls.create(
    to: [{ type: 'phone', number: ENV['VONAGE_NUMBER'] }],
    from: { type: 'phone', number: ENV['VONAGE_TO_NUMBER'] },
    answer_url: ["#{BASE_URL}/answer"],
    event_url: ["#{BASE_URL}/event"]
  )
  puts response.inspect
end

A get /new ação acima cria uma nova chamada telefônica com o to:, from:, answer_url: e event_url: parâmetros fornecidos.

O to: e from: parâmetros exigem tanto um type e um number. No nosso caso, o type valor para ambos é phone. O answer_url e event_url devem ser URLs acessíveis externamente, das quais a plataforma da Vonage possa receber instruções e para as quais possa enviar atualizações sobre o status das chamadas, respectivamente.

Assim que iniciamos a ligação, a Vonage acessa a answer_url caminho em busca de instruções de chamada. Precisamos criar essa ação também. A ação irá gerar e enviar as instruções no formato JSON. As instruções fornecem o action, o caminho da URL para um arquivo de áudio silencioso que será reproduzido em segundo plano, mantendo a conexão aberta, e um loop parâmetro, que definimos como 0.

get '/answer' do
    # Provide the Vonage Call Control Object (NCCO) as JSON to the Vonage Platform
    content_type :json
    [{ :action => 'stream', :streamUrl => ["#{BASE_URL}/stream/silent"], :loop => 0 }].to_json
end

Neste momento, precisamos criar mais um GET caminho para entregar o arquivo de áudio sem som que especificamos nas instruções do NCCO:

get '/stream/silent' do
    # Stream a silent file in the background to keep the call open
    send_file File.join(settings.public_folder, 'silence.mp3')
end

Por fim, também criamos um POST caminho para /event que recebe o status da chamada da plataforma Vonage e envia o áudio em streaming assim que ela for atendida. A ação analisa os dados recebidos e usa o status para determinar quando a chamada foi atendida. O status de uma chamada muda de started para ringing e, em seguida, answered e, finalmente, quando é desconectada, para completed. Nosso código reproduz o arquivo de áudio assim que a status atingir answered. Também recebemos o identificador exclusivo dessa chamada, o uuid, a partir dos dados recebidos, o que é necessário para que possamos inserir nosso áudio em streaming nessa chamada específica.

post '/event' do
  data = JSON.parse(request.body.read)
  response = client.calls.stream.start(data['uuid'], stream_url: [AUDIO_URL]) if data['status'] == 'answered'
  puts response.inspect
end

Então, com essa POST ação, concluímos a criação do nosso aplicativo. Agora, basta executar ruby server.rb na linha de comando para inicializar nosso servidor e garantir que o ngrok esteja inicializado, de modo que nosso servidor local fique acessível externamente. Feito isso, acesse http://localhost:4567 no seu navegador e você receberá a ligação. Ao atender a ligação, o áudio começará a ser transmitido.

Conclusão

Em aproximadamente 40 linhas de código, criamos um servidor web totalmente funcional, capaz de ligar para qualquer número de telefone e reproduzir áudio em streaming durante a chamada. Há muito mais que pode ser feito com a Voice API da Vonage, e você pode explorá-la por completo na Plataforma de Desenvolvedores da Vonage.

Se você tiver alguma dúvida sobre esta publicação, sinta-se à vontade para enviar um e-mail para devrel@nexmo.com ou participe do canal da comunidade da Vonage no Slack, onde estamos à sua disposição, prontos para ajudar.

Compartilhar:

https://a.storyblok.com/f/270183/384x384/e5480d2945/ben-greenberg.png
Ben GreenbergEx-funcionários da Vonage

Ben é um desenvolvedor que mudou de carreira, tendo atuado anteriormente por uma década nas áreas de educação de adultos, organização comunitária e gestão de organizações sem fins lucrativos. Ele trabalhou como representante de desenvolvedores na Vonage. Escreve regularmente sobre a interseção entre desenvolvimento comunitário e tecnologia. Natural do sul da Califórnia e morador de longa data da cidade de Nova York, Ben reside atualmente perto de Tel Aviv, em Israel.