
Compartilhar:
Naomi Pentrel is a Software Engineer with a passion for organizing and attending hackathons. She has worked at companies such as Google, Microsoft, and Palantir. In her free time, she occasionally blogs about her side projects.
Crie um “Babel Fish” com o Nexmo e a API de fala do Microsoft Translator
Tempo de leitura: 12 minutos
Se você esteve na internet nos últimos meses, é bem provável que tenha visto os Pixel Buds do Google com tradução em tempo real. Uma tecnologia bem parecida com o peixe de Babel em O Guia do Mochileiro das Galáxias , capaz de traduzir qualquer fala de seres sencientes para quem os usa, permitindo assim que se comuniquem com praticamente qualquer ser. É claro que os Google Pixel Buds têm um preço — então, por que não construir os nossos próprios?! Foi isso que Danielle e eu pensamos na última hackference. Criamos um “peixe Babel” da Nexmo que permite que duas pessoas conversem ao telefone, sendo que cada uma ouve uma versão traduzida do que a outra está dizendo.
Babelfish
Nesta postagem do blog, vamos explicar passo a passo como funciona o sistema Babel Fish, começando pela instalação e configuração necessárias. Em seguida, vamos configurar um número da Nexmo para atender chamadas recebidas. Em seguida, implementaremos um servidor em Python que receberá a fala por meio de um WebSocket e encaminhará a fala recebida do número da Nexmo para a API de Fala do Microsoft Translator. Usaremos a API de Fala do Translator para realizar a transcrição e a tradução. Além disso, implementaremos uma lógica para gerenciar um diálogo bidirecional e para instruir o número do Nexmo a reproduzir as traduções. Para facilitar a implementação, ambas as partes deverão ligar para o número do Nexmo do nosso serviço. Abaixo, você pode ver um diagrama geral do sistema que mostra como uma instância de fala de qualquer um dos lados é processada. Observe que, ao longo deste tutorial, usarei o exemplo de uma conversa em alemão e inglês britânico.

Se você preferir apenas ver o código, ele está disponível no GitHub aqui.
Pré-requisitos
Você precisará ter tanto o Python 2.x ou 3.x quanto o software de tunelamento HTTP ngrok para poder acompanhar o passo a passo. Listaremos todos os comandos necessários para instalar o restante à medida que você for avançando.
Introdução
Configure seu ambiente
Vamos começar nossa solução “faça você mesmo” do Babel Fish configurando um ambiente virtual para este projeto usando Virtualenv. O Virtualenv nos permite isolar as dependências deste projeto das dos nossos outros projetos. Vá em frente e crie um diretório para este projeto e copie a lista de dependências a seguir em um arquivo no diretório do seu projeto chamado requirements.txt:
nexmo
tornado>=4.4.2
requests>=2.12.4
Para criar e ativar seu ambiente virtual, execute os seguintes comandos no terminal:
virtualenv venv # sets up the environment
source venv/bin/activate # activates the environment
pip install -r requirement.txt # installs our dependencies
# if you are running python3 please run the following instead
pip3 install -r requirement.txtNeste momento, inicie o ngrok em uma janela de terminal separada, executando o comando abaixo. O ngrok nos permitirá expor nosso localhost na porta 5000 para solicitações recebidas. Você precisará manter o ngrok em execução em segundo plano para que isso funcione. Você pode ler mais sobre como conectar o ngrok ao Nexmo aqui.
ngrok http 5000Depois de executar o comando acima, seu terminal deverá ficar parecido com a captura de tela abaixo. Você precisará da URL de redirecionamento ao configurar seu aplicativo Nexmo e seu número nas próximas etapas.

