我正在尝试在应用引擎网站上使用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。
非常感谢,
阿德里安
答案 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。