最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【未解决】换用MediaStreamRecorder实现麦克风录音且支持多个浏览器和wav格式

JS crifan 3767浏览 0评论

折腾:

【已解决】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>&lt;!-- or link specific release --&gt;
&lt;script src="https://github.com/streamproc/MediaStreamRecorder/releases/download/1.3.4/MediaStreamRecorder.js"&gt;&lt;/script&gt;
</code>

打开:

Releases · streamproc/MediaStreamRecorder

果然找到了。最新的是:

MediaStreamRecorder v1.3.4

下载得到:

然后放到代码里,试试效果:

<code>&lt;script src="js/MediaStreamRecorder/MediaStreamRecorder.min.js"&gt;&lt;/script&gt;
</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 -&gt; DOMException: Permission denied
                //Safari -&gt; 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?

抽空去优化看看

转载请注明:在路上 » 【未解决】换用MediaStreamRecorder实现麦克风录音且支持多个浏览器和wav格式

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
89 queries in 0.166 seconds, using 22.09MB memory