Playwright如何检测网站内非DOM音频是否处于播放状态
Playwright 全局音频播放状态检测方案(适配未挂载DOM的Audio实例)
实现原理
通过new Audio()创建的音频实例即使不挂载到DOM树,也属于HTMLMediaElement实例,常规遍历DOM查找audio标签的方案无法捕获这类实例,最稳定的方案是在页面初始化阶段劫持原生Audio构造函数,全量追踪所有音频实例的播放状态。
1. 提前注入实例追踪逻辑
在页面跳转、业务JS加载前,通过Playwright的addInitScript注入追踪代码,避免遗漏早期创建的音频实例:
// 注意:这行代码要在page.goto()调用前执行 await page.addInitScript(() => { // 全局存储正在播放的音频实例 window.__activeAudioSet = new Set(); const NativeAudio = window.Audio; // 重写原生Audio构造函数 window.Audio = function (...args) { const instance = new NativeAudio(...args); // 播放时加入活跃集合 instance.addEventListener('play', () => { window.__activeAudioSet.add(instance); }); // 暂停、播放结束、资源清空、报错时移出活跃集合 const deactivate = () => window.__activeAudioSet.delete(instance); instance.addEventListener('pause', deactivate); instance.addEventListener('ended', deactivate); instance.addEventListener('emptied', deactivate); instance.addEventListener('error', deactivate); return instance; }; // 保留原构造函数原型,避免业务代码的instanceof判断失效 window.Audio.prototype = NativeAudio.prototype; });
2. 调用检测逻辑
直接在page.evaluate中读取全局活跃集合的状态即可,无需遍历DOM:
const isAudioPlaying = await page.evaluate(() => { // 检测被追踪的Audio实例播放状态 const hasTrackedAudioPlaying = window.__activeAudioSet?.size > 0; // 可选兜底:如果业务用到Web Audio API,可补充检测音频上下文状态 let hasWebAudioPlaying = false; if (window.__activeAudioContexts) { hasWebAudioPlaying = window.__activeAudioContexts.size > 0; } return hasTrackedAudioPlaying || hasWebAudioPlaying; });
注意点
- 注入追踪脚本的时机必须早于业务代码执行,否则业务代码提前创建的Audio实例不会被劫持追踪,导致检测结果不准。
- 未挂载到DOM树的媒体元素触发的事件不会冒泡到window,因此无法通过全局事件监听捕获播放状态,劫持构造函数是兼容性、准确率最高的方案。
- 该方案同时兼容挂载到DOM的
audio、video元素播放状态检测,不需要额外写DOM遍历逻辑。
内容的提问来源于stack exchange,提问作者Woww
相关产品推荐
相关产品推荐

