JS实现前端录音,并解决其中duration为Infinity以及播放触发ended问题

前端js调用浏览器录音,实现前端录音

 if (navigator.mediaDevices.getUserMedia) {
                    const constraints = {
                        audio: true
                    };
                    let chunks = [];
                    navigator.mediaDevices.getUserMedia(constraints)
                        .then((stream) => {
                            this.recorder = new MediaRecorder(stream);

                            this.recorder.onstop = () => {
                                const blob = new Blob(chunks, {
                                    type: 'audio/ogg; codecs=opus'
                                });

                                chunks = [];
                                const audioURL = URL.createObjectURL(blob);
                                this.audio.src = audioURL;

                                this.audio.oncanplay = function(e) {
                                    console.error(this.duration, e);
                                    this.play();
                                };
                                this.submitRecord(blob);
                            };
                            this.recorder.ondataavailable = function(e) {
                                chunks.push(e.data);
                            };
                        })
                        .catch((err) => {
                            this.cantRecord = false;
                            console.error('您的设备不能录音', err);
                        });
                } else {
                    this.cantRecord = false;
                    console.error('您的设备不能录音');
                }
复制代码

但是这样写会遇到问题,我们在获取获取audio的duration时候会发现 duration 是Infinity? 这是如果我们动态的展示录音时间时候就会有问题。首先明确一下这是chrome浏览器自己的存在的一个bug,因为我们拿到的录音数据流没有定义长度,所以浏览器无法解析出当前音频的时长。

相关问题链接参考资料 相关问题链接参考资料

如何解决

    formatePlayerDuration() {
        this.player.onloadedmetadata = e => {
            const audio = e.target;
            const audioDuration = audio.duration;
            if (audioDuration === Infinity) {
                audio.currentTime = 1e101;
                audio.ontimeupdate = function () {
                    this.ontimeupdate = () => {
                        return;
                    };
                    // 不重新设置currtTime,会直接触发audio的ended事件,因为之前将currentTime设置成了一个比音频时长还大的值。所以要将currentTime重置为初始状态。
                    // 注: 这里有一个问题,直接设置为0 是不起作用的。需要重新设置一下audio.currentTime = 1e101;然后再设置为0
                    audio.currentTime = 1e101;
                    audio.currentTime = 0;
                };
            }
        };
    }
复制代码

完整代码

const recorder = {
    init() {
        this.initRecordPlayer();
        this.initRecorder();
        this.formatePlayerDuration();
    },
    initRecordPlayer() {
        this.player = document.createElement('audio');
    },
    formatePlayerDuration() {
        this.player.onloadedmetadata = e => {
            const audio = e.target;
            const audioDuration = audio.duration;
            if (audioDuration === Infinity) {
                audio.currentTime = 1e101;
                audio.ontimeupdate = function () {
                    this.ontimeupdate = () => {
                        return;
                    };
                    // 不重新设置currtTime,会直接触发audio的ended事件,因为之前将currentTime设置成了一个比音频时长还大的值。
                    // 注: 这里有一个问题,直接设置为0 是不起作用的。需要重新设置一下audio.currentTime = 1e101;然后再设置为0
                    audio.currentTime = 1e101;
                    audio.currentTime = 0;
                };
            }
        };
    },
    initRecorder() {
        if (navigator.mediaDevices.getUserMedia) {
            const constraints = {
                audio: true
            };
            let chunks = [];
            navigator.mediaDevices.getUserMedia(constraints)
                .then((stream) => {
                    this.recorder = new MediaRecorder(stream);
                    this.recorder.onstop = () => {
                        const blob = new Blob(chunks, {
                            type: 'audio/ogg; codecs=opus'
                        });
                        chunks = [];
                        const audioURL = URL.createObjectURL(blob);
                        this.audio.src = audioURL;
                        // 录完自动播放
                        this.audio.oncanplay = function (e) {
                            this.play();
                        };
                    };
                    this.recorder.ondataavailable = function (e) {
                        chunks.push(e.data);
                    };
                })
                .catch((err) => {
                    console.error('您的设备不能录音', err);
                });
        } else {
            console.error('您的设备不能录音');
        }
    }
}
复制代码

这就是相关的简单例子,实现方案大体就是这样,(代码我没跑啊,直接是从业务中粘贴粘贴攒的),但是思路就是这样,自测业务没有问题,大家有问题可以留言,一起解决纠正

你可能感兴趣的:(JS实现前端录音,并解决其中duration为Infinity以及播放触发ended问题)