6
votes

Google Chrome Uncaught (promis) DOMException lors de la lecture AUDIO

Chrome bloque la lecture automatique de l'audio / vidéo. J'ai recherché le problème, mais je n'ai trouvé que des solutions pour la lecture automatique de la vidéo et mon cas d'utilisation nécessite la lecture automatique de l'audio. Voici mon code:

let audio = new Audio('music/test.mp3'); audio.play(); audio.loop = true;

Il en résulte une "DOMException non interceptée (en promesse)" uniquement sur les navigateurs Chromium en raison des nouvelles règles.


1 commentaires

Je crois en chrome audio.play () ne peut être utilisé que dans un événement déclenché par l'utilisateur, comme à l'intérieur d'un événement de clic. Il est difficile de dire que c'est le cas ici sans voir plus de code cependant.


3 Réponses :


12
votes

Vous recevez une exception non interceptée car vous ne gérez pas d'erreur.

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

Audio est un objet HTMLMediaElement et la méthode play() renvoie une promesse. Par conséquent, je recommande de gérer l'erreur.

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); });
}

Une des deux erreurs est possible:

NotSupportedError

Cela signifie que la source audio n'est pas prise en charge par le navigateur (probablement en raison du format audio)

NotAllowedError

C'est celui que je soupçonne que vous déclenchez. Cela signifie que l'utilisateur doit déclencher explicitement audio.play() , donc la méthode n'est utilisable que si elle est en réponse à un événement généré par l'utilisateur tel qu'un événement de clic.

Documents:

L'agent utilisateur (navigateur) ou le système d'exploitation n'autorise pas la lecture des médias dans le contexte ou la situation actuelle. Cela peut se produire, par exemple, si le navigateur demande à l'utilisateur de démarrer explicitement la lecture multimédia en cliquant sur un bouton «lecture».


0 commentaires

0
votes

Ce code peut vous aider. Il déclenchera la lecture automatique (et la boucle) avec l'interaction d'un premier utilisateur avec le 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>

Pas une solution de contournement parfaite, mais utile dans certains cas.


0 commentaires

1
votes

Le navigateur demande à l'utilisateur de démarrer explicitement la lecture multimédia en cliquant sur un bouton «lecture». Le code ci-dessous résout votre problème.

<!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>


1 commentaires

Je l'ai découvert moi-même, mais je voulais qu'il joue sans interaction de l'utilisateur.