使用 Amazon Transcribe、Amazon Translate 和 Amazon Polly PlatoBlockchain 数据智能突破语言障碍。 垂直搜索。 哎。

使用 Amazon Transcribe、Amazon Translate 和 Amazon Polly 突破语言障碍

想象一下,外科医生无需人工翻译即可与全球患者进行视频通话。 如果一家初出茅庐的初创公司可以通过提供流畅、准确、多语言的客户支持和销售,轻松地将其产品跨越国界并进入新的地理市场,而无需现场人工翻译,那会怎样? 当您不再受语言束缚时,您的业务会发生什么?

今天,与说多种不同语言的国际团队和客户进行虚拟会议很常见。 无论是内部会议还是外部会议,在复杂的讨论中往往会迷失意义,并且您可能会遇到语言障碍,使您无法尽可能高效地工作。

在这篇文章中,您将学习如何使用三种完全托管的 AWS 服务 (亚马逊转录, 亚马逊翻译亚马逊波莉) 以产生近乎实时的语音到语音翻译器解决方案,可以将源说话者的现场语音输入快速翻译成口语、准确、翻译的目标语言,所有这些都具有零机器学习 (ML) 经验。

解决方案概述

我们的翻译器由三个完全托管的 AWS ML 服务组成,通过使用 适用于Python的AWS开发工具包(Boto3) 用于我们的文本翻译和文本到语音部分,以及用于音频输入转录的异步流 SDK。

Amazon Transcribe:将语音流式传输到文本

您在我们的堆栈中使用的第一个服务是 Amazon Transcribe,这是一种完全托管的语音到文本服务,它接收输入语音并将其转录为文本。 Amazon Transcribe 具有灵活的提取方法(批处理或流式传输),因为它接受存储的音频文件或流式音频数据。 在这篇文章中,您使用 适用于 Python 的异步 Amazon Transcribe 流式传输开发工具包,它使用 HTTP/2 流协议来流式传输实时音频并接收实时转录。

当我们第一次构建此原型时,Amazon Transcribe 流式摄取不支持自动语言检测,但到 2021 年 XNUMX 月不再支持这种情况。批处理和流式摄取现在都支持对所有人进行自动语言检测 支持的语言. 在这篇文章中,我们展示了如何通过使用流式自动语言检测,通过无缝的多语言无参数设计实现基于参数的解决方案。 在我们转录的语音片段作为文本返回后,您向 Amazon Translate 发送请求以翻译并在我们的 Amazon Transcribe 中返回结果 EventHandler 方法。

Amazon Translate:最先进的完全托管翻译 API

我们堆栈中的下一个是 Amazon Translate,这是一种神经机器翻译服务,可提供快速、高质量、经济实惠且可自定义的语言翻译。 截至 2022 年 75 月,Amazon Translate 支持跨 XNUMX 种语言的翻译,并不断进行新的语言对和改进。 Amazon Translate 使用托管在高度可扩展且具有弹性的 AWS 云架构上的深度学习模型,根据您的使用案例,以实时或批量方式快速提供准确的翻译。 使用 Amazon Translate 非常简单,不需要管理底层架构或 ML 技能。 Amazon Translate 具有多项功能,例如创建和使用 习惯术语 处理行业特定术语之间的映射。 有关 Amazon Translate 服务限制的更多信息,请参阅 准则和限制. 应用程序收到目标语言的翻译文本后,会将翻译后的文本发送到 Amazon Polly,以便立即播放翻译后的音频。

Amazon Polly:完全托管的文本转语音 API

最后,您将翻译后的文本发送到 Amazon Polly,这是一项完全托管的文本转语音服务,可以发回逼真的音频剪辑响应以立即进行流式播放,也可以批量保存在 亚马逊简单存储服务 (Amazon S3) 供以后使用。 您可以使用标准化控制语音的各个方面,例如发音、音量、音高、语速等 语音合成标记语言 (SSML)。

您可以为某些 Amazon Polly 合成语音 神经声音 使用 Newscaster 风格使它们听起来像电视或广播新闻播音员。 您还可以根据音频流中包含的元数据检测何时说出文本中的特定单词或句子。 这允许开发人员将图形突出显示和动画(例如化身的嘴唇运动)与合成语音同步。

您可以修改特定单词的发音,例如公司名称、首字母缩略词、外来词或新词,例如“P!nk”、“ROTFL”或“C'est la vie”(以非法语发音时)语音),使用自定义词典。

