Редактировать громкость аудио элемента в usercript - PullRequest
0 голосов
/ 17 февраля 2019

Я пишу пользовательский скрипт, чтобы попытаться уменьшить чрезмерно громкий аудиоэлемент.Как получить доступ к аудиоэлементу, который был создан, но нигде не размещен в 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();
    };

    //...
}();

В моемuserScript, я хочу сделать что-то вроде

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, как их можно сыграть?Кажется, они просто существуют где-то в документе, поскольку их можно воспроизвести, но для меня не очевидно, как их найти.

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

Учитывая код вопроса и тот факт, что политика современных браузеров 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

0 голосов
/ 17 февраля 2019

Поскольку callbackFn вызывается асинхронно, вы можете изменить установщик HTMLMediaElement.prototype в его свойстве volume, так что изменение тома элемента с src, который вас интересует, приведет кисходный сеттер вызывается с объемом, равным 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страницы, например, с использованием usercript.

Я ищу способ доступа к аудио элементам, которые существуют на веб-странице, но не были добавлены в DOM

Уверен, что единственный способ сделать что-то подобное - это использовать хак, например, перезаписать document.createElement кодом, который запускается до запуска кода страницы, использующего createElement.

...