对象方法中的本地变量音频无法播放

时间:2018-10-30 06:17:46

标签: javascript html audio

我正在做一个游戏,我想在事件发生时播放声音。我目前有一个如下所示的对象:

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

然后我正在播放如下声音:

soundObject.invaderShoot();

但是,当我尝试执行此操作时,它会出现以下错误:

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.

然后在方法中突出显示此行:

audio.play();

出什么问题了?我已经搜索了GitHub线程和Stack Overflow问题,但是找不到错误的定义,更不用说如何解决了。

我该如何解决?

编辑:

只允许我使用.wav文件,因为那是我的代码托管服务允许的唯一文件格式。

2 个答案:

答案 0 :(得分:1)

Audio.play()返回一个Promise,当成功开始播放后,Promise将被解决。由于任何原因(例如权限问题)而无法开始播放,将导致诺言被拒绝。

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

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

就自动播放而言,您可能需要根据新的浏览器策略在HTML中添加AudoContext。 https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#webaudio

编辑

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

答案 1 :(得分:1)

从附件的错误看来,问题似乎是由于默认情况下禁用了音频/视频自动播放。这当然对用户来说是实用的,因为尽管这样做可以减少滥用量。但是对于您的情况,这意味着您不能即时创建音频对象。

相反,您应该事先创建它,并仅在需要时切换URL /恢复音频。 所附票证中的以下片段似乎很有希望。

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