降低使用recorderjs创建的WAV文件的比特率

时间:2013-04-30 09:35:40

标签: html5 audio wav audio-recording recorder.js

我正在尝试在应用引擎网站上使用recorderjs,用户可以在其中上传简短的录音(例如,长达1到12秒)。我注意到我上传的WAV文件比我预期的要大得多。例如,我刚创建了一个持续大约9秒的记录,上传的blob是1736769字节,这是> 1.5兆字节。

问题:

如何修改recorderjs代码(或我自己的代码 - 也许我正在使用recorderjs),以便我的音频blob具有较低的比特率?我希望10秒钟的录音能够安全地低于1 MB。

我的猜测是我需要修改here中的encodeWAV函数,或者可能是exportWAV,但我不确定如何。在exportWAV中删除交错缓冲区的每个其他元素是否有意义?有更聪明的方法吗?导出的WAV的比特率如何取决于我的计算机的属性(例如我的声卡的采样率)?

如果可能有帮助,我可以在我自己的代码中添加一些细节。

修改:如果您想查看实际示例,请安装Google Chrome测试版并尝试this page。在我的电脑上,5-10秒长的录音超过1 MB。

非常感谢,

阿德里安

3 个答案:

答案 0 :(得分:21)

在我的情况下,Chrome会录制96kHz的音频和44.1kHz的Firefox,这会产生巨大的 WAV 文件。我在recorderWorker.js中实现了一个下采样功能,您可以在其中选择所需的采样率,如16000。

function downsampleBuffer(buffer, rate) {
    if (rate == sampleRate) {
        return buffer;
    }
    if (rate > sampleRate) {
        throw "downsampling rate show be smaller than original sample rate";
    }
    var sampleRateRatio = sampleRate / rate;
    var newLength = Math.round(buffer.length / sampleRateRatio);
    var result = new Float32Array(newLength);
    var offsetResult = 0;
    var offsetBuffer = 0;
    while (offsetResult < result.length) {
        var nextOffsetBuffer = Math.round((offsetResult + 1) * sampleRateRatio);
        var accum = 0, count = 0;
        for (var i = offsetBuffer; i < nextOffsetBuffer && i < buffer.length; i++) {
            accum += buffer[i];
            count++;
        }
        result[offsetResult] = accum / count;
        offsetResult++;
        offsetBuffer = nextOffsetBuffer;
    }
    return result;
}

我在导出wav文件时调用它:

function exportWAV(rate, type) {
    var bufferL = mergeBuffers(recBuffersL, recLength);
    var bufferR = mergeBuffers(recBuffersR, recLength);
    var interleaved = interleave(bufferL, bufferR);
    var downsampledBuffer = downsampleBuffer(interleaved, rate);
    var dataview = encodeWAV(rate, downsampledBuffer, false);
    var audioBlob = new Blob([ dataview ], {
        type : type
    });

    this.postMessage(audioBlob);
}

答案 1 :(得分:4)

你可以试试几件事。首先,我认为你正在关注&#34;删除交错缓冲区的所有其他元素&#34; (将声音转换为单声道)。

为此您可以选择保留左声道或右声道。你可以改变&#34;交错&#34;功能是:

function interleave(inputL, inputR){
  return inputL; // or inputR
}

如果你想保留两个频道,但是&#34; pan&#34;它们都是中心(对于单个单声道),你可以做类似的事情:

function interleave(inputL, inputR){
  var result = new Float32Array(inputL.length);
  for (var i = 0; i < inputL.length; ++i)
    result[i] = 0.5 * (inputL[i] + inputR[i]);
  return result;
}

话虽如此,可能很多其他位置你必须改变编码音频从被表示为立体声到单声道。但是,我的猜测是(我还没有使用recorder.js,所以我不知道它的内部工作原理),记录器工作室中的第113/114行可能会改为1.

我的猜测是,你可以通过改变这里提到的两个地方(交错函数,以及设置通道计数的地方[第114行])来逃避因为:interleave和encodeWAV只能通过exportWAV函数调用因此,不要触及原始工作者如何录制音频(并且它已经录制立体声),希望不会打破它。在这种情况下,我们只会对存储的音频进行更改。

答案 2 :(得分:3)

我使用相同的刻录机代码,我需要降低比特率。我的解决方案产生11025Hz单声道文件。它不是很优雅,所以如果有人对我进行更正,我会很高兴。

首先,我将init函数中的采样率更改为11025而不是音频上下文的比特率(这是非优雅的部分,因为上下文可能不是44100Hz)。

我用此

替换interleave函数内容
var length = inputL.length / 4;
var result = new Float32Array(length);

var index = 0,
  inputIndex = 0;

while (index < length) {
    result[index++] = 0.25 * (inputL[inputIndex++] + inputL[inputIndex++] +
                              inputL[inputIndex++] + inputL[inputIndex++]);
}

return result;

这只占用左通道,并在结果中将每4个缓冲区样本转换为1,因此占用的内存较少。如果比特率改变相同的比率(除以4,例如11025),则文件听起来会相同但会小得多。

我还将encodeWAV中的频道数量更改为一个

/* channel count */
 view.setUint16(22, 1, true);

与原始制作的文件相比,录制的尺寸为1/8。