繁体   English   中英

在用户脚本中编辑音频元素音量

[英]Edit audio element volume in userscript

我正在编写一个用户脚本来尝试减少过于响亮的音频元素。 如何访问已创建但未放置在 DOM 中任何位置的音频元素?

在网站本身,它有类似的东西:

function () {
    var audioElement = document.createElement('audio');
    audioElement.setAttribute('src', 'http://www.example.com/sound.mp3');

    callbackFn = function() {
        audioElement.volume = way_too_high;
        audioElement.load();
        audioElement.play();
    };

    //...
}();

在我的用户脚本中,我想做一些类似的事情

function () {
    newCallbackFunction = function() {
        var audioElement = document.querySelector('audio'); // doesn't work, presumably because never added to DOM
        audioElement.volume = 0.1 * audioElement.volume;
        audioElement.load();
        audioElement.play();
    };

    // ...
}();

不过,我似乎无法访问它。 我真的不明白这些对象住在哪里。 如果它们不在 DOM 中,如何播放它们? 它们似乎只是存在于文档中的某个地方,因为它们可以播放,但我不清楚如何找到它们。

因为callbackFn是异步调用的,所以您可以在其volume属性上更改HTMLMediaElement.prototype的 setter,这样对具有您感兴趣的src的元素上的 volume 的更改将导致使用 volume 1 调用原始 setter /10th 默认调用的内容:

const { prototype } = HTMLMediaElement;
const { set: setter, get: getter } = Object.getOwnPropertyDescriptor(prototype, 'volume');
Object.defineProperty(prototype, 'volume', {
  get() {
    return getter.call(this);
  },
  set(arg) {
    const newArg = this.src.endsWith('/sounds/warframe_alarm.mp3')
    ? arg / 10
    : arg;
    setter.call(this, newArg);
  }
});

当然,请注意,这只是当您无法更改页面的现有 JS(例如使用用户脚本)时的一种 hack。

我正在寻找一种方法来访问网页中存在但尚未添加到 DOM 中的音频元素

很确定做这样的事情的唯一方法是使用像在使用createElement的页面代码运行之前运行的代码覆盖document.createElement类的黑客。

鉴于问题中的代码以及现代浏览器的autoplay策略已更改的事实,您可以找到DOM哪个元素在用户操作后开始媒体播放,您可以删除事件处理程序并将其替换为设置volume并调用原始的函数处理程序,例如

<!DOCTYPE html>
<html>

<head>
</head>

<body>
  click
  <script>
    (function() {
      var audioElement = document.createElement('audio');
      audioElement.setAttribute('src', 'https://upload.wikimedia.org/wikipedia/commons/6/6e/Micronesia_National_Anthem.ogg');

      callbackFn = function() {
        audioElement.load();
        audioElement.play();
      };
      document.onclick = callbackFn;

      //...
      function intercept(volume, audioElement) {
        const fn = document.onclick;
        document.onclick = null;
        document.onmouseup = function() {
          audioElement.volume = volume;
          fn();
        };
      }

      intercept(.2, audioElement)
    })();
  </script>
</body>

</html>

plnkr https://plnkr.co/edit/fNlhODuwC5Z0jXchoWBE?p=preview

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM