首页 > 解决方案 > 用于为 Lex 转换 MP3 输入的 AWS Lambda 代码

问题描述

我有一个驻留在用户本地移动设备上的解决方案,我希望它使用 AWS REST API 将音频内容发布到 Lex。问题是该解决方案无法流式传输音频(向上或向下)并且在本地几乎没有音频处理功能。然而,Lex 有非常具体的输入要求和流输出。

因此,访问将通过 API 网关作为代理,使用 Lambda (Python 2.7) 函数来处理音频问题。

输出全部处理完毕,Lambda 代码将 AudioStream 保存到一个文件中并将该文件作为响应正文发送,这工作正常。但是我无法让输入工作。

输入音频是作为 POST 请求正文发送的 MP3 文件,我需要将其转换为 Lex 可接受的格式。

我研究了以下方法

原生 AWS
使用 S3 和 Elastic Transcoder - 转码为 PCM 时允许的最低采样率为 22050,但 Lex 需要 16000,这似乎也不允许转码为 Opus 格式

使用 MediaConvert - 看不到转换为 PCM 或 Opus 的设置

原生 Python
Python 似乎不具备原生解压 MP3 的能力。我读过这会很慢,不值得做。

导入库
使用 ffmpeg-python 或 ffmpy - 但这涉及创建部署包或类似的东西。我可以走这条路,但这对于我想做的事情来说似乎过于复杂。

使用 Python 以外的其他东西
我选择了 Python,因为我更熟悉在 Lambda 中使用它进行编码,但也许 C#、Node、Java 8 有一些可用的东西可以使这在 Lambda 函数中变得容易。

目前我正在考虑执行以下操作

当然这里会有一些延迟问题,但只要它们不太严重,我愿意忍受它们。对于我认为相当简单的任务来说,这似乎过于复杂。然而,这是迄今为止我想出的最好的,但即使要证明这一点也需要花费数小时的工作,而且我已经花了好几天的时间。

所以主要的问题是是否可以在 AWS Lambda 中使用 Python Wave 库以这种方式修改采样率?

如果没有,是否有办法通过创建部署包、使用我尚未研究的 AWS 功能或在 Python 以外的其他东西中更简洁地执行此操作来解决此问题?

问题是这个应用程序的 Lex 部分应该是一个不错的选择,它不是主要功能,但它占用了大部分开发时间,我非常接近放弃它,但我想我会先在这里问。

标签: amazon-web-servicesaudioaws-lambdatranscoding

解决方案


所以花了一段时间,但有办法做到这一点。

我解决它的方法是将文件保存到 s3,然后通过 Elastic Transcoder 运行以获取 wav 文件(1 个通道,22050 采样率)。

然后使用以下 var 值

  • 无速率=22050
  • 出价=16000
  • 频道内=2
  • 输出频道=1

这段代码应该把它降到 16000

import audioop
import wave

s_read = wave.open(src, 'r')
s_write = wave.open(dst, 'w')

n_frames = s_read.getnframes()
data = s_read.readframes(n_frames)

converted = audioop.ratecv(data, 1, inchannels, inrate, outrate, None)

s_write.setparams((outchannels, 2, outrate, 0, 'NONE', 'Uncompressed'))
s_write.writeframes(converted[0])

s_read.close()
s_write.close()

然后 Lex 接受该文件并按预期获得响应。

这种方法有一些明显的延迟,根据 CloudWatch Logs,处理时间通常约为 7-10 秒,因此对于生产级解决方案来说可能是不可接受的,但它足以满足我的需求。

感谢以下来源


推荐阅读