简体   繁体   English

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

[英]Edit audio element volume in userscript

I'm writing a userscript to try to decrease an overly loud audio element.我正在编写一个用户脚本来尝试减少过于响亮的音频元素。 How do I get access to an audio element that has been created, but not placed in the DOM anywhere?如何访问已创建但未放置在 DOM 中任何位置的音频元素?

On the site itself, it has something akin to:在网站本身,它有类似的东西:

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();
    };

    //...
}();

In my userscript, I want to do something like在我的用户脚本中,我想做一些类似的事情

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();
    };

    // ...
}();

I can't seem to get access to it, though.不过,我似乎无法访问它。 I don't really understand where these objects live.我真的不明白这些对象住在哪里。 If they're not in the DOM, how can they be played?如果它们不在 DOM 中,如何播放它们? They just seem to exist in the document somewhere since they can be played, but it is not obvious to me how to find them.它们似乎只是存在于文档中的某个地方,因为它们可以播放,但我不清楚如何找到它们。

Because the callbackFn is called asynchronously, you can alter HTMLMediaElement.prototype 's setter on its volume property, so that changes to the volume on an element with the src you're interested in will result in the original setter being called with a volume 1/10th of what it would be called with by default:因为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);
  }
});

Of course, note that this is only a hack for when you can't alter the existing JS of a page, such as with a userscript.当然,请注意,这只是当您无法更改页面的现有 JS(例如使用用户脚本)时的一种 hack。

I'm looking for a way to access audio elements that exist in the webpage but have not been added to the DOM我正在寻找一种方法来访问网页中存在但尚未添加到 DOM 中的音频元素

Pretty sure the only way to do something like this would be to use a hack like overwriting document.createElement with code that runs before the page's code that uses createElement runs.很确定做这样的事情的唯一方法是使用像在使用createElement的页面代码运行之前运行的代码覆盖document.createElement类的黑客。

Given the code at the question and the fact that autoplay policy of modern browsers have changed, one you locate which element in the DOM begins media playback after user action you can remove and replace the event handler with a function which sets volume and calls the original handler, for example鉴于问题中的代码以及现代浏览器的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 plnkr https://plnkr.co/edit/fNlhODuwC5Z0jXchoWBE?p=preview

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

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