Кодирование аудио LINEAR16 в аудио Twilio media /x-mulaw | NodeJS
Я пытался передать поток мультимедиа Mulaw обратно в Twilio. Требование - полезная нагрузка должна быть в кодировке audio/x-mulaw с частотой дискретизации 8000 и в кодировке base64.
Мой ввод сделан из @google-cloud/ преобразования текста в речь в LINEAR16 Google Docs.
Я пробовал Wavefile
Вот как я закодировал ответ от @google-cloud/text-to-speech
const wav = new wavefile.WaveFile(speechResponse.audioContent)
wav.toBitDepth('8')
wav.toSampleRate(8000)
wav.toMuLaw()
Затем отправляю результат обратно в twilio через websocket
twilioWebsocket.send(JSON.stringify({
event: 'media',
media: {
payload: wav.toBase64(),
},
streamSid: meta.streamSid,
}))
Проблема в том, что мы здесь только случайный шум на другом конце вызова Twilio, похоже, что кодировка неправильная
Во-вторых, я проверил звук вывода @google-cloud/ преобразования текста в речь, сохранив его в файле, и он был правильным и понятным.
Может ли кто-нибудь помочь мне с кодировкой
2 ответа
У меня тоже была такая же проблема. Ошибка в
wav.toBase64()
, так как он включает заголовок wav. Медиапотоки Twilio ожидают необработанные аудиоданные, которые вы можете получить с помощью
wav.data.samples
, поэтому ваш код будет:
const wav = new wavefile.WaveFile(speechResponse.audioContent)
wav.toBitDepth('8')
wav.toSampleRate(8000)
wav.toMuLaw()
const payload = Buffer.from(wav.data.samples).toString('base64');
У меня была такая же проблема. Решение состоит в том, что вам необходимо вручную преобразовать LINEAR16 в соответствующий кодек MULAW.
Вы можете использовать код из музыкальной библиотеки .
Из этого я создал функцию для преобразования линейного 16-байтового массива в mulaw:
short2ulaw(b: Buffer): Buffer {
// Linear16 to linear8 -> buffer is half the size
// As of LINEAR16 nature, the length should ALWAYS be even
const returnbuffer = Buffer.alloc(b.length / 2)
for (let i = 0; i < b.length / 2; i++) {
// The nature of javascript forbids us to use 16-bit types. Every number is
// A double precision 64 Bit number.
let short = b.readInt16LE(i * 2)
let sign = 0
// Determine the sign of the 16-Bit byte
if (short < 0) {
sign = 0x80
short = short & 0xef
}
short = short > 32635 ? 32635 : short
const sample = short + 0x84
const exponent = this.exp_lut[sample >> 8] & 0x7f
const mantissa = (sample >> (exponent + 3)) & 0x0f
let ulawbyte = ~(sign | (exponent << 4) | mantissa) & 0x7f
ulawbyte = ulawbyte == 0 ? 0x02 : ulawbyte
returnbuffer.writeUInt8(ulawbyte, i)
}
return returnbuffer
}
Теперь вы можете использовать это на Raw PCM (Linear16). Теперь вам просто нужно подумать об удалении байтов в начале потока Google, поскольку Google добавляет заголовок wav. Затем вы можете закодировать полученный буфер base64 и отправить его в twilio.