架构概述

下图说明了我们的解决方案体系结构。

此图显示了从客户端设备到 Amazon Transcribe、Amazon Translate 和 Amazon Polly 的数据流

工作流程如下:

  1. 音频由 Python SDK 提取。
  2. Amazon Polly 将语音转换为 39 种可能语言的文本。
  3. Amazon Translate 会转换语言。
  4. Amazon Live Transcribe 将文本转换为语音。
  5. 音频被输出到扬声器。

先决条件

您需要一台配备麦克风、扬声器和可靠互联网连接的主机。 现代笔记本电脑应该可以正常工作,因为不需要额外的硬件。 接下来,您需要使用一些软件工具来设置机器。

您必须安装 Python 3.7+ 才能使用异步 Amazon Transcribe 流式开发工具包和名为 pyaudio,用于控制机器的麦克风和扬声器。 这个模块依赖于一个名为的 C 库 portaudio.h. 如果您遇到问题 pyaudio 错误,我们建议检查您的操作系统,看看您是否有 portaudio.h 库安装。

对于服务调用的授权和身份验证,您创建一个 AWS身份和访问管理 (IAM) 服务角色,有权调用必要的 AWS 服务。 通过配置 AWS命令行界面 (AWS CLI) 使用此 IAM 服务角色,您可以在您的机器上运行我们的脚本,而无需传递密钥或密码,因为编写 AWS 库是为了使用配置的 AWS CLI 用户的凭证。 这是一种快速原型设计的便捷方法,并确保我们的服务被授权身份调用。 与往常一样,在创建 IAM 用户或角色时分配 IAM 策略时遵循最小权限原则。

总而言之,您需要以下先决条件:

  • 带有麦克风、扬声器和互联网连接的 PC、Mac 或 Linux 机器
  • portaudio.h 用于您的操作系统的 C 库(brew、apt get、wget),这是 pyaudio 工作所必需的
  • 通过在 AWS CLI 中运行 aws configure 来配置具有正确授权的 IAM 用户的 AWS CLI 2.0
  • Python 3.7 +
  • 异步 Amazon Transcribe Python 开发工具包
  • 以下 Python 库:
    • boto3
    • amazon-transcribe
    • pyaudio
    • asyncio
    • concurrent

实施解决方案

您将严重依赖用于 Python 的异步 Amazon Transcribe 流式开发工具包作为起点,并将在该特定开发工具包的基础上进行构建。 在您尝试了 Python 的流式 SDK 之后,您添加 流媒体麦克风 通过使用输入 pyaudio,一个常用的 Python 开源库,用于处理音频数据。 然后,您将 Boto3 调用添加到 Amazon Translate 和 Amazon Polly,以实现我们的翻译和文本转语音功能。 最后,您再次通过计算机的扬声器输出已翻译的语音 pyaudio. Python 模块 concurrent 使您能够在其自己的异步线程中运行阻塞代码,以无缝、非阻塞的方式播放您返回的 Amazon Polly 语音。

让我们导入所有必要的模块,转录流类,并实例化一些全局变量:

import boto3
 import asyncio
 import pyaudio
 import concurrent
 from amazon_transcribe.client import TranscribeStreamingClient
 from amazon_transcribe.handlers import TranscriptResultStreamHandler
 from amazon_transcribe.model import TranscriptEvent


 polly = boto3.client('polly', region_name = 'us-west-2')
 translate = boto3.client(service_name='translate', region_name='us-west-2', use_ssl=True)
 pa = pyaudio.PyAudio()

 #for mic stream, 1024 should work fine
 default_frames = 1024

 #current params are set up for English to Mandarin, modify to your liking
 params['source_language'] = "en"
 params['target_language'] = "zh"
 params['lang_code_for_polly'] = "cmn-CN"
 params['voice_id'] = "Zhiyu"
 params['lang_code_for_transcribe'] = "en-US"

首先,您使用 pyaudio 获取输入设备的采样率、设备索引和通道数:

#try grabbing the default input device and see if we get lucky
 default_indput_device = pa.get_default_input_device_info()

 # verify this is your microphone device 
 print(default_input_device)

 #if correct then set it as your input device and define some globals
 input_device = default_input_device

 input_channel_count = input_device["maxInputChannels"]
 input_sample_rate = input_device["defaultSampleRate"]
 input_dev_index = input_device["index"]

