- 原文地址:Build a Babel Fish with Nexmo, and the Microsoft Translator Speech API
- 原文做者:Naomi Pentrel
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:Starrier
- 校對者:haoyuez
若是在過去的幾個月時間裏你關注過互聯網上的變化,那你就會注意到 Google 的即時翻譯 Pixel Buds。它是一個像給 Galaxy 的 Hitchhiker 指南中 Bable Fish 同樣的技術,能夠爲穿戴者翻譯任何可感知的語言並讓他們像虛擬人類同樣與穿戴者進行交流。但使用 Google 的 Pixel Buds 代價昂貴 —— 那麼咱們爲什麼不本身動手構建呢?這也是 Danielle 和我最近在 hackference 上所構想的。咱們想要去建立一個讓電話交流的雙方能夠根據本身所需,聽到彼此說話內容的翻譯版本的 Nexmo Babel Fish。html
來自給 Galaxy 的 Hitchhiker 的指南中的 Bable Fish 的圖片。前端
在這篇博客中,咱們將介紹搭建 Babel Fish 系統的步驟。首先咱們須要設置和配置環境。而後咱們會設置一個 Nexmo number 來處理調用。在此以後,咱們會搭建一個經過 WebSocket 接收語音,並將其從 Nexmo number 傳送到微軟語言翻譯 API 的 Python 服務器。咱們會使用語音翻譯 API 來處理轉錄和翻譯。在此基礎上,咱們將實現管理雙向對話的邏輯,並指示 Nexmo number 說出翻譯內容。爲了便於實現,雙方必須都調用咱們的 Nexmo number。你能夠參考下面的高級圖表,它展現了來自任何一方的語音實例是如何處理的。注意在本教程中,我會使用一個德語/英語的示例。python
該圖表展現了消息如何在系統中傳遞。一個德語調用者經過 Nexmo 發送一條德語消息給 Python 服務器。Python 服務器將德語音頻發送給微軟語音 API。語音 API 將英文翻譯做爲文本發送到 Python 服務器來響應請求。Python 服務器會向 Nexmo 發送請求,向英語調用者說出英語消息。此時英語調用者便會聽到翻譯後的英語信息。android
若是你只想看代碼,能夠在 Github 上找到。ios
你須要同時安裝 Python 2.x 或 3.x 和 HTTP 通道軟件 ngrok。咱們會列出你在安裝過程當中須要的全部命令。git
咱們從使用 Virtualenv 來爲此項目配置虛擬環境的 DIY Babel Fish 的解決方案開始。Virtualenv 容許咱們將此項目與其餘項目隔離。繼續爲此項目建立目錄,並將如下依賴列表複製到你項目目錄中命名爲 requirements.txt
的文件中:github
nexmo
tornado>=4.4.2
requests>=2.12.4
複製代碼
爲了建立並激活你的虛擬環境,請在終端運行如下命令:web
virtualenv venv # sets up the environment
source venv/bin/activate # activates the environment
pip install -r requirement.txt # installs our dependencies
# 若是你使用的是 Python 3,請使用如下命令
pip3 install -r requirement.txt
複製代碼
此時,經過在單獨打開一個終端的窗口中運行下列命令來啓動 ngrok。ngrok 容許咱們將本地 5000 端口暴露給外部請求。爲此,你須要讓 ngrok 在後臺保持正常運行。你能夠閱讀更多關於用 Nexmo 連接 ngrok 的信息。json
ngrok http 5000
複製代碼
一旦你運行上述命令,你的終端就會和下面的截圖相似。下一步,你須要在配置你的 Nexmo 應用程序和編號 時轉發 URL。後端
在終端運行的 ngrok 以及展現轉發來自 「016a0331.ngrok.io」 URL 的屏幕截圖。
使用咱們的翻譯服務須要一個 Nexmo Number。若是你尚未帳號,能夠在 dashboard.nexmo.com/sign-up 進行註冊,請前往 dashboard.nexmo.com/buy-numbers 購買一個具備語音功能的 Nexmo number。
該截屏展現了用戶如何使用 Nexmo 的購買編號菜單來購買 Nexmo number。用戶須要選擇國家和語音將做爲特徵,移動設備做爲類型,最後點擊搜索按鈕。而後點擊第一個數字邊的購買連接,即可確認購買。
進入你的應用程序,而後新增一個。對事件 URL 和應答 URL 使用 Ngrok 轉發 URL,添加 /event
做爲事件 URL(e.g. http://016a0331.ngrok.io/event
) 的路徑,對應答 URL(e.g. http://016a0331.ngrok.io/ncco
) 使用 /ncco
。咱們以後會設置這些端點。在你的電腦上經過用戶接口生成並存儲一對公鑰/私鑰對。
使用 Nexmo 應用程序目錄建立應用程序的用戶屏幕截圖。用戶點擊新增應用程序。在顯示的表單中,用戶輸入 Babelfish 做爲應用程序名,http://016a0331.ngrok.io/event
做爲事件的 URL,http://016a0331.ngrok.io/ncco
做爲應答 URL。而後用戶單擊 Generate public/private key pair
連接,在提示時保存密鑰,最後單擊建立應用程序。編號設置的最後一步是將你以前購買的編號連接到你的應用程序。使用應用程序儀表板來連接編號。
咱們須要設置的另外一個服務是微軟的語音服務 API。在 azure.com 上註冊一個免費的微軟 Azure 帳號,而後跳轉到 portal.azure.com,建立一個語音翻譯 API 資源。你須要它爲下一步生成的密鑰。
設置微軟語音翻譯 API 的用戶屏幕截圖。用戶在微軟 Azure 上的市場搜索中輸入語言翻譯。而後,用戶單擊出現的語音翻譯 API 選項,再單擊 API 概述屏幕上的建立按鈕。以後,用戶填寫資源的表單,使用 babelfish 做爲應用程序名,Pay-as-you-go 做爲訂閱,F0(10 小時的音頻輸入)做爲訂價層,babelfish —— 資源做爲資源組組名。選中用戶已經「閱讀並理解注意事項」的選框,並檢查添加到儀表板,用戶單擊建立並重定向到儀表板。部署完成後,用戶單擊已部署的資源,會顯示一個資源儀表板。在資源儀表板中,抓取用戶單擊的鍵並複製鍵 1。
咱們如今有了本身的 Nexmo number 和語音翻譯 API 密鑰。咱們如今要作的就是去設置一個包含全部這些重要細節的密碼和配置,這樣咱們就沒必要繼續編輯它們,能夠對它們進行單獨的管理。將下列內容存儲在你項目目錄的 secrets.py
中,而後用你的值來替換佔位符值。
# 用你的值替換下面的值
# 你的 API 密鑰和密碼能夠在這裏找到 https://dashboard.nexmo.com/getting-started-guide
NEXMO_API_KEY = "<your-api-key>"
NEXMO_API_SECRET = "<your-api-secret>"
# 你的 nexmo 編號
NEXMO_NUMBER = "+447512345678"
# 這能夠在你的 Nexmo 應用程序面板上找到
NEXMO_APPLICATION_ID = "<nexmo-application-id>"
# 這是設置你的應用程序時下載的私鑰
NEXMO_PRIVATE_KEY = '''-----BEGIN PRIVATE KEY----- <your-private-key> -----END PRIVATE KEY-----'''
# 你必須註冊一個免費的微軟帳號才能使用微軟語音翻譯 API:http://docs.microsofttranslator.com/speech-translate.html
MICROSOFT_TRANSLATION_SPEECH_CLIENT_SECRET = "<your-api-key>"
複製代碼
以後,在你的項目目錄中,在 config.py
中存儲如下內容,而後再用值替換佔位符值。注意,你也能夠選擇如下語言的其餘語言。你也能夠在以後的任意時間更改這些內容。
HOSTNAME = '<your-value>.ngrok.io'
# 用相同格式的數字替換變量賦值
CALLER = '447812345678'
# 用語言替換變量值
LANGUAGE1 = 'de-DE'
# 將變量賦值替換爲你的語言的相應名稱。能夠在這裏找到:
# https://developer.nexmo.com/api/voice/ncco#voice-names
VOICE1 = 'Marlene'
# 其餘語言和語音
LANGUAGE2 = 'en-US'
VOICE2 = 'Kimberly'
複製代碼
咱們將首先介紹如何使用語言翻譯 API 進行身份認證。而後咱們將使用提供的模版來設置咱們的 Tornado Web 服務器。以後,咱們要實現 CallHandler
、EventHandler
以及 WSHandler
。CallHandler
將爲咱們處理 Nexmo number 的調用。在此基礎上,EventHandler
將被用於處理 Nexmo 發送的事件,例如開始或完成的調用。在每一個事件中,Nexmo 都會發送關於啓動或完成調用的執行者的信息。咱們會使用這些信息來存儲特定調用中的人。WSHandler
同時被用來打開 WebSocket,Nexmo 和咱們的 Python 服務器經過它進行通訊。Python 服務器將建立音頻片斷並將其發送到語言翻譯 API。處理器將使用 EventHandler
收集信息來正確地路由。下面的部分會進一步解釋這些概念,並顯示相應的實現。
要使用語音翻譯 API,咱們須要一個名爲 MICROSOFT_TRANSLATION_SPEECH_CLIENT_SECRET
的 token。幸運的是,微軟提供了一個 Python AzureAuthClient,咱們會使用它,不會作任何更改。請將如下內容複製並保存到你的項目目錄中名爲 azure_auth_client.py
的文件中。
""" 從 Azure 平臺獲取示例 A 的代碼。 訪問 http://docs.microsofttranslator.com/oauth-token.html 來查看 微軟 Azure 認知服務的身份驗證服務 API 參考資料。 """
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
複製代碼
計算機通訊協議 WebSocket 容許咱們在一個 TCP 鏈接中擁有一個雙向通訊管道。Nexmo 的 Voice API 容許你將電話調用連接到這樣的 WebScoket 端點。咱們會使用 Tornado Web 服務器 web 框架來實現咱們的 WebSocket 協議。
若是你一直按照步驟來,並且全部的文件都如咱們所描述的建立,那麼你能夠從下面的 Tornado Web 服務器配置開始。這個代碼會處理全部的導入,配置 Nexmo 客戶端以及 azure auth 客戶端,並使用 5000 端口啓動服務器。注意這個服務器目前還未執行任何有用操做。它有 3 個端點:ncco
、event
和 socket
,它們會分別調用 CallHandler
、EventHandler
和 WSHandler
。咱們會在下面的部分實現處理器。
在你的項目文件夾中建立一個名爲 main.py
的文件,並將如下代碼複製進去。
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()
複製代碼
爲了將電話調用鏈接到 WebSocket 端點,Nexmo 的 Voice API 使用 Nexmo Call Control Object (NCCO) 或 API 調用。當有人調用你的 Nexmo number 時,Nexmo 就會向你在設置 Nexmo Voice 應用程序時提供的 URL 發起 GET 請求。咱們將應用程序指向服務器,服務器如今須要經過 NCCO
來響應這個請求。這個 NCCO
應該指示 Nexmo 給調用者發生一個簡短的歡迎消息,而後將調用者鏈接到 WebSocket。
顯示用戶、Nexmo 以及 web 服務器之間的交互圖。當用戶調用 Nexmo number 時,Nexmo 就會向 web 服務器/ncco 發送一個 GET 請求。web 服務器會指示 Nexmo 打開自身的 socket 來讓 NCCO 進行響應。
接着將如下的 NCCO
保存到你項目中名爲 ncco.json
的文件中。它包含執行請求動做所需的模版。可是,它也包括一些咱們之後使用時須要替換的佔位符變量($hostname
、$whoami
和 $cid
)。
[
{
"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"
}
}
]
}
]
複製代碼
在服務器模版中,如下再現部分設置了 /ncco
端點和 CallHandler
之間的映射。這個映射確保了在 /ncco
接收到 GET 請求時,CallHandler
的 get 方法由服務器執行。
application = web.Application([
(r"/event", EventHandler),
(r"/ncco", CallHandler),
(r"/socket", WSHandler),
])
複製代碼
當服務器執行方法時,它會使用如下代碼返回一個組裝的 NCCO
。首先,咱們從 data
變量中查詢(即 GET 請求)收集數據。咱們還存儲conversation_uuid
,以便以後的使用。在這種狀況下,有一個打印語句,能夠在你測試服務器時看見 conversation_uuid
。接下來,代碼從咱們建立的 ncco.json
文件中加載 NCCO
。爲了完成加載 NCCO
,咱們用從數據變量中手機的值替換佔位符變量($hostname
、$cid
和 $whoami
)。替換以後,咱們已經準備好將其返回給 Nexmo 了。
將上述模版中的 CallHandler
替換爲如下代碼:
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()
複製代碼
不管什麼時候,只要有人調用 Nexmo number,Nexmo 就會向咱們的 /ncco
端點發送 GET 請求,CallHandler
將組裝併發送 NCCO
。Nexmo 以後會執行 NCCO
中所設計的動做。在這種狀況下,這意味着調用者會聽到**「請稍侯,咱們正在與你創建鏈接。」**以後,Nexmo 會嘗試將調用鏈接到提供的 socket
端點。它也會提供了 Nexmo 要使用的 event
端點。若是你如今經過在終端窗口運行 python main.py
來啓動服務器,你就會發現你能聽到消息,但調用會在消息以後結束。這是由於咱們沒有實現 EventHandler
或 WSHandler
。咱們開始實現吧!
EventHandler
處理 Nexmo 發送的時間。咱們對任何調用都感興趣,所以咱們會檢查任何請求,以肯定其主體是否包含 direction
,以及該目錄是否爲 incoming
。若是是的話,咱們會存儲 uuid 並完成上下文請求。call_id_by_conversation_id
字典將用於 WSHandler
中調用方之間的消息路由。
用如下模版代碼替換 EventHandler
:
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()
複製代碼
CallHandler
和 EventHandler
容許咱們的應用程序來設置調用。WSHandler
如今將關注調用的音頻流。語音的主調用者將經過語音翻譯 API 轉錄並翻譯,結果文本將由另外一端的 Nexmo 語音說出。所以第二我的就能夠用他們所明白的語言來傾聽調用者的語音了,而後再做出響應。語言翻譯 API 將依次翻譯響應,以便第一格人能夠聽到他們的語言。這個工做流就是咱們要實現的部分。
當 Nexmo Voice API 鏈接 WebSocket 時,Nexmo 會向端點發送一個初始化的 HTTP GET 請求。咱們的服務器響應 HTTP 101 來切換協議,服務器以後會使用 TCP 鏈接 Nexmo。鏈接會經過 Tornado 來爲咱們處理升級。不管什麼時候有人調用 Nexmo number,Nexmo 都會在調用期間打開 WebSocket。當 WebSocket 被打開而且最後被關閉時,Tornado 框架將調用下面的 open
和 close
方法。咱們不須要在這兩種狀況下作任何事情,但咱們會打印消息,這樣咱們就能夠在服務器運行時跟蹤掌握所發生的一切。
如今咱們打開一個鏈接,Nexmo 會在 on_message
方法中處理咱們發送的信息。咱們從 Nexmo 收到第一個消息是帶有元數據的純文本。在收到這一消息後,咱們會設置 WSHandler
的 whoami
屬性,以便能識別發言人。以後,咱們會建立一個咱們發送到語音翻譯 API 的 wave 標題。爲了向語音翻譯 API 發送消息,咱們將建立一個 translator_future
。根據調用者的不一樣,例如,消息來源,咱們將使用相應的語言變量建立 translator_future
,以便 API 瞭解從哪一種語言翻譯成哪一種其餘的語言。
translator_future
是鏈接到語音翻譯 API 的另外一個 WebSocket。咱們使用它來傳遞咱們從 Nexmo Voice API 接收到的消息。在它建立以後,translator_future
被存儲在變量 ws
中,被用來發送咱們以前建立的 wave 標題。來自 Nexmo 的每一個後續消息都是二進制消息。這些二進制消息使用 translator_future
傳遞語音翻譯 API,它會處理音頻並返回轉錄的翻譯。
當咱們初始化 translator_future
時,咱們聲明語言翻譯 API 處理咱們時,它應該會調用 speech_to_translation_completed
方法。這個方法在接收到消息後,會檢查消息是否爲空,而後以消息接收語言語音出消息內容。它只會對其餘調用者說出消息,而不是最初說話的人。此外,咱們還會將翻譯內容打印到終端。
將模版中的 WSHandler
替換爲如下代碼:
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")
複製代碼
咱們使用名爲 make_wave_header
的函數來建立語言翻譯 API 所指望的標題。用於建立 WAV 頭的代碼複製於 Python-Speech-Translate 項目,以下簡介。
將 make_wave_header
函數複製到 main.py
文件末尾:
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
複製代碼
最後,上述說起的 speak
函數實際上是在 nexmo_client
方法 send_speech
周圍的進行的簡單封裝。正如你在下面所看到的那樣,它會打印打印一些在運行代碼時可能對你有用的信息,而後使用 Nexmo API 指示 Nexmo 使用給定的 voice_name
來播放 text
。
將下列 speak
函數複製到你的 main.py
文件末尾。
def speak(uuid, text, vn):
print("speaking to: " + uuid + " " + text)
response = nexmo_client.send_speech(uuid, text=text, voice_name=vn)
print(response)
複製代碼
若是你一直是按照步驟作的,那麼如今應該已經成功構建了本身的 Babel Fish!若是你沒有遵循步驟,也能夠在這裏找到源代碼。
經過在終端中輸入 python main.py
來運行。如今和別人合做(或者使用兩部手機)。從兩條線上撥打你的 Nexmo 號碼。你應該能夠聽到歡迎信息,而後就能夠用你選擇的兩種語音進行交流了。
咱們歸納一下:咱們首先配置了環境, Nexmo 應用程序和微軟的語言翻譯 API。而後構建了本身的 Tornado WebServer,它容許咱們使用 WebSocket 來處理語音調用,能夠將語音調用的語音傳遞給語音翻譯 API。API 爲咱們翻譯並轉錄語音。獲得結果後,咱們用新語言說出信息。咱們的路由邏輯使得咱們的服務能夠處理雙向調用,即咱們的服務在鏈接兩個調用者後,會先翻譯任何一我的的語音以確保他們彼此能夠選擇彼此須要的語言來進行溝通。
咱們如今作到了。咱們正在運行的 Babel Fish!恐怕咱們的 DIY Babel Fish 並不會像電影中的那樣可愛,但這是一種可行性的選擇。
若是你有任何疑問,請聯繫 @naomi_pen 或在 naomi.codes 上找我。
若是你對此有深刻了解的興趣,那麼爲何不實現容許用戶在調用開始時能夠選擇語言的邏輯呢?這種邏輯也可能會消除咱們硬編碼主要電話號碼的必要性。對於一個有趣的項目來講,你也能夠探索爲電話會議工做以及爲每一個電話建立記錄。最後,我設想你可能想要確保你本身服務的安全性以及不讓任何人都有機會調用你的服務。你能夠經過只容許某個號碼(或多個)來使用你的服務,或者使用第二階段的內部調用的邏輯來容許你邀請沒有給定 Bable Fish 服務權限的用戶。我很想知道你在 Twitter 上構建的內容 —— @naomi_pen!
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。