Код AWS Lambda для преобразования входных данных MP3 для Lex

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

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

О выводе все заботятся, код Lambda сохраняет 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 (импорт wav), чтобы прочитать файл, а затем запишите файл с частотой дискретизации 16000 (это шаг, в котором я не уверен)
  • Отправьте файл (с правильной частотой дискретизации) в Lex

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

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

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

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


person Matt Haughton    schedule 09.09.2018    source источник


Ответы (1)


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

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

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

  • внутренняя скорость = 22050
  • превышение = 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 Logs, поэтому, вероятно, это неприемлемо для решения производственного уровня, но этого достаточно для моих нужд.

Благодаря следующим источникам

person Matt Haughton    schedule 23.09.2018