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

问题描述 投票:1回答:2

我正在写一个用户脚本试图减少过大的音频元素。如何访问已创建但未放置在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中,他们怎么能玩?它们似乎只是存在于某个地方,因为它们可以播放,但对我来说如何找到它们并不明显。

javascript html5-audio userscripts
2个回答
1
投票

因为callbackFn是异步调用的,所以你可以在HTMLMediaElement.prototype属性上改变volume的setter,这样你对感兴趣的src元素的音量变化将导致原始的setter被调用的音量为1/10默认情况下会调用它:

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(例如使用用户脚本)时,这只是一种破解。

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

非常肯定做这样的事情的唯一方法是使用像使用document.createElement运行的页面代码之前运行的代码覆盖createElement这样的hack。


0
投票

鉴于问题的代码和现代浏览器的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>

plinkr桶

© www.soinside.com 2019 - 2024. All rights reserved.