Criar uma aplicação Nexmo
Acesse suas aplicações e adicione uma nova aplicação. Use a URL de encaminhamento do Ngrok tanto para a URL do Evento quanto para a URL de Resposta, adicionando /event como caminho para a URL de evento (por exemplo, http://016a0331.ngrok.io/event) e /ncco para a URL de resposta (por exemplo, http://016a0331.ngrok.io/ncco). Configuraremos esses endpoints mais tarde. Gere um par de chaves pública/privada pela interface do usuário e salve a chave no seu computador.

A última etapa da configuração do número é vincular o número que você adquiriu anteriormente ao seu aplicativo. Use o painel do aplicativo para vincular o número.

Obter chaves para a API de Reconhecimento de Fala do Microsoft Translator
O outro serviço que precisaremos configurar é a API de Reconhecimento de Fala do Microsoft Translator. Cadastre-se para obter um account gratuito do Microsoft Azure em azure.com e, em seguida, acesse portal.azure.com e crie um recurso da API de Reconhecimento de Fala do Translator. Você precisará da chave gerada para a próxima etapa.

Gerenciar segredos e configurações
Agora que já temos nosso número da Nexmo e nossa chave da API do Translator Speech, tudo o que precisamos fazer é criar um arquivo de segredos e um arquivo de configuração com todos esses detalhes importantes, para que não precisemos ficar digitando-os repetidamente e possamos gerenciá-los separadamente. Salve o conteúdo abaixo na secrets.py na pasta do seu projeto e substitua os valores de preenchimento por seus próprios valores.
# Replace the below values with your values
# Your API key and secret can be found here ${CUSTOMER_DASHBOARD_URL}/getting-started-guide
NEXMO_API_KEY = "<your-api-key>"
NEXMO_API_SECRET = "<your-api-secret>"
# Your nexmo number
NEXMO_NUMBER = "+447512345678"
# This is found on your Nexmo application’s dashboard
NEXMO_APPLICATION_ID = "<nexmo-application-id>"
# This is the private key you downloaded when setting up your application
NEXMO_PRIVATE_KEY = '''-----BEGIN PRIVATE KEY-----
<your-private-key>
cobranding_allowed: false
-----END PRIVATE KEY-----'''
# You will have to sign up for a free Microsoft account to use the Microsoft Translator Speech API: http://docs.microsofttranslator.com/speech-translate.html
MICROSOFT_TRANSLATION_SPEECH_CLIENT_SECRET = "<your-api-key>"
Em seguida, salve o código abaixo na config.py na pasta do seu projeto e substitua novamente os valores dos espaços reservados pelos seus. Observe que você pode escolher outros idiomas além dos listados abaixo. Você também pode alterá-los a qualquer momento posteriormente.
HOSTNAME = '<your-value>.ngrok.io'
# Replace the variable assignment with your number in the same format
CALLER = '447812345678'
# Replace the variable assignment with your languages
LANGUAGE1 = 'de-DE'
# Replace the variable assignments with the respective name for your language. They can be found here:
# https://developer.nexmo.com/api/voice/ncco#voice-names
VOICE1 = 'Marlene'
# the other person's language and voice
LANGUAGE2 = 'en-US'
VOICE2 = 'Kimberly'
Etapas do tutorial
A seguir, vamos primeiro explicar como realizar a autenticação na API de Reconhecimento de Fala do Translator. Em seguida, configuraremos nosso servidor web Tornado usando um modelo fornecido. Depois disso, implementaremos o CallHandler, o EventHandler, e o WSHandler. O CallHandler cuidará das chamadas recebidas no número da Nexmo para nós. Além disso, o EventHandler será usado para lidar com eventos enviados pela Nexmo, como o início ou o término de uma chamada. A cada evento, a Nexmo envia informações sobre quem iniciou ou encerrou a chamada. Usaremos essas informações para armazenar quem está participando de uma chamada específica. O WSHandler , por sua vez, será usado para abrir o WebSocket por meio do qual o Nexmo e nosso servidor Python se comunicarão. O servidor Python criará trechos de áudio e os enviará para a API de Fala do Translator. O manipulador utilizará as informações que o EventHandler reúne para rotear as mensagens corretamente. Cada seção a seguir explicará esses Concepts com mais detalhes e mostrará a respectiva implementação.
Autenticar-se com a API de Reconhecimento de Fala do Microsoft Translator
Para usar a API de Fala do Translator, precisamos obter um token, ao qual chamamos de MICROSOFT_TRANSLATION_SPEECH_CLIENT_SECRET. Felizmente, a Microsoft oferece uma biblioteca Python AzureAuthClient , que usaremos sem alterações. Copie o código abaixo e salve-o em um arquivo chamado azure_auth_client.py no diretório do seu projeto.
"""
Code example for getting a A from the Azure Platform.
Visit http://docs.microsofttranslator.com/oauth-token.html to view the API reference
for Microsoft Azure Cognitive Services authentication service.
"""
from datetime import timedelta
from datetime import datetime
import requests
class AzureAuthClient(object):
"""
Provides a client for obtaining an OAuth token from the authentication service
for Microsoft Translator in Azure Cognitive Services.
"""
def __init__(self, client_secret):
"""
:param client_secret: Client secret.
"""
self.client_secret = client_secret
# token field is used to store the last token obtained from the token service
# the cached token is re-used until the time specified in reuse_token_until.
self.token = None
self.reuse_token_until = None
def get_access_token(self):
'''
Returns an access token for the specified subscription.
This method uses a cache to limit the number of requests to the token service.
A fresh token can be re-used during its lifetime of 10 minutes. After a successful
request to the token service, this method caches the access token. Subsequent
invocations of the method return the cached token for the next 5 minutes. After
5 minutes, a new token is fetched from the token service and the cache is updated.
'''
if (self.token is None) or (datetime.utcnow() > self.reuse_token_until):
token_service_url = 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken'
request_headers = {'Ocp-Apim-Subscription-Key': self.client_secret}
response = requests.post(token_service_url, headers=request_headers)
response.raise_for_status()
self.token = response.content
self.reuse_token_until = datetime.utcnow() + timedelta(minutes=5)
return self.token
Criar um servidor
O protocolo de comunicação entre computadores WebSockets permite que tenhamos um canal de comunicação bidirecional por meio de uma única conexão TCP. A Voice API da Nexmo permite conectar chamadas telefônicas a esses pontos finais WebSocket. Usaremos a estrutura de servidor web Tornado, pois ela implementa o protocolo WebSocket para nós.
Se você tem acompanhado o passo a passo e nomeou todos os arquivos conforme descrito, pode começar com a configuração do servidor web Tornado abaixo. Este código lida com todas as nossas importações, configura o cliente Nexmo e o cliente de autenticação do Azure e inicia um servidor na porta 5000. Observe que esse servidor ainda não faz nada útil. Ele possui três endpoints: ncco, event, e socket que chamam o CallHandler, EventHandler, e WSHandler respectivamente. Implementaremos os manipuladores nas seções a seguir.
Crie um arquivo chamado main.py no diretório do seu projeto e copie este código nele.
from string import Template
import json
import os
import requests
import struct
import StringIO
from tornado import httpserver, httpclient, ioloop, web, websocket, gen
from xml.etree import ElementTree
import nexmo
from azure_auth_client import AzureAuthClient
from config import HOSTNAME, CALLER, LANGUAGE1, VOICE1, LANGUAGE2, VOICE2
from secrets import NEXMO_APPLICATION_ID, NEXMO_PRIVATE_KEY, MICROSOFT_TRANSLATION_SPEECH_CLIENT_SECRET, NEXMO_NUMBER
nexmo_client = nexmo.Client(application_id=NEXMO_APPLICATION_ID, private_key=NEXMO_PRIVATE_KEY)
azure_auth_client = AzureAuthClient(MICROSOFT_TRANSLATION_SPEECH_CLIENT_SECRET)
conversation_id_by_phone_number = {}
call_id_by_conversation_id = {}
class CallHandler(web.RequestHandler):
@web.asynchronous
def get(self):
self.write("Hello world")
class EventHandler(web.RequestHandler):
@web.asynchronous
def post(self):
self.write("Hello world")
class WSHandler(websocket.WebSocketHandler):
def open(self):
print("WebSocket opened")
def on_message(self, message):
self.write_message(u"You said: " + message)
def on_close(self):
print("WebSocket closed")
def main():
application = web.Application([
(r"/event", EventHandler),
(r"/ncco", CallHandler),
(r"/socket", WSHandler),
])
http_server = httpserver.HTTPServer(application)
port = int(os.environ.get("PORT", 5000))
http_server.listen(port)
print("Running on port: " + str(port))
ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main() Implementar o CallHandler
Para conectar chamadas telefônicas a pontos de extremidade WebSocket, a Voice API da Nexmo utiliza um Nexmo Call Controle Objeto (NCCO) ou uma chamada de API. Quando alguém ligar para o seu número Nexmo, a Nexmo enviará uma solicitação GET para a URL de resposta que você forneceu ao configurar seu aplicativo de voz Nexmo. Direcionamos nosso aplicativo para o nosso servidor, que agora precisa responder a essa solicitação retornando um NCCO. Isso NCCO deve instruir a Nexmo a apresentar uma breve mensagem de boas-vindas ao chamador e, em seguida, conectá-lo ao WebSocket.
Diagram that shows the interactions between a user, Nexmo, and the web server. When the user calls the Nexmo number, Nexmo sends a GET request to the web server's /ncco endpoint. The web server responds with an NCCO that instructs Nexmo to open a socket with the web server.
Vá em frente e salve o seguinte NCCO em um arquivo chamado ncco.json no diretório do seu projeto. Ele contém um modelo que executará as ações necessárias. No entanto, inclui algumas variáveis de preenchimento ($hostname, $whoamie $cid), que precisaremos substituir mais tarde, quando o utilizarmos.
[
{
"action": "talk",
"text": "Please wait while we connect you."
},
{
"action": "connect",
"eventUrl": [
"http://$hostname/event"
],
"from": "12345",
"endpoint": [
{
"type": "websocket",
"uri" : "ws://$hostname/socket",
"content-type": "audio/l16;rate=16000",
"headers": {
"whoami": "$whoami",
"cid": "$cid"
}
}
]
}
]No modelo do servidor, a seção reproduzida a seguir define o mapeamento entre o /ncco ponto de extremidade e o CallHandler. Esse mapeamento garante que, quando o /ncco ponto de extremidade receber uma solicitação GET, o CallHandlermétodo get do seja executado pelo servidor.
application = web.Application([
(r"/event", EventHandler),
(r"/ncco", CallHandler),
(r"/socket", WSHandler),
])Quando o servidor executa o método, ele retorna um NCCO usando o código abaixo. Para começar, coletamos os dados da consulta (ou seja, a solicitação GET) em uma data variável. Também armazenamos o conversation_uuid para uso posterior. Nesse caso, há uma instrução de impressão para que você possa ver o conversation_uuid ao testar seu servidor. Na etapa seguinte, o código carrega o NCCO do ncco.json arquivo que criamos. Para completar o NCCO, substituímos as variáveis de espaço reservado ($hostname, $cide $whoami) pelos valores coletados da variável de dados. Após a substituição, estamos prontos para enviá-lo de volta ao Nexmo.
Substitua o CallHandler do modelo acima por este código:
class CallHandler(web.RequestHandler):
@web.asynchronous
def get(self):
data={}
data['hostname'] = HOSTNAME
data['whoami'] = self.get_query_argument('from')
data['cid'] = self.get_query_argument('conversation_uuid')
conversation_id_by_phone_number[self.get_query_argument('from')] = self.get_query_argument('conversation_uuid')
print(conversation_id_by_phone_number)
filein = open('ncco.json')
src = Template(filein.read())
filein.close()
ncco = json.loads(src.substitute(data))
self.write(json.dumps(ncco))
self.set_header("Content-Type", 'application/json; charset="utf-8"')
self.finish()Sempre que alguém ligar para o número da Nexmo, a Nexmo enviará uma solicitação GET para o nosso /ncco ponto de extremidade e o CallHandler este irá montar e enviar a NCCO. A Nexmo então executará as ações conforme descrito no NCCO. Nesse caso, isso significa que o chamador ouvirá “Aguarde enquanto conectamos sua ligação.”. Em seguida, a Nexmo tentará conectar a chamada ao socket . Isso também fornece à Nexmo o event ponto de extremidade a ser usado. Se você iniciar seu servidor agora executando python main.py na janela do seu terminal, você perceberá que ouvirá a mensagem, mas a chamada será encerrada logo em seguida. Isso ocorre porque ainda não implementamos o EventHandler nem o WSHandler. Vamos fazer isso agora!
Implementar o EventHandler
O EventHandler trata os eventos enviados pela Nexmo. Estamos interessados em todas as chamadas recebidas e, por isso, verificamos todas as solicitações recebidas para ver se o corpo da solicitação contém um direction e se essa direção é incoming. Se for, vamos armazenar o uuid e encerrar o contexto da solicitação. O call_id_by_conversation_id dicionário será usado para rotear mensagens entre os chamadores no WSHandler.
Substitua o EventHandler do modelo por este código:
class EventHandler(web.RequestHandler):
@web.asynchronous
def post(self):
body = json.loads(self.request.body)
if 'direction' in body and body['direction'] == 'inbound':
if 'uuid' in body and 'conversation_uuid' in body:
call_id_by_conversation_id[body['conversation_uuid']] = body['uuid']
self.content_type = 'text/plain'
self.write('ok')
self.finish() Implementar o WSHandler
O CallHandler e o EventHandler permitiram que nosso aplicativo estabelecesse a chamada. O WSHandler agora cuidará do fluxo de áudio da chamada. A fala do chamador principal será transcrita e traduzida pela Voice API do Translator, e o texto resultante será reproduzido por uma voz da Nexmo do outro lado da linha. A segunda pessoa poderá, assim, ouvir o chamador em um idioma que compreenda e, em seguida, responder. A API de Fala do Translator traduzirá a resposta, por sua vez, para que a primeira pessoa a ouça em seu idioma. Esse fluxo de trabalho é a parte que vamos implementar agora.
Quando a Voice API da Nexmo se conecta a um WebSocket, a Nexmo envia uma solicitação HTTP GET inicial para o endpoint. Nosso servidor responde com um código de estado HTTP 101 para alternar de protocolo, e, em seguida, o servidor se conecta à Nexmo usando TCP. Essa atualização da conexão é gerenciada pelo Tornado. Sempre que alguém liga para o nosso número da Nexmo, a Nexmo abre um WebSocket enquanto a chamada durar. Quando um WebSocket é aberto e, por fim, fechado, a estrutura Tornado chama o open e close abaixo. Não precisamos fazer nada em nenhum dos casos, mas exibiremos mensagens para que possamos acompanhar o que está acontecendo ao executarmos o servidor.
Agora que temos uma conexão aberta, a Nexmo enviará mensagens que serão processadas pelo on_message método. A primeira mensagem que receberemos da Nexmo será um texto simples com metadados. Ao receber essa mensagem, definiremos a whoami propriedade do WSHandler para podermos identificar quem está falando. Em seguida, criaremos um cabeçalho Wave que enviaremos à API de Fala do Translator. Para enviar mensagens à API de Fala do Translator, criaremos um translator_future. Dependendo do chamador, ou seja, da pessoa de quem a mensagem vem, vamos definir a translator_future com as respectivas variáveis de idioma, para que a API saiba de qual idioma traduzir para qual outro idioma.
Um translator_future é outro WebSocket que se conecta à API do Speech Translator. Nós o usamos para repassar as mensagens que recebemos da Voice API da Nexmo. Após sua criação, o translator_future é armazenado na variável ws e é usado para enviar o cabeçalho “wave” que criamos anteriormente. Cada mensagem subsequente da Nexmo será uma mensagem binária. Essas mensagens binárias são repassadas à API do Translator Speech por meio do translator_future que processa o áudio e retorna a tradução transcrita.
Ao inicializarmos o translator_future, definimos que, quando a API de Fala do Translator tiver processado nossa mensagem, ela deve chamar o método speech_to_translation_completed. Esse método, ao receber uma mensagem, verificará se ela não está vazia e, em seguida, reproduzirá a mensagem na voz do idioma do destinatário da mensagem. Ele reproduzirá a mensagem apenas para o outro interlocutor, não para a pessoa que falou inicialmente. Além disso, exibiremos a tradução no terminal.
Substitua o WSHandler do modelo por este código:
class WSHandler(websocket.WebSocketHandler):
whoami = None
def open(self):
print("Websocket Call Connected")
def translator_future(self, translate_from, translate_to):
uri = "wss://dev.microsofttranslator.com/speech/translate?from={0}&to={1}&api-version=1.0".format(translate_from[:2], translate_to)
request = httpclient.HTTPRequest(uri, headers={
'Authorization': 'Bearer ' + azure_auth_client.get_access_token(),
})
return websocket.websocket_connect(request, on_message_callback=self.speech_to_translation_completed)
def speech_to_translation_completed(self, new_message):
if new_message == None:
print("Got None Message")
return
msg = json.loads(new_message)
if msg['translation'] != '':
print("Translated: " + "'" + msg['recognition'] + "' -> '" + msg['translation'] + "'")
for key, value in conversation_id_by_phone_number.iteritems():
if key != self.whoami and value != None:
if self.whoami == CALLER:
speak(call_id_by_conversation_id[value], msg['translation'], VOICE2)
else:
speak(call_id_by_conversation_id[value], msg['translation'], VOICE1)
@gen.coroutine
def on_message(self, message):
if type(message) == str:
ws = yield self.ws_future
ws.write_message(message, binary=True)
else:
message = json.loads(message)
self.whoami = message['whoami']
print("Sending wav header")
header = make_wave_header(16000)
if self.whoami == CALLER:
self.ws_future = self.translator_future(LANGUAGE1, LANGUAGE2)
else:
self.ws_future = self.translator_future(LANGUAGE2, LANGUAGE1)
ws = yield self.ws_future
ws.write_message(header, binary=True)
@gen.coroutine
def on_close(self):
print("Websocket Call Disconnected")
No código acima, usamos uma função chamada make_wave_header para criar o cabeçalho que a API do Translator Speech espera. O código usado para criar um cabeçalho WAV foi copiado do projeto Python-Speech-Translate e está reproduzido abaixo.
Copie a make_wave_header função no final do seu main.py arquivo:
def make_wave_header(frame_rate):
"""
Generate WAV header that precedes actual audio data sent to the speech translation service.
:param frame_rate: Sampling frequency (8000 for 8kHz or 16000 for 16kHz).
:return: binary string
"""
if frame_rate not in [8000, 16000]:
raise ValueError("Sampling frequency, frame_rate, should be 8000 or 16000.")
nchannels = 1
bytes_per_sample = 2
output = StringIO.StringIO()
output.write('RIFF')
output.write(struct.pack('<L', 0))
output.write('WAVE')
output.write('fmt ')
output.write(struct.pack('<L', 18))
output.write(struct.pack('<H', 0x0001))
output.write(struct.pack('<H', nchannels))
output.write(struct.pack('<L', frame_rate))
output.write(struct.pack('<L', frame_rate * nchannels * bytes_per_sample))
output.write(struct.pack('<H', nchannels * bytes_per_sample))
output.write(struct.pack('<H', bytes_per_sample * 8))
output.write(struct.pack('<H', 0))
output.write('data')
output.write(struct.pack('<L', 0))
data = output.getvalue()
output.close()
return data
Por fim, a speak função usada acima é um simples wrapper em torno do nexmo_client método send_speech. Como você pode ver abaixo, ela exibirá algumas informações que podem ser úteis ao executar o código e, em seguida, usará a API da Nexmo para instruir a Nexmo a pronunciar um determinado text com um determinado voice_name. Copie a speak função abaixo no final do seu main.py arquivo.
def speak(uuid, text, vn):
print("speaking to: " + uuid + " " + text)
response = nexmo_client.send_speech(uuid, text=text, voice_name=vn)
print(response) Conclusão
Se você seguiu o passo a passo, já criou com sucesso seu próprio “Babel Fish”! Caso não tenha seguido, você pode encontrar o código final aqui. Execute-o digitando python main.py no seu terminal. Agora junte-se a outra pessoa (ou use dois celulares) e ligue para o seu número Nexmo de duas linhas diferentes. Você deve ouvir sua mensagem de boas-vindas e, em seguida, poderá conversar com a outra pessoa nos dois idiomas escolhidos. Vamos recapitular: Começamos configurando nosso ambiente, bem como nosso aplicativo Nexmo e a API de Fala do Microsoft Translator. Em seguida, criamos nosso servidor web Tornado, que nos permitiu usar WebSockets para lidar com chamadas de voz e encaminhar a fala da chamada para a API de Fala do Translator. A API, então, traduz e transcreve a fala para nós. Ao receber o resultado, falamos a mensagem no novo idioma. Nosso serviço lida com chamadas bidirecionais graças à nossa lógica de roteamento, o que significa que, após conectar dois interlocutores, ele traduz a fala de cada um antes de retransmití-la, permitindo assim que eles se comuniquem nos idiomas escolhidos. E pronto! Nosso “peixe de Babel” em funcionamento! Infelizmente, nosso “peixe de Babel” feito por nós mesmos não parece tão cativante quanto o do filme, mas é uma alternativa que funciona. Se você tiver alguma dúvida, entre em contato pelo @naomi_pen ou me encontre no naomi.codes.
E agora, para onde vamos?
Se você estiver interessado em aprofundar esse assunto, por que não implementar uma lógica que permita aos usuários escolherem o idioma no início da ligação? Essa lógica também poderia eliminar a necessidade de codificar manualmente nosso número de telefone principal. Como projeto divertido, você também poderia explorar a possibilidade de fazer isso funcionar para teleconferências e criar transcrições para cada ligação. Por fim, imagino que você queira trabalhar na segurança do seu serviço e impedir que pessoas aleatórias liguem para ele. Você poderia fazer isso permitindo que apenas um determinado número (ou vários) use seu serviço e criando uma lógica para iniciar uma segunda etapa da chamada a partir da própria chamada, o que permitiria convidar outros usuários sem conceder a eles o privilégio de usar seu serviço “Babel Fish”. Adoraria saber o que você criou no Twitter @naomi_pen!