#node.js #twilio #google-text-to-speech #mu-law
#node.js #twilio #google-преобразование текста в речь #mu-law
Вопрос:
Я пытался передать мультимедийный поток mulaw обратно в Twilio. Требование — полезная нагрузка должна быть закодирована в аудио / x-mulaw с частотой дискретизации 8000 и кодироваться на base64
Мой вклад взят из @google-cloud / преобразование текста в речь в LINEAR16 Google Docs
Я попробовал Wavefile
Вот как я закодировал ответ от @google-cloud / преобразование текста в речь
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 / text-to-speech, сохранив его в файле, и он был правильным и понятным
Может кто-нибудь, пожалуйста, помочь мне с кодировкой
Ответ №1:
У меня тоже была такая же проблема. Ошибка wav.toBase64()
, так как это включает заголовок wav. Twilio media streams ожидает необработанные аудиоданные, которые вы можете получить 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');
Ответ №2:
У меня только что была такая же проблема. Решение заключается в том, что вам нужно вручную преобразовать 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 amp; 0xef
}
short = short > 32635 ? 32635 : short
const sample = short 0x84
const exponent = this.exp_lut[sample >> 8] amp; 0x7f
const mantissa = (sample >> (exponent 3)) amp; 0x0f
let ulawbyte = ~(sign | (exponent << 4) | mantissa) amp; 0x7f
ulawbyte = ulawbyte == 0 ? 0x02 : ulawbyte
returnbuffer.writeUInt8(ulawbyte, i)
}
return returnbuffer
}
Теперь вы можете использовать это на необработанном PCM (Linear16). Теперь вам просто нужно подумать о том, чтобы удалить байты в начале потока Google, поскольку Google добавляет заголовок wav.
Затем вы можете закодировать полученный буфер base64 и отправить его в twilio.