播放AUDIO时未捕获Google Chrome(承诺)DOMException

时间:2019-02-16 02:25:01

标签: javascript html

默认情况下,Google Chrome浏览器会阻止播放音频/视频。我已经查找了问题,但是我只能找到视频的解决方案,并且希望音频循环播放。这是我的代码:

var audio = new Audio('audio/audio.mp3'); audio.play(); audio.loop = true;

由于新政策或其他原因,这只会在Google Chrome上导致“未捕获(承诺)的DOMException”。有人可以帮忙吗?

4 个答案:

答案 0 :(得分:3)

由于未处理错误,因此您收到未捕获的异常。

https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play

音频是一个HTMLMediaElement对象,并且play()方法返回一个promise。因此,我建议处理该错误。

var promise = audio.play();
if (promise) {
    //Older browsers may not return a promise, according to the MDN website
    promise.catch(function(error) { console.error(error); });
}

可能是两个错误之一:

NotSupportedError

这意味着浏览器不支持音频源(可能由于音频格式)

NotAllowedError

这是我怀疑您正在触发的那个。这意味着用户需要显式触发audio.play(),因此该方法仅在响应用户生成的事件(如单击事件)时才可用。

文档:

  

用户代理(浏览器)或操作系统不允许在当前上下文或情况下播放媒体。例如,如果浏览器要求用户通过单击“播放”按钮显式启动媒体播放,则可能会发生这种情况。

答案 1 :(得分:1)

浏览器要求用户通过单击“播放”按钮来显式启动媒体播放。下面的代码解决了您的问题。

<!DOCTYPE html>
<html>
<head>
<title>Play MP3 music on web</title>
<script>
function playMusic(){
    var promise = document.querySelector('audio').play();
    if (promise !== undefined) {
        promise.then(_ => {
            // Autoplay started!
        }).catch(error => {
            // Autoplay was prevented. Show a "Play" button so that user can start playback.
        });
    }
}
</script> 
</head>  
<body>
    <p>Play MP3</p>
    <input type="button" value="play music" onClick="playMusic();">
    <audio loop id="sound">
        <source src="audio/audio.mp3" type="audio/mpeg">
        <p>Browser doesn't support html5</p>
    </audio>
</body>
</html>

答案 2 :(得分:0)

此代码可能会有所帮助。它将在第一个用户与DOM交互时触发自动播放(并循环播放)。

<!doctype html>

<html lang="fr">
<head>
    <meta charset="utf-8">
</head>

<style>html,body{height:100%}</style>

<body>


    <!-- SOUND -->
    <audio loop id="sound">
        <source src="sound.mp3" type="audio/mpeg">
        <p>Browser doesn't support html5</p>
    </audio>


    <!-- CONTENT -->
    <button onClick="audio_manager.play()">Play sound</button>
    <button onClick="document.querySelector('body').style.backgroundColor = '#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6);">Do something else</button>
    <ol id="text"><li>Autoplay will be start on user first interaction with body (click anywhere to test)</li></ol>


    <!-- JS SCRIPT -->
    <script>
        var audio_manager = {

            // Variables
            user_has_interacted: false,
            detection_is_active: false,


            /**
             * Init function
             * 
             * Detect first user's interaction
             */ 

            init: function(){

                // If already detecting => return
                if( audio_manager.detection_is_active){
                    return false;
                }

                // Detection active
                audio_manager.detection_is_active = true;

                // Set up eventListener for user's first interaction
                document.querySelector('body').addEventListener('click', audio_manager.detect_first_interaction, true);

            },


            detect_first_interaction: function(e) {

                // Set user_has_interacted to true
                audio_manager.user_has_interacted = true;

                // Remove listener
                document.querySelector('body').removeEventListener(e.type, audio_manager.detect_first_interaction, true);

                // Play media (= Autoplay)
                audio_manager.play();

                // Log first detection
                document.getElementById('text').innerHTML += "<li>Autoplay, first interaction detected on " + e.type + " on " + e.target.nodeName + "</li>";
            },


            /**
             * Play function
             * 
             * Play "sound" or init first user's detection
             */ 

            play: function(){

                // If user interaction, play media
                if(audio_manager.user_has_interacted){
                    document.getElementById('sound').play();                    
                    return true;
                }

                // Init detection
                audio_manager.init();
            }

        };

        // Load autoplay
        audio_manager.play();

        // Uncomment next line to test autoplay on load without workaround => throw error "Uncaught (in promise) DOMException" or "NotAllowedError: The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission."
        //document.getElementById('sound').play();  
    </script>

    </body>
</html>

这不是一个完美的解决方法,但在某些情况下很有用。

答案 3 :(得分:0)

我也不得不处理这个问题,当你想触发浏览器中的所有异常时,这很烦人,它触发了音频异常。

所以,我在纯 javascript 中找到的最佳解决方案:

let has_clicked;
window.addEventListener('click', () => {has_clicked = true;});
window.addEventListener('touchstart', () => {has_clicked = true;});

function playSound() {
    if (!has_clicked)
        return;

    // insert the play code, for ex yours:
    let audio = new Audio('music/test.mp3'); audio.play(); audio.loop = true;
}