我正在做一个游戏,我想在事件发生时播放声音。我目前有一个如下所示的对象:
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
文件,因为那是我的代码托管服务允许的唯一文件格式。
答案 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();
});
}