如果这不起作用,您还可以循环并打印您的设备,如以下代码所示,然后使用设备索引检索设备信息 pyaudio:

print ("Available devices:n")
 for i in range(0, pa.get_device_count()):
     info = pa.get_device_info_by_index(i)
     print (str(info["index"])  + ": t %s n t %s n" % (info["name"], p.get_host_api_info_by_index(info["hostApi"])["name"]))

 # select the correct index from the above returned list of devices, for example zero
 dev_index = 0 
 input_device = pa.get_device_info_by_index(dev_index)

 #set globals for microphone stream
 input_channel_count = input_device["maxInputChannels"]
 input_sample_rate = input_device["defaultSampleRate"]
 input_dev_index = input_device["index"]

你用 channel_count, sample_ratedev_index 作为麦克风流中的参数。 在该流的回调函数中,您使用 asyncio 非阻塞线程安全回调将麦克风流的输入字节放入 asyncio 输入队列。 记下使用创建的 loop 和 input_queue 对象 asyncio 以及它们在以下代码中的使用方式:

async def mic_stream():
     # This function wraps the raw input stream from the microphone forwarding
     # the blocks to an asyncio.Queue.
     
     loop = asyncio.get_event_loop()
     input_queue = asyncio.Queue()
     
     def callback(indata, frame_count, time_info, status):
         loop.call_soon_threadsafe(input_queue.put_nowait, indata)
         return (indata, pyaudio.paContinue)
         
     # Be sure to use the correct parameters for the audio stream that matches
     # the audio formats described for the source language you'll be using:
     # https://docs.aws.amazon.com/transcribe/latest/dg/streaming.html
     
     print(input_device)
     
     #Open stream
     stream = pa.open(format = pyaudio.paInt16,
                 channels = input_channel_count,
                 rate = int(input_sample_rate),
                 input = True,
                 frames_per_buffer = default_frames,
                 input_device_index = input_dev_index,
                 stream_callback=callback)
     # Initiate the audio stream and asynchronously yield the audio chunks
     # as they become available.
     stream.start_stream()
     print("started stream")
     while True:
         indata = await input_queue.get()
         yield indata

现在当生成器函数 mic_stream() 被调用时,只要输入队列中有麦克风输入数据,它就会不断产生输入字节。

现在您知道如何从麦克风获取输入字节,让我们看看如何将 Amazon Polly 输出音频字节写入扬声器输出流:

#text will come from MyEventsHandler
 def aws_polly_tts(text):

     response = polly.synthesize_speech(
         Engine = 'standard',
         LanguageCode = params['lang_code_for_polly'],
         Text=text,
         VoiceId = params['voice_id'],
         OutputFormat = "pcm",
     )
     output_bytes = response['AudioStream']
     
     #play to the speakers
     write_to_speaker_stream(output_bytes)
     
 #how to write audio bytes to speakers

 def write_to_speaker_stream(output_bytes):
     """Consumes bytes in chunks to produce the response's output'"""
     print("Streaming started...")
     chunk_len = 1024
     channels = 1
     sample_rate = 16000
     
     if output_bytes:
         polly_stream = pa.open(
                     format = pyaudio.paInt16,
                     channels = channels,
                     rate = sample_rate,
                     output = True,
                     )
         #this is a blocking call - will sort this out with concurrent later
         while True:
             data = output_bytes.read(chunk_len)
             polly_stream.write(data)
             
         #If there's no more data to read, stop streaming
             if not data:
                 output_bytes.close()
                 polly_stream.stop_stream()
                 polly_stream.close()
                 break
         print("Streaming completed.")
     else:
         print("Nothing to stream.")

现在让我们扩展您在帖子中构建的内容 适用于 Python 的异步 Amazon Transcribe 流式处理开发工具包. 在以下代码中,您使用 ThreadPoolExecutor 具有三个并发的工人的子类。 然后,您在 EventHandler 中对最终返回的脚本添加 Amazon Translate 调用,并传递翻译后的文本、执行程序对象和我们的 aws_polly_tts() 函数成一个 asyncio 循环 loop.run_in_executor(),它在下一次迭代开始时异步运行我们的 Amazon Polly 函数(带有翻译的输入文本) asyncio 环。

