折腾:
【已解决】web端html+js中如何调用麦克风获取用户语音输入说话
期间,通过:
【已解决】js中MediaRecorder录音支持哪些音频格式
和
【已解决】js的MediaRecorder的浏览器支持情况和相关polyfill
发现:
官网的html的MediaRecorder,只有Chrome和Firefox支持,Safari浏览器不支持。
且Chrome还不支持wav等常见格式。
现在发现:
MediaStreamRecorder不仅能解决支持多个浏览器的问题,且好像:
https://github.com/streamproc/MediaStreamRecorder#record-audiowav
还支持wav?
好像还支持:
<code> $allowed = array( 'webm', 'wav', 'mp4', 'mp3', 'ogg' ); </code>
mp3和ogg?
看到是支持:
<code>// audio: audioRecorder.mimeType = 'audio/webm'; // MediaRecorderWrapper audioRecorder.mimeType = 'audio/ogg'; // MediaRecorderWrapper audioRecorder.mimeType = 'audio/wav'; // StereoAudioRecorder audioRecorder.mimeType = 'audio/pcm'; // StereoAudioRecorder </code>
所以,此处还是去换用:MediaStreamRecorder
demo:
WebRTC Audio Recording using MediaStreamRecorder
source:
https://github.com/streamproc/MediaStreamRecorder/blob/master/demos/audio-recorder.html
通过:
<code><!-- or link specific release --> <script src="https://github.com/streamproc/MediaStreamRecorder/releases/download/1.3.4/MediaStreamRecorder.js"></script> </code>
打开:
Releases · streamproc/MediaStreamRecorder
果然找到了。最新的是:
MediaStreamRecorder v1.3.4
下载得到:

然后放到代码里,试试效果:
<code><script src="js/MediaStreamRecorder/MediaStreamRecorder.min.js"></script> </code>

<code>
function downloadRecordedAudio(blobUrl, suffix){
console.log("downloadRecordedAudio: blobUrl=%s, suffix=%s", blobUrl, suffix);
$("#downloadSpeakAudio").attr("href", blobUrl);
var curDate = new Date();
console.log("curDate=%o", curDate);
var curDatetimeStr = curDate.Format("yyyyMMdd_HHmmss");
console.log("curDatetimeStr=%o", curDatetimeStr);
var recordedAudioFilename = curDatetimeStr + suffix;
console.log("recordedAudioFilename=%o", recordedAudioFilename);
$("#downloadSpeakAudio").attr("download", recordedAudioFilename);
}
function playRecordedAudio(blobUrl){
console.log("playRecordedAudio: blobUrl=%s", blobUrl);
var inputAudio = document.getElementById('inputAudio');
// var inputAudio = $("#inputAudio");
console.log("inputAudio=o", inputAudio);
inputAudio.src = blobUrl;
console.log("inputAudio.src=%s", inputAudio.src);
inputAudio.play();
}
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;
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();
});
mediaStreamRecorder.start();
console.log("mediaStreamRecorder started");
}
function onSuccessGetUserMedia(mediaStream) {
console.log("handleSuccess: mediaStream=%o", mediaStream);
testMediaStreamRecorder(mediaStream);
}
function testAudioInput(){
console.log("testAudioInput");
var mediaConstraints = {
audio: true,
video: false
};
console.log("mediaConstraints=%o", mediaConstraints);
navigator.mediaDevices
.getUserMedia(mediaConstraints)
.then(onSuccessGetUserMedia)
.catch(function (error) {
console.error("Try getUserMedia error: %o", error);
//Chorome click not allow -> DOMException: Permission denied
//Safari -> Trying to call getUserMedia from an insecure document.
});
}
</code>效果是OK的,和之前一样的:

再去换成其他格式,比如wav试试
结果提示:
<code>curAudioType={mimeType: "audio/wav", suffix: ".wav"}
MediaStreamRecorder.min.js:3 The AudioContext was not allowed to start. It must be resume (or created) after a user gesture on the page. https://goo.gl/7K7WLu
</code>
不能录音。
看到:
<code>recorderType You can force StereoAudioRecorder or WhammyRecorder or similar recorders on Firefox or Edge; even on Chrome and Opera. All browsers will be using your specified recorder: // force WebAudio API on all browsers // it allows you record remote audio-streams in Firefox // it also works in Microsoft Edge mediaRecorder.recorderType = StereoAudioRecorder; // force webp based webm encoder on all browsers mediaRecorder.recorderType = WhammyRecorder; // force MediaRecorder API on all browsers // Chrome Canary/Dev already implemented MediaRecorder API however it is still behind a flag. // so this property allows you force MediaRecorder in Chrome. mediaRecorder.recorderType = MediaRecorderWrapper; // force GifRecorder in all browsers. Both WhammyRecorder and MediaRecorder API will be ignored. mediaRecorder.recorderType = GifRecorder; </code>
// audio:
audioRecorder.mimeType = ‘audio/webm’; // MediaRecorderWrapper
audioRecorder.mimeType = ‘audio/ogg’; // MediaRecorderWrapper
audioRecorder.mimeType = ‘audio/wav’; // StereoAudioRecorder
audioRecorder.mimeType = ‘audio/pcm’; // StereoAudioRecorder
难道要强制recorderType?
<code> mediaStreamRecorder.mimeType = curAudioType.mimeType;
if (curAudioType == AUDIO_TYPE.wav) {
mediaStreamRecorder.recorderType = StereoAudioRecorder;
console.log("set recorderType to StereoAudioRecorder when wav");
}
</code>结果:
问题依旧。
换成pcm:
<code>var curAudioType = AUDIO_TYPE.pcm; </code>
结果同样现象,不支持。
换成ogg:
<code>var curAudioType = AUDIO_TYPE.ogg; </code>
结果:
<code>Passing following params over MediaRecorder API. {mimeType: "audio/webm"}
</code>
即:
自动换成webm了。。。
想起了了,对于上面的wav提示:
<code>The AudioContext was not allowed to start. It must be resume (or created) after a user gesture on the page. https://goo.gl/7K7WLu </code>
看了不能代码主动start,要放到别的,比如按钮点击,才能触发
【未解决】MediaStreamRecorder中stop后还会执行ondataavailable
期间看到了:
MediaStreamRecorder/audio-recorder.html at master · streamproc/MediaStreamRecorder
<code>var recorderType = document.getElementById('audio-recorderType').value;
if (recorderType === 'MediaRecorder API') {
mediaRecorder.recorderType = MediaRecorderWrapper;
}
if (recorderType === 'WebAudio API (WAV)') {
mediaRecorder.recorderType = StereoAudioRecorder;
mediaRecorder.mimeType = 'audio/wav';
}
if (recorderType === 'WebAudio API (PCM)') {
mediaRecorder.recorderType = StereoAudioRecorder;
mediaRecorder.mimeType = 'audio/pcm';
}
// don't force any mimeType; use above "recorderType" instead.
// mediaRecorder.mimeType = 'audio/webm'; // audio/ogg or audio/wav or audio/webm
</code>意思是:
我此处的,主动设置mimeType,是不好的做法,应该设置recorderType
-》内部会自动设置mimeType?
抽空去优化看看