对象方法中的局部变量音频未播放

Posted

技术标签:

【中文标题】对象方法中的局部变量音频未播放【英文标题】:Local variable audio in object method not playing 【发布时间】:2018-10-30 06:17:45 【问题描述】:

我正在制作游戏,我希望在发生的事件中播放声音。我目前有一个如下所示的对象:

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 文件,因为这是我的代码托管服务允许的唯一文件格式。

【问题讨论】:

所有浏览器都出现这种情况吗? 【参考方案1】:

Audio.play() 返回一个 Promise,当播放成功开始时该 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');
  );

【讨论】:

但是当你有const playedPromise = audio.play();,你会如何执行这个函数呢? play() 在您提供的代码中的什么位置? 您可以在代码中添加音频上下文并忽略承诺部分。 例如 是的,在 Safari11 之后,他们添加了这个限制,但他们允许一些例外,比如 Youtube 等。 它似乎工作,非常感谢!如果有任何问题,我会与您联系。【参考方案2】:

从附加的错误来看,问题似乎是由于默认情况下禁用了音频/视频自动播放。这对用户来说当然是实用的,因为它虽然增加了滥用的数量,但它减少了滥用的数量。但是,对于您的情况,这意味着您无法动态创建音频对象。

相反,您应该事先创建它,并在需要时简单地切换 URL/恢复音频。 随附票证中的以下 sn-p 似乎很有希望。

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

【讨论】:

以上是关于对象方法中的局部变量音频未播放的主要内容,如果未能解决你的问题,请参考以下文章

局部变量的赋值导致音频在 JUCE 中停止处理

面向对象(成员变量和局部变量的区别)

面向对象之成员变量和局部变量

成员变量和局部变量,静态变量的区别

局部变量和成员变量

成员变量与局部变量的区别