Twilioの音声データはaudio/x-mulaw
形式、8000Hz, 8bit, 1チャンネルの固有の型を持っています。
特にx-mulaw
形式がわからなく、死ぬほどハマったので共有します。
結論
x-mulaw
形式の方法があるのでそれに従います。
const WaveFile = require('wavefile').WaveFile;
// Base64エンコードされたオーディオデータをデコード
let decodedData = Buffer.from(base64String, 'base64');
let wav = new WaveFile();
// 8ではなく、”8m”
wav.fromScratch(1, 8000, '8m', decodedData);
// μ-law形式としてWAVファイルを保存
wav.toMuLaw();
fs.writeFileSync('output.wav', wav.toBuffer());
自らWav Headerを作成する場合
const fs = require('fs');
const WaveFile = require('wavefile').WaveFile;
const fileStream = fs.createWriteStream("sample.wav", {flags: 'a'});
// Wavファイルのヘッダーを作成。8000Hz, 8bit, 1チャンネル
const header = createWavHeader(8000, 8, 1);
fileStream.write(header);
~~~~~~~~~~~
// streamのpayloadから音声データを取得
base64String = msg.media.payload
// Base64エンコードされたオーディオデータをデコード
let decodedData = Buffer.from(base64String, 'base64');
fileStream.write(buffers);
~~~~~~~~~~~~~
fileStream.end();
//Headerにデータ容量を書き込む。なくても良い。
const dataSize = fileStream.length;
header.writeUInt32LE(dataSize + 36, 4);
header.writeUInt32LE(dataSize, 40);
function createWavHeader(sampleRate, bitDepth, channels) {
const blockAlign = channels * bitDepth / 8;
const byteRate = sampleRate * blockAlign;
const header = Buffer.alloc(44);
header.write('RIFF', 0);
header.writeUInt32LE(36, 4);
header.write('WAVE', 8);
header.write('fmt ', 12);
header.writeUInt32LE(16, 16);
header.writeUInt16LE(0x0007, 20); // AudioFormat PCMなら1, mulawは0x0007
header.writeUInt16LE(channels, 22);
header.writeUInt32LE(sampleRate, 24);
header.writeUInt32LE(byteRate, 28);
header.writeUInt16LE(blockAlign, 32);
header.writeUInt16LE(bitDepth, 34);
header.write('data', 36);
header.writeUInt32LE(0, 40);
return header;
}
弊社Passinate Geniusでは一緒に働く仲間を募集しています!興味をお持ちいただける方は、ホームページまで!