AWS лямбда-код для преобразования MP3-ввода для Lex - PullRequest
0 голосов
/ 09 сентября 2018

У меня есть решение, которое будет находиться на локальном мобильном устройстве пользователя, и я хочу, чтобы оно отправляло аудиоконтент на Lex с помощью API-интерфейса AWS REST. Проблема заключается в том, что решение не может передавать аудио (вверх или вниз) и практически не имеет возможностей манипулирования аудио локально. Однако у Лекса очень специфические требования к входу, а также потоковый вывод.

Таким образом, доступ будет осуществляться через API-шлюз, действующий как прокси-сервер с функцией Lambda (Python 2.7) для решения проблем со звуком.

Все выходные обрабатываются, лямбда-код сохраняет AudioStream в файл и отправляет этот файл в качестве тела ответа, это прекрасно работает. Однако я не могу заставить работать данные.

Входной аудиосигнал - это файл MP3, отправляемый в качестве тела запроса POST, и мне нужно преобразовать его в формат, приемлемый для 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.

В данный момент я собираюсь сделать следующее

  • Использование Python для сохранения файла MP3 в корзину S3
  • Пусть Elastic Transcoder преобразует этот MP3 в PCM с частотой дискретизации 22050 (но со всеми другими настройками, установленными в соответствии с требованиями Lex)
  • Лямбда считывает транскодированный файл обратно с S3
  • Используйте библиотеку wave (import wav) для чтения файла, а затем запишите файл с частотой дискретизации 16000 (это шаг, в котором я не уверен)
  • Отправьте файл (с правильной частотой дискретизации) на Lex

Конечно, здесь будут некоторые проблемы с задержкой, но пока они не слишком серьезны, я готов с ними жить. Это кажется слишком сложным для того, что я думал, было бы довольно простой задачей. Тем не менее, это лучшее, что я придумал до сих пор, но даже чтобы доказать это, потребуется несколько часов работы, и я уже потратил несколько дней на это.

Таким образом, главный вопрос заключается в том, можно ли использовать библиотеку Python Wave в AWS Lambda для изменения частоты дискретизации таким образом?

Если нет, то есть ли способ решить эту проблему, создав пакет развертывания, используя функцию AWS, которую я еще не исследовал, или более аккуратный способ сделать это в чем-то отличном от Python?

Проблема в том, что часть Lex этого приложения должна была быть приятной, но не основной, но все же занимала большую часть времени разработки, я довольно близок к тому, чтобы отказаться от нее. но подумал, что сначала спрошу здесь.

1 Ответ

0 голосов
/ 23 сентября 2018

Так что это заняло некоторое время, но есть способ сделать это.

Способ, который я решил, - сохранить файл на s3, а затем запустить Elastic Transcoder, чтобы получить файл wav (1канал с частотой дискретизации 22050).

Затем используйте следующие значения var

  • inrate = 22050
  • outrate = 16000
  • inchannels = 2
  • outchannels = 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 и получит ожидаемый ответ.

В этом методе есть заметная задержка, обработка обычно составляет около 7-10 секунд в соответствии с журналами CloudWatch, поэтому, вероятно, неприемлема для решения производственного уровня, но этого достаточно для моих нужд.следующие источники

...