情形一:浏览器未进行过声音文件的播放,直接最小化,然后触发去播放声音文件,声音文件无法播放。此时再将浏览器放大,触发播放声音文件的方法,声音正常播放。
情形二:浏览器最大化且进行过声音文件的播放,然后最小化,再去触发播放声音文件,可以正常播放。
代码如下
canplaythroughListener;
init(fileName: string) {
let fileUrl = '/' + fileName
this._source.setAttribute("src", fileUrl)
// 再次加载相同的音频文件--重载
this._audio.load()
this._audio.autoplay = true;
return new Promise((resolve, reject) => {
this.canplaythroughListener = () => {
console.log('this._audio.readyState', this._audio.readyState);
try {
if (this._audio.readyState == this._audio.HAVE_ENOUGH_DATA) {
this._audio.play()
.then(()=>{
this._audio.play()
console.log('this._audio', this._audio)
resolve(undefined)
})
.catch((err)=>{
if (err.name == 'NotAllowedError') {
console.log('NotAllowedError')
reject()
}
})
}
} catch (error) {
console.log('catch-error')
}
};
this._audio.addEventListener("canplaythrough", this.canplaythroughListener);
// test
this._audio.addEventListener('load', () => {
console.log('load~~~~')
this._audio.addEventListener('canplaythrough', function() {
console.log('Video can play through');
});
});
this._audio.addEventListener('error', function() {
console.log('Error loading video');
});
})
}
测试结果如下:当处于情形一的时候,audio对象的addEventListener事件未添加成功。当处于情形二的时候,addEventListener事件添加成功,内部方法也可正常执行。
猜测:声音只要正常播放过,全局即存在this._audio.addEventListener("canplaythrough"),后续哪怕浏览器最小化,也可以正常播放。
请问造成浏览器初始化状态未最小化且未进行过声音文件的播放,执行声音文件的播放方法且无法播放的原因是什么,有什么解决方案?
init(fileName: string) {
let fileUrl = '/' + fileName
this._source.setAttribute("src", fileUrl)
this._audio.load()
document.addEventListener('visibilitychange', () => {
if (!document.hidden && this._audio.paused) {
this._audio.play().catch(err => console.log('可见性变化时播放失败:', err));
}
});
return new Promise((resolve, reject) => {
// ... existing code ...
this.canplaythroughListener = () => {
console.log('this._audio.readyState', this._audio.readyState);
try {
if (this._audio.readyState == this._audio.HAVE_ENOUGH_DATA) {
if (!document.hidden) {
this._audio.play()
.then(()=>{
console.log('音频播放成功');
resolve(undefined);
})
.catch((err)=>{
console.log('播放错误:', err);
if (err.name == 'NotAllowedError') {
// 存储播放意图,等待用户交互
this._pendingPlay = true;
console.log('需要用户交互才能播放');
// 不立即reject,等待用户交互
} else {
reject(err);
}
});
} else {
// 页面不可见,标记为待播放
this._pendingPlay = true;
console.log('页面不可见,等待页面可见后播放');
}
}
} catch (error) {
console.log('catch-error', error);
reject(error);
}
};
// ... existing code ...
//监听器
const userInteractionHandler = () => {
if (this._pendingPlay) {
this._audio.play()
.then(() => {
this._pendingPlay = false;
resolve(undefined);
})
.catch(err => console.log('用户交互后播放失败:', err));
}
};
['click', 'touchend', 'keydown'].forEach(eventType => {
document.addEventListener(eventType, userInteractionHandler, {once: true});
});
});
}
浏览器自动播放策略限制
现代浏览器(Chrome >=66、Safari等)对音频自动播放有严格限制。当以下条件同时满足时,音频会被阻止:
事件监听时机问题
在情形一中,当浏览器最小化时:
this._audio.addEventListener("canplaythrough", this.canplaythroughListener)
可能由于浏览器节流机制,导致事件监听器未能及时挂载
双play()
调用
代码中存在嵌套的this._audio.play()
调用:
this._audio.play().then(() => {
this._audio.play() // 重复调用
})
这可能导致NotAllowedError
(当浏览器认为这是非用户触发的自动播放时)
方案一:遵循自动播放策略(推荐)
// 增加用户手势监听
document.addEventListener('click', initAudioContext, { once: true })
async function initAudioContext() {
// 在用户交互后初始化音频
await this._audio.play().catch(e => console.log('预备播放失败'))
this._audio.pause()
this._audio.currentTime = 0
}
方案二:优化事件监听逻辑
// 修改后的 init 方法
init(fileName: string) {
// 清除旧监听器防止重复
this._audio.removeEventListener("canplaythrough", this.canplaythroughListener)
// 使用一次性监听器
const canPlayHandler = () => {
this._audio.removeEventListener("canplaythrough", canPlayHandler)
this.handlePlay().then(resolve).catch(reject)
}
this._audio.addEventListener("canplaythrough", canPlayHandler)
}
private async handlePlay() {
try {
// 单次播放调用
await this._audio.play()
console.log('Playback started')
} catch (err) {
if (err.name === 'NotAllowedError') {
console.warn('需要用户交互后才能播放')
// 可在此处添加点击按钮提示
}
}
}
方案三:使用 Web Audio API(更底层控制)
const audioContext = new (window.AudioContext || window.webkitAudioContext)()
const source = audioContext.createMediaElementSource(this._audio)
source.connect(audioContext.destination)
// 恢复音频上下文(需要用户手势)
document.addEventListener('click', () => {
if (audioContext.state === 'suspended') {
audioContext.resume()
}
})
NotAllowedError
并提供用户反馈资源管理:
// 页面可见性变化处理
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
this._audio.pause()
} else {
this._audio.play().catch(() => {})
}
})
预加载策略:
<!-- 添加 preload 元数据 -->
audio preload="auto"></audio>
遵循这些修改后,当浏览器从最小化状态恢复时,通过visibilitychange
事件触发重新播放,配合用户手势验证,可解决初始化状态下的播放问题。
B站网页视频暂停后再播放就会一直缓冲.网络良好不卡,换浏览器也不行。 只有重启可以解决问题
本文向大家介绍vue中解决chrome浏览器自动播放音频和MP3语音打包到线上的实现方法,包括了vue中解决chrome浏览器自动播放音频和MP3语音打包到线上的实现方法的使用技巧和注意事项,需要的朋友参考一下 一、vue中解决chrome浏览器自动播放音频 需求 有新订单的时候,页面自动语音提示和弹出提示框; 问题 chrome浏览器在18年4月起,就在桌面浏览器全面禁止了音视频的自动播放功能。
我希望我的应用程序从SD卡播放. ogg音频文件,但媒体播放器和SoundPool无法为某些特定的ogg文件执行此操作。我有问题要播放的示例声音属于Telegram。下面的代码适用于其他ogg文件和mp3格式,但在播放此类声音时会给我错误。 示例文件下载链接:http://www.mediafire.com/download/fxr4z4hh7b2gv50/test.ogg 它引发以下异常:
问题内容: 我正在用HTML5和Javascript制作游戏。 如何通过Javascript播放游戏音频? 问题答案: 如果您不想弄乱HTML元素: 这使用了接口,该接口播放音频的方式与element相同。 如果需要更多功能,我使用了howler.js库,发现它简单实用。
本文向大家介绍浏览页面时如何保持音频播放?,包括了浏览页面时如何保持音频播放?的使用技巧和注意事项,需要的朋友参考一下 要在浏览页面时继续加载音频以播放,请尝试以下操作: 使用Ajax加载内容 History API也可以用于更改URL,而无需重新加载页面。 应使用History.js在多个浏览器中保持一致的行为。 将有三个参数: 状态对象用于由创建的新条目 标题:您可以传递简短标题 U
我的主页有一个有音频的视频背景。但音频只能使用firefox自动播放。如果我要在其他网站(如chrome或IE)上打开我的主页,音频将听不到。
本文向大家介绍IOS中微信小程序播放缓存的音频文件的方法,包括了IOS中微信小程序播放缓存的音频文件的方法的使用技巧和注意事项,需要的朋友参考一下 很多时候我们都想把数据预先缓存到本地,节省带宽。但是最近在处理微信小程序播放缓存到本地的音频文件的时候,遇到一些小问题,然后对于安卓和IOS需要采用不同的播放策略。 首先,如果哪怕用audio标签来播放在线的音频文件,假如服务端没有实现断点续传,IOS
我正在开发一个包含一些音频播放器的RecyclerView的应用程序。应用程序将下载。3gp文件(如果尚未下载)。 当我单击playAudio按钮时,音频未被播放。 这是我的适配器代码: 我怎样才能解决这个问题?