You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 08:33:25