折腾:
【已解决】用Recorderjs实现js录音保存为wav格式
后,虽然可以正常录音和下载wav,但是wav文件太大:
3秒就要600多KB,所以去优化看看:
(估计默认是44100)-〉降低sample rate看看
对于要设置sample rate为多少,参考:
【已解决】web端html+js中如何调用麦克风获取用户语音输入说话
中的:
“Content-type: The Content-type field describes the format and codec of the audio stream. Currently, only WAV file and PCM Mono 16000 encoding is supported. The Content-type value for this format is audio/wav; codec=audio/pcm; samplerate=16000”
应该是设置为:
采样率:16000=16k
声道数量:1 -》 单声道=mono
去找找如何配置sample rate:
https://github.com/mattdiamond/Recorderjs
和:
搜索源码:sampleRate
但是看到:
好像不支持sampleRate的配置?
去试试代码
<code> recorderConfig = { sampleRate: 16000 } gRecorder = new Recorder(input, recorderConfig) </code>
结果:
好像是没用的:
3秒左右还是要600多KB
而百度的:
http://ai.baidu.com/docs#/ASR-API/top
-》
16000=16K采样率的wav,4秒,(估计是mono 单声道)才130KB:
-》微软的wav也是:单声道,16000采样率
此处,感觉是:
441000的采样率,然后还是双声道,3秒要600多KB
此处看看,能否修改源码,实现直接设置
16000
单声道
貌似js库中,可以直接去修改
config的numChannels,从2改为1:
<code>var Recorder = exports.Recorder = (function () { ... this.config = { bufferLen: 4096, numChannels: 1, mimeType: 'audio/wav' }; </code>
看看效果
同时,注意到:
此处的
.sampleRate
好像是:
worker中的.sampleRate:
是调用了:
config中的.sampleRate
所以后续还可以继续去试试:
给config中添加sampleRate,设置为16000,再看看效果
先去看看
numChannels从2变1
效果如何:
但是为何初始化后,还是2啊:
<code>audioContext= AudioContext {baseLatency: 0.005804988662131519, destination: AudioDestinationNode, currentTime: 0, sampleRate: 44100, listener: AudioListener, …}audioWorklet: AudioWorklet {}baseLatency: 0.005804988662131519currentTime: 31.759092970521543destination: AudioDestinationNode {maxChannelCount: 2, context: AudioContext, numberOfInputs: 1, numberOfOutputs: 0, channelCount: 2, …}listener: AudioListener {positionX: AudioParam, positionY: AudioParam, positionZ: AudioParam, forwardX: AudioParam, forwardY: AudioParam, …}onstatechange: nullsampleRate: 44100state: "running"__proto__: AudioContext main.js:412 input= MediaStreamAudioSourceNode {mediaStream: MediaStream, context: AudioContext, numberOfInputs: 0, numberOfOutputs: 1, channelCount: 2, …}channelCount: 2channelCountMode: "max"channelInterpretation: "speakers"context: AudioContextaudioWorklet: AudioWorklet {}baseLatency: 0.005804988662131519currentTime: 47.74022675736961destination: AudioDestinationNode {maxChannelCount: 2, context: AudioContext, numberOfInputs: 1, numberOfOutputs: 0, channelCount: 2, …}listener: AudioListener {positionX: AudioParam, positionY: AudioParam, positionZ: AudioParam, forwardX: AudioParam, forwardY: AudioParam, …}onstatechange: nullsampleRate: 44100state: "running"__proto__: AudioContextmediaStream: MediaStream {id: "IC5UKcx2fJRq5xk0sk5iYnaq1gByya9aQcYl", active: true, onaddtrack: null, onremovetrack: null, onactive: null, …}numberOfInputs: 0numberOfOutputs: 1__proto__: MediaStreamAudioSourceNode main.js:417 gRecorder= Recorder {config: {…}, recording: false, callbacks: {…}, context: AudioContext, node: ScriptProcessorNode, …} </code>
先试试结果:
好像真的是降低一半大小了,3秒左右,300多KB了:
而再去看代码:
好像这处:
<code>var Recorder = exports.Recorder = (function () { function Recorder(source, cfg) { ... this.config = { bufferLen: 4096, //numChannels: 2, numChannels: 1, mimeType: 'audio/wav' }; ... Object.assign(this.config, cfg); </code>
是可以支持传入的参数中包含我们希望的:
numChannels
sampleRate
-》所以去把直接修改库
Recorderjs/recorder.js
中的config的numChannels的做法,还原:
放到调用代码中:
<code> var recorderConfig = { sampleRate: 16000, numChannels: 1 } gRecorder = new Recorder(input, recorderConfig) </code>
-》同时发现,之前代码是:
recorderConfig = {
好像缺少了个var
此处加上了
-〉那干脆单独试试之前的:
<code>recorderConfig = { sampleRate: 16000 } console.log("recorderConfig=", recorderConfig) gRecorder = new Recorder(input, recorderConfig) </code>
看看log是啥,是否是正常的js的变量
-》说明之前没有加var也是对的。
那么现在就可以去:
先单独试试numChannels
<code> var recorderConfig = { // sampleRate: 16000, numChannels: 1 } </code>
结果:
去录音看看:
是对的:3秒只有300多KB了
-》numChannels是可以通过调用参数config去传递进去的
同理,再去加上sampleRate:
<code> var recorderConfig = { sampleRate: 16000, numChannels: 1 } console.log("recorderConfig=", recorderConfig) gRecorder = new Recorder(input, recorderConfig) </code>
结果:
5秒,只有500多KB
以及:
4秒-》400多KB
-〉感觉只有单声道使得wav大小降低了
-》而sampleRate从44100变成16000,好像没啥变化啊
-〉还是sampleRate根本就没生效?
-》
同样的:
单声道
采样率 16000
-〉
百度的wav示例:4秒-〉130KB
而我们的:4秒-〉400KB
相差3倍左右
-》好像就是 44100 和16000的3倍关系
-〉很像是sampleRate设置16000作为config,传递进去,没有起效果。
试试,手动去:
Recorderjs/recorder.js
改为16k:
<code>var Recorder = exports.Recorder = (function () { function Recorder(source, cfg) { ... this.config = { bufferLen: 4096, sampleRate: 16000, numChannels: 2, mimeType: 'audio/wav' }; </code>
结果:
log中看到:
<code>1. AudioContext 1. audioWorklet:AudioWorklet {} 2. baseLatency:0.005804988662131519 3. currentTime:6.3854875283446715 4. destination:AudioDestinationNode {maxChannelCount: 2, context: AudioContext, numberOfInputs: 1, numberOfOutputs: 0, channelCount: 2, …} 5. listener:AudioListener {positionX: AudioParam, positionY: AudioParam, positionZ: AudioParam, forwardX: AudioParam, forwardY: AudioParam, …} 6. onstatechange:null 7. sampleRate:44100 8. state:"running" 1. config: 1. bufferLen:4096 2. mimeType:"audio/wav" 3. numChannels:1 4. sampleRate:16000 </code>
即:
config的sampleRate是16000
AudioContext的sampleRate是44100
-》先去运行看看效果
4秒-〉近400KB
好像也不对
不行的话:
直接给worker设置sampleRate为16000,看看效果如何
再去找找,如何改变AudioContext的(初始化时的)sampleRate
或者说是sampleRate生效了,但是Recorderjs内部的算法有问题?
recorder js sample rate not work
How to Reduce wav File-size created by Recorder.js · Issue #53 · mattdiamond/Recorderjs
改为:
<code> function encodeWAV(samples) { ... /* byte rate (sample rate * block align) */ //view.setUint32(28, sampleRate * 4, true); // fixbug from https://github.com/mattdiamond/Recorderjs/issues/53 view.setUint32(28, sampleRate * numChannels * 2, true); </code>
效果是:
3秒-》300多KB
没啥区别。
html5 – Decrease bitrate on WAV file created with recorderjs – Stack Overflow
试试:
<code> // function exportWAV(type) { // var buffers = []; // for (var channel = 0; channel < numChannels; channel++) { // buffers.push(mergeBuffers(recBuffers[channel], recLength)); // } // var interleaved = undefined; // if (numChannels === 2) { // interleaved = interleave(buffers[0], buffers[1]); // } else { // interleaved = buffers[0]; // } // var dataview = encodeWAV(interleaved); // var audioBlob = new Blob([dataview], { type: type }); // self.postMessage({ command: 'exportWAV', data: audioBlob }); // } 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; } 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); self.postMessage({ command: 'exportWAV', data: audioBlob }); } </code>
结果:
出错:
<code>Uncaught ReferenceError: recBuffersL is not defined at exportWAV (blob:null/46831f77-b9a5-4626-a42b-646c1000843a:86) at self.onmessage (blob:null/46831f77-b9a5-4626-a42b-646c1000843a:16) exportWAV @ blob:null/46831f77-b9a5-4626-a42b-646c1000843a:86 self.onmessage @ blob:null/46831f77-b9a5-4626-a42b-646c1000843a:16 </code>
Changing the bitrate and recording the mono wav files · Issue #40 · mattdiamond/Recorderjs
recorder-worker.js in pubnub-api | source code search engine
javascript – Change sample rate of AudioContext (getUserMedia) – Stack Overflow
去试试
<code> var input = audioContext.createMediaStreamSource(mediaStream) console.log("input=", input) var resampler = new Resampler(44100, 16000) input.connect(resampler) var recorderConfig = { sampleRate: 16000, numChannels: 1 } console.log("recorderConfig=", recorderConfig) gRecorder = new Recorder(input, recorderConfig) </code>
结果:
和我猜的一样,找不到Resampler:
<code>Try getUserMedia error: ReferenceError: Resampler is not defined at testRecorderjs (main.js:414) at onSuccessGetUserMedia (main.js:468) </code>
然后对于上面的:recBuffersL
突然有点看懂了:
好像就是自己去加上:
recBuffersL
和:
recBuffersR
<code> this.worker = new _inlineWorker2.default(function () { var recLength = 0, recBuffers = [], recBuffersL = [], recBuffersR = [], sampleRate = undefined, numChannels = undefined; </code>
估计就可以了:
但是发现:
估计也不对:
因为代码里还有其他地方调用了之前的:recBuffers呢。
先去试试看看
果然不对:
需要改很多代码:
保存时,要传递参数才行?
Highest Voted ‘recorder.js’ Questions – Stack Overflow
-》
https://stackoverflow.com/questions/16296645/decrease-bitrate-on-wav-file-created-with-recorderjs
然后注意到了:
有人去问:
“How to have recBuffersL and recBuffersR in your function? – Minh-Hung Nguyen Jul 27 ’15 at 0:09”
那人回复:
“They are attributes in recorderWorker.js. Be careful, there’s a new version of Recorder.js and now the number of channels is configurable recBuffers = [], you will have to adapt my solution if you use this version of the library. ”
但是不知道如何修改啊
javascript – record audio from user and save to server – Stack Overflow
通过调试发现:
<code> function encodeWAV(samples) { console.log("encodeWAV: numChannels=", numChannels, ", sampleRate=", sampleRate) </code>
输出:
然后就好办了,去搞清楚,sampleRate为何不是此处设置的16000
AudioContext config sampleRate
AudioContext config sample Rate
先去试试前面的:
https://github.com/taisel/XAudioJS/blob/master/resampler.js
加进来试试
结果报错:
<code>main.js:483 Try getUserMedia error: Error: inputBuffer is not an object. at new Resampler (resampler.js:14) at testRecorderjs (main.js:413) at onSuccessGetUserMedia (main.js:467) </code>
好像是少了?
resampler.connect(audioContext.destination)
加上:
<code> var audioContext = new AudioContext() console.log("audioContext=", audioContext) var input = audioContext.createMediaStreamSource(mediaStream) console.log("input=", input) var resampler = new Resampler(44100, 16000) console.log("resampler=", resampler) input.connect(resampler) resampler.connect(audioContext.destination) var recorderConfig = { sampleRate: 16000, numChannels: 1 } console.log("recorderConfig=", recorderConfig) gRecorder = new Recorder(input, recorderConfig) console.log("gRecorder=", gRecorder) </code>
结果:
错误依旧。
直接设置:
<code>var audioContext = new AudioContext() console.log("audioContext=", audioContext) audioContext.sampleRate = 16000 </code>
结果:
没用。还是44100。
Uncaught ReferenceError: recBuffersL is not defined
recBuffersL is not defined
暂时先不继续优化了:
等后期:
语音识别接口无法识别此处wav
觉得wav的确太大了,的确需要优化时
再去优化
转载请注明:在路上 » 【暂未解决】去优化Recorderjs降低生成的wav文件大小