web-dev-qa-db-fra.com

La variable audio locale dans la méthode objet ne joue pas

Je fais un jeu et je veux que des sons soient joués sur les événements qui se produisent. J'ai actuellement un objet qui ressemble à ci-dessous:

var soundObject = {
    invaderShoot: function() {
        var audio = new Audio("laser.wav");
        audio.play();
    },
    //Many more of the same method
};

Et puis je joue les sons comme ceci:

soundObject.invaderShoot();

Cependant, lorsque j'essaie de le faire, il se produit l'erreur suivante:

Unhandled Promise Rejection: NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.

Et cela revient à mettre en évidence cette ligne dans la méthode:

audio.play();

Quel est le problème? J'ai cherché dans les threads GitHub et les questions de débordement de pile, mais je ne trouve pas définition de ce qu'est l'erreur, et encore moins comment la corriger.

Comment dois-je résoudre ce problème?

Je ne suis autorisé qu'à utiliser .wav fichiers, car c'est le seul format de fichier autorisé par mon service d'hébergement de code.

5
Jack Bashford

Audio.play () renvoie une promesse qui est résolue lorsque la lecture a été lancée avec succès. Le fait de ne pas commencer la lecture pour une raison quelconque, comme des problèmes d'autorisation, entraîne le rejet de la promesse.

const playedPromise = audio.play();
if (playedPromise) {
        playedPromise.catch((e) => {
            if (e.name === 'NotAllowedError' ||
                e.name === 'NotSupportedError') {
                //console.log(e.name);
            }
        });
    }

Dans votre cas, il semble que votre navigateur/système d'exploitation ne permette pas la lecture automatique de l'audio. 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 oblige l'utilisateur à démarrer explicitement la lecture multimédia en cliquant sur un bouton "lecture". Ici est la référence.

En ce qui concerne la lecture automatique, vous devrez peut-être ajouter AudoContext dans votre code HTML conformément à la nouvelle politique du navigateur. https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#webaudio

ÉDITER

window.onload = function() {
  var context = new AudioContext();
  // Setup all nodes
  ...
}
context.resume().then(() => {
    audio.play();
    console.log('Playback resumed successfully');
  });
7
Narendra

D'après le bogue joint, il semble que le problème soit dû à la lecture automatique audio/vidéo désactivée par défaut. Bien sûr, cela est pratique pour l'utilisateur car il réduit la quantité d'abus, bien qu'il ajoute. Pour votre situation, cela signifie cependant que vous ne pouvez pas créer l'objet audio à la volée.

Au lieu de cela, vous devez le créer au préalable et simplement changer l'URL/reprendre l'audio lorsque vous en avez besoin. L'extrait suivant du ticket ci-joint semble prometteur.

// sm2 attaches the audio element as sound._a
let audio = sound._a;
audio.crossOrigin = 'anonymous';
sound._sourceNode = audioContext.createMediaElementSource(audio);
sound._sourceNode.connect(inputNode);

function play() {
  /**
   * If an AudioContext is created prior to the document receiving a
   * user gesture, it will be created in the "suspended" state, and
   * you will need to call resume() after a user gesture is
   * received.
   */
    audioContext.resume().then(() => {
        sound.play();
    });
}

https://github.com/scottschiller/SoundManager2/issues/178

2
Ish