#use concurrent package to create an executor object with 3 workers ie threads
 executor = concurrent.futures.ThreadPoolExecutor(max_workers=3)

 class MyEventHandler(TranscriptResultStreamHandler):
     async def handle_transcript_event(self, transcript_event: TranscriptEvent):

         #If the transcription is finalized, send it to translate
 
         results = transcript_event.transcript.results
         if len(results) > 0:
             if len(results[0].alternatives) > 0:
                 transcript = results[0].alternatives[0].transcript
                 print("transcript:", transcript)

                 print(results[0].channel_id)
                 if hasattr(results[0], "is_partial") and results[0].is_partial == False:
                     
                     #translate only 1 channel. the other channel is a duplicate
                     if results[0].channel_id == "ch_0":
                         trans_result = translate.translate_text(
                             Text = transcript,
                             SourceLanguageCode = params['source_language'],
                             TargetLanguageCode = params['target_language']
                         )
                         print("translated text:" + trans_result.get("TranslatedText"))
                         text = trans_result.get("TranslatedText")

                         #we run aws_polly_tts with a non-blocking executor at every loop iteration
                         await loop.run_in_executor(executor, aws_polly_tts, text)  

最后,我们有 loop_me() 功能。 在其中,您定义 write_chunks(),它将 Amazon Transcribe 流作为参数,并将流式麦克风输入块异步写入其中。 然后你使用 MyEventHandler() 将输出转录流作为其参数并创建一个处理程序对象。 然后你使用等待 asyncio.gather() 并使用 handle_events() 方法传入 write_chunks() 和处理程序,以处理这些协程的最终未来。 最后,您收集所有事件循环并循环 loop_me()run_until_complete()。 请参见以下代码:

async def loop_me():
 # Setup up our client with our chosen AWS region

     client = TranscribeStreamingClient(region="us-west-2")
     stream = await client.start_stream_transcription(
         language_code=params['lang_code_for_transcribe'],
         media_sample_rate_hz=int(device_info["defaultSampleRate"]),
         number_of_channels = 2,
         enable_channel_identification=True,
         media_encoding="pcm",
     )
     recorded_frames = []
     async def write_chunks(stream):
         
         # This connects the raw audio chunks generator coming from the microphone
         # and passes them along to the transcription stream.
         print("getting mic stream")
         async for chunk in mic_stream():
             t.tic()
             recorded_frames.append(chunk)
             await stream.input_stream.send_audio_event(audio_chunk=chunk)
             t.toc("chunks passed to transcribe: ")
         await stream.input_stream.end_stream()

     handler = MyEventHandler(stream.output_stream)
     await asyncio.gather(write_chunks(stream), handler.handle_events())

 #write a proper while loop here
 loop = asyncio.get_event_loop()
 loop.run_until_complete(loop_me())
 loop.close()

当前面的代码一起运行没有错误时,你可以对着麦克风说话,并很快听到你的声音被翻译成普通话。 Amazon Transcribe 和 Amazon Translate 的自动语言检测功能可将任何受支持的输入语言翻译成目标语言。 您可以说话很长一段时间,并且由于函数调用的非阻塞性质,您的所有语音输入都被翻译和说出,这使其成为翻译现场演讲的绝佳工具。

结论

尽管这篇文章展示了这三个完全托管的 AWS API 如何可以无缝协同工作,但我们鼓励您考虑如何以其他方式使用这些服务,以当前成本的一小部分为服务或媒体(如多语言隐藏式字幕)提供多语言支持. 医学、商业甚至外交关系都可以从不断改进、低成本、低维护的翻译服务中受益。

有关此用例的概念验证代码库的更多信息,请查看我们的 Github上.


作者简介

使用 Amazon Transcribe、Amazon Translate 和 Amazon Polly PlatoBlockchain 数据智能突破语言障碍。 垂直搜索。 哎。迈克尔·特兰 是 Amazon Web Services 的 Envision 工程团队的解决方案架构师。 他提供技术指导,并通过在 AWS 上展示可能的艺术来帮助客户提高创新能力。 他为我们的客户围绕 AI/ML 和 IoT 构建了多个原型。 您可以在 Twitter 上与我联系 @Mike_Trann。

使用 Amazon Transcribe、Amazon Translate 和 Amazon Polly PlatoBlockchain 数据智能突破语言障碍。 垂直搜索。 哎。卡梅伦威尔克斯 是 AWS Industry Accelerator 团队的原型设计师。 在团队中,他向客户交付了几个基于 ML 的原型,以展示 AWS 上 ML 的“可能艺术”。 他喜欢音乐制作、越野和设计。

时间戳记:

更多来自 AWS机器学习