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,由於咱們拿到的錄音數據流沒有定義長度,因此瀏覽器沒法解析出當前音頻的時長。html

相關問題連接參考資料 相關問題連接參考資料前端

如何解決

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('您的設備不能錄音');
        }
    }
}
複製代碼

這就是相關的簡單例子,實現方案大致就是這樣,(代碼我沒跑啊,直接是從業務中粘貼粘貼攢的),可是思路就是這樣,自測業務沒有問題,你們有問題能夠留言,一塊兒解決糾正html5

相關文章
相關標籤/搜索