折腾:
【未解决】换用MediaStreamRecorder实现麦克风录音且支持多个浏览器和wav格式
期间,遇到一个奇怪的现象:
代码:
<code> function testMediaStreamRecorder(mediaStream){ console.log("testMediaStreamRecorder: mediaStream=%o", mediaStream); var mediaStreamRecorder = new MediaStreamRecorder(mediaStream); console.log("mediaStreamRecorder=%o", mediaStreamRecorder); const AUDIO_TYPE = { webm: { mimeType: 'audio/webm', suffix: ".webm" }, wav: { mimeType: 'audio/wav', suffix: ".wav" }, pcm: { mimeType: 'audio/pcm', suffix: ".pcm" }, ogg: { mimeType: 'audio/ogg', suffix: ".ogg" } } // var curAudioType = AUDIO_TYPE.webm; var curAudioType = AUDIO_TYPE.wav; // var curAudioType = AUDIO_TYPE.pcm; // var curAudioType = AUDIO_TYPE.ogg; console.log("curAudioType=%o", curAudioType); mediaStreamRecorder.mimeType = curAudioType.mimeType; mediaStreamRecorder.ondataavailable = function (recordedBlob) { console.log("mediaStreamRecorder.ondataavailable: recordedBlob=%o", recordedBlob); const blobUrl = URL.createObjectURL(recordedBlob); console.log("blobUrl=%o", blobUrl); playRecordedAudio(blobUrl); downloadRecordedAudio(blobUrl, curAudioType.suffix); }; $( "#stopSpeak" ).on( "click", function() { console.log("#stopSpeak clicked"); mediaStreamRecorder.stop(); }); if ((curAudioType == AUDIO_TYPE.wav) || (curAudioType == AUDIO_TYPE.pcm)) { // mediaStreamRecorder.recorderType = StereoAudioRecorder; // console.log("set recorderType to StereoAudioRecorder when wav"); console.log("seems wav type need trigger then can start record"); $( "#startSpeak" ).on( "click", function() { console.log("#startSpeak clicked"); mediaStreamRecorder.start(); }); } else { console.log("directly start by code"); mediaStreamRecorder.start(); } console.log("mediaStreamRecorder started"); } </code>
是通过点击按钮去触发录音了,但是ondataavailable会被执行多次:
所以,看起来和之前的AudioContext:
<code> function testAudioContext(mediaStream){ console.log("testAudioContext: mediaStream=%o", mediaStream); var audioContext = new AudioContext(); console.log("audioContext=%o", audioContext); var mediaInputSrc = audioContext.createMediaStreamSource(mediaStream) console.log("mediaInputSrc=%o", mediaInputSrc); var processor = audioContext.createScriptProcessor(1024,1,1); console.log("processor=%o", processor); mediaInputSrc.connect(processor); processor.connect(audioContext.destination); console.log("audioContext.destination=%o", audioContext.destination); $( "#startSpeak" ).on( "click", function() { console.log("#startSpeak clicked"); audioContext.resume().then(() => { console.log('Playback resumed successfully'); }); }); processor.onaudioprocess = function(e) { console.log("Audio processor onaudioprocess"); // Do something with the data, i.e Convert this to WAV console.log(e.inputBuffer); }; } </code>
很像啊。
然后看到其demo:
MediaStreamRecorder/audio-recorder.html at master · streamproc/MediaStreamRecorder
<code> <select id="audio-recorderType" style="font-size:22px;vertical-align: middle;margin-right: 5px;"> <option>[Best Available Recorder]</option> <option>MediaRecorder API</option> <option>WebAudio API (WAV)</option> <option>WebAudio API (PCM)</option> </select> </code>
想起来了:
如果此处用的audio/wav,则内部是用WebAudio API (WAV)的接口
-》该接口就是这么使用的。
-〉好像就会多次调用这个ondataavailable?
去搜搜:
WebAudio API ondataavailable
Stream capturing with MediaRecorder · TryCatch
还是应该改为:
ondataavailable:只是保存数据
stop:才去处理数据
结果用了代码:
<code> function testMediaStreamRecorder(mediaStream){ console.log("testMediaStreamRecorder: mediaStream=%o", mediaStream); var mediaStreamRecorder = new MediaStreamRecorder(mediaStream); console.log("mediaStreamRecorder=%o", mediaStreamRecorder); const AUDIO_TYPE = { webm: { mimeType: 'audio/webm', suffix: ".webm" }, wav: { mimeType: 'audio/wav', suffix: ".wav" }, pcm: { mimeType: 'audio/pcm', suffix: ".pcm" }, ogg: { mimeType: 'audio/ogg', suffix: ".ogg" } } // var curAudioType = AUDIO_TYPE.webm; var curAudioType = AUDIO_TYPE.wav; // var curAudioType = AUDIO_TYPE.pcm; // var curAudioType = AUDIO_TYPE.ogg; console.log("curAudioType=%o", curAudioType); const recordedBlobChunks = []; mediaStreamRecorder.mimeType = curAudioType.mimeType; mediaStreamRecorder.ondataavailable = function (recordedBlob) { console.log("mediaStreamRecorder.ondataavailable: recordedBlob=%o", recordedBlob); if (recordedBlob.size > 0) { recordedBlobChunks.push(recordedBlob); console.log("recordedBlobChunks=%o", recordedBlobChunks); } }; $( "#stopSpeak" ).on( "click", function() { console.log("#stopSpeak clicked"); mediaStreamRecorder.stop(); }); mediaStreamRecorder.stop = function() { console.log("mediaStreamRecorder stoped"); console.log("recordedBlobChunks=%o", recordedBlobChunks); const recordedBlob = new Blob(recordedBlobChunks); console.log("recordedBlob=%o", recordedBlob); const blobUrl = URL.createObjectURL(recordedBlob); console.log("blobUrl=%o", blobUrl); playRecordedAudio(blobUrl); downloadRecordedAudio(blobUrl, curAudioType.suffix); }; if ((curAudioType == AUDIO_TYPE.wav) || (curAudioType == AUDIO_TYPE.pcm)) { // mediaStreamRecorder.recorderType = StereoAudioRecorder; // console.log("set recorderType to StereoAudioRecorder when wav"); console.log("seems wav type need trigger then can start record"); $( "#startSpeak" ).on( "click", function() { console.log("#startSpeak clicked"); mediaStreamRecorder.start(); console.log("mediaStreamRecorder started by button click"); }); } else { mediaStreamRecorder.start(); console.log("directly mediaStreamRecorder started by code"); } } </code>
也还是有问题:
stop后,还是会执行:ondataavailable
WebAudio API ondataavailable after stop
WebAudio still ondataavailable after stop
WebAudio ondataavailable
官网的api,好像是这个:
MediaRecorder.ondataavailable – Web APIs | MDN
那在stop后,不应该还继续会调用到ondataavailable才对啊
突然发现,貌似是自己的此处代码中的:
<code>mediaStreamRecorder.stop = function() { </code>
应该改为:
<code>mediaStreamRecorder.onstop = function() { </code>
才对啊
另看到示例代码:
https://github.com/streamproc/MediaStreamRecorder/blob/master/demos/audio-recorder.html
中有:
<code> document.querySelector('#stop-recording').onclick = function() { this.disabled = true; mediaRecorder.stop(); mediaRecorder.stream.stop(); document.querySelector('#pause-recording').disabled = true; document.querySelector('#start-recording').disabled = false; }; </code>
即:除了
mediaRecorder.stop()
还要:
mediaRecorder.stream.stop();
或许就是我此处只mediaRecorder.stop(),但是还会ondataavailable的原因?
去加上试试
但是加了onstop后,的确就不再继续ondataavailable了
但是点击下载,却没有下载到wav文件,而是index.html文件
看来是没有执行到onstop
然后另外,再去参考
https://github.com/streamproc/MediaStreamRecorder/blob/master/demos/audio-recorder.html
好像就没有stop或onstop的event函数
WebRTC Audio Recording using MediaStreamRecorder
的确是:此处demo中没有写stop的event,只有
mediaRecorder.start(3000);
每隔3秒保存一次
但是官网
https://github.com/streamproc/MediaStreamRecorder#record-audiowav
已经说了用:
How to manually stop recordings?
mediaRecorder.stop();
了啊
也有
https://github.com/streamproc/MediaStreamRecorder#onstop
onstop的
后来明白了之前为何stop后还继续ondataavailable
因为:
<code>mediaStreamRecorder.stop = function() { </code>
就是重写了stop函数,没有真正的调用原先的mediaStreamRecorder的stop。
但是此处代码:
<code> mediaStreamRecorder.ondataavailable = function (recordedBlob) { console.log("mediaStreamRecorder.ondataavailable: recordedBlob=%o", recordedBlob); if (recordedBlob.size > 0) { recordedBlobChunks.push(recordedBlob); console.log("recordedBlobChunks=%o", recordedBlobChunks); } }; mediaStreamRecorder.onstop = function() { console.log("mediaStreamRecorder.onstop"); console.log("recordedBlobChunks=%o", recordedBlobChunks); const recordedBlob = new Blob(recordedBlobChunks); console.log("recordedBlob=%o", recordedBlob); const blobUrl = URL.createObjectURL(recordedBlob); console.log("blobUrl=%o", blobUrl); playRecordedAudio(blobUrl); downloadRecordedAudio(blobUrl, curAudioType.suffix); }; $( "#stopSpeak" ).on( "click", function() { console.log("#stopSpeak clicked"); console.log("now call mediaStreamRecorder.stop"); mediaStreamRecorder.stop(); }); </code>
却没有执行到mediaStreamRecorder.onstop
转载请注明:在路上 » 【未解决】MediaStreamRecorder中stop后还会执行ondataavailable