How do I prevent the browser from preloading the <video> tag?

放肆的年华 提交于 2019-12-04 02:39:23

One dirty solution that seems to work is to use a MutationObserver from your userscript, once you're sure it does run at document-start.

This TamperMonkey script does work for me :

// ==UserScript==
// @name         Block videos preloading
// @include      *
// @run-at document-start
// ==/UserScript==

(function() {
  'use strict';
  var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      var nodes = mutation.addedNodes;
      for (var i = 0; i < nodes.length; i++) {
        if (nodes[i].nodeName == "VIDEO") {
          nodes[i].setAttribute('preload', 'none');
          nodes[i].removeAttribute('autoplay');
        }
      }
    })
  });
  observer.observe(document.documentElement, {
    childList: true,
    subtree: true
  });

})();

You may want to call observer.disconnect() on DOMContentLoaded, if you're not expecting other video elements for being inserted afterwards by scripts.

Check if what you think really happens. It should be impossible, because both "run_at": "document_start" and "run_at": "document_end" should make your code run before anything is loaded.

From the documentation in developer.chrome.com:

In the case of "document_start", the files are injected after any files from css, but before any other DOM is constructed or any other script is run.

In the case of "document_end", the files are injected immediately after the DOM is complete, but before subresources like images and frames have loaded.

In addition, because your code runs in document_start, the document.getElementsByTagName("Video") should fail because no DOM is even constructed yet.

Try debugging your code (start with checking for errors in the console). Also, read more about the "run_at" attribute here: https://developer.chrome.com/extensions/content_scripts#run_at

Try storing <audio>, <video> src value, then remove src attribute from <audio>, <video> elements for setting preload, autoplay attributes; using DOMContentLoaded event

The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <script>
    var sources = [];
    document.addEventListener("DOMContentLoaded", function(event) {
      var media = document.querySelectorAll("audio, video");
      [].forEach.call(media, function(el) {
        if (el.src) {
          sources.push(el.src);
          el.removeAttribute("src");
        }
        var src = el.querySelectorAll("source");
        if (src.length) {
          [].forEach.call(src, function(source) {
            sources.push(source.src);
            source.removeAttribute("src");
          });
        };
      });
      console.log(sources);
    });
  </script>
</head>
<body style="height:270px">
  <video src="http://mirrors.creativecommons.org/movingimages/webm/ScienceCommonsJesseDylan_240p.webm" controls></video>
 <audio controls>
    <source src="https://upload.wikimedia.org/wikipedia/commons/6/6e/Micronesia_National_Anthem.ogg" type="video/ogg" />
  </audio>
</body>
</html>

Edit, Updated

can you test it in user script ?

Utilizing content_scripts, "run_at": "document_start" in manifest.json returned expected results as a chromium, chrome extension; that is, src attribute of <audio>, <video>, <source> elements should be removed from document.

manifest.json

{
  "manifest_version": 2,
  "name": "blockmedia",
  "description": "remove src from audio, video elements",
  "version": "1.0",
  "permissions": ["<all_urls>"],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["script.js"],
      "run_at": "document_start"
    }
  ]
}

script.js

var sources = [];
document.addEventListener("DOMContentLoaded", function(event) {
  var media = document.querySelectorAll("audio, video");
  [].forEach.call(media, function(el) {
    if (el.src) {
      sources.push(el.src);
      el.removeAttribute("src");
    }
    var src = el.querySelectorAll("source");
    if (src.length) {
      [].forEach.call(src, function(source) {
        sources.push(source.src);
        source.removeAttribute("src");
      });
    };
  });
 console.log(sources);
});

You're battling against the Chrome parser preloader.

Even if you inject a content script at document start, using Mutation Observer or another technique suggested above, you still cannot action the HTML before the browser preloader.

Read this article, which helped me.

https://andydavies.me/blog/2013/10/22/how-the-browser-pre-loader-makes-pages-load-faster/

To achieve what you want to do, you're going to need to use the Chrome webRequest API to block the request.

https://developer.chrome.com/extensions/webRequest

You will need to filter requests according to the media type and then search the headers for the file types you want to block.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!