0

I'm creating an extension that mutes the autoplay video when you navigate to a Youtube channel. It's able to execute content.js when navigating to a Youtube channel and select the video, but how can I set the video's volume? Setting video.volume = 0 does not work like I thought it would.

Background script:

'use strict';

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {

    if (changeInfo.status == 'complete') {
        const site = tab.url.split('/');

        let domain = site[2];
        let page = site[3];

        if (page === 'channel' || page === 'user') {
            chrome.tabs.sendMessage(tab.id, {'message': 'loaded_channel_page'});
        }
    }
});

Content script:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {

    if (request.message === 'loaded_channel_page' || document.readyState != 'loading') {

        let newVolume = 0;

        document.addEventListener('yt-navigate-finish', () => {
            setTimeout(mute, 2000);
        });

        function mute() {
            let video = document.querySelector('.html5-main-video');
            video.volume = newVolume;
        }
    }
})
wOxxOm
  • 65,848
  • 11
  • 132
  • 136

1 Answers1

0

Youtube doesn't monitor direct changes to the DOM video element's properties, they use their own wrapper on a #movie_player element that exposes the volume control function in page context which we can't access directly from the content script so we need to run it in a <script> element:

// direct call
inPage(setVolume, 0);
// delayed call
setTimeout(inPage, 2000, setVolume, 0);

// range is 0 - 100
function setVolume(vol) {
  document.getElementById('movie_player').setVolume(vol);
}

function inPage(fn, ...args) {
  const script = document.createElement('script');
  script.textContent = `(${fn})(${JSON.stringify(args).slice(1, -1)})`;
  document.documentElement.appendChild(script);
  script.remove();
}
wOxxOm
  • 65,848
  • 11
  • 132
  • 136