折腾:
【未解决】换用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