简体   繁体   English

如何阻止浏览器预加载<video>标签?

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

I have written a user script extension for Chrome with JavaScript in order to prevent video and audio tags from downloading automatically on pageload 我使用JavaScript为Chrome编写了一个用户脚本扩展程序,以防止在页面加载时自动下载视频和音频标记

This is the code: 这是代码:

var videoTags = document.getElementsByTagName("Video");
var i;
for(i=0; i<videoTags.length; i++)
{
    videoTags[i].setAttribute("preload", "none");
    videoTags[i].removeAttribute("autoplay");
}

var audioTags = document.getElementsByTagName("audio");
var i;
for(i=0; i<audioTags.length; i++)
{
    audioTags[i].setAttribute("preload", "none");
    audioTags[i].removeAttribute("autoplay");
}

And this is the manifest.json file: 这是manifest.json文件:

   {
      "content_scripts": [ {
      "exclude_globs": [  ],
      "exclude_matches": [  ],
      "include_globs": [ "*" ],
      "js": [ "script.js" ],
      "matches": [ "http://*/*", "https://*/*" ],
      "run_at": "document_start"
   } ],
      "converted_from_user_script": true,
      "description": "",
      "key": "an2xaeZJluPfnpmcsHPXI4aajQPL1cBm5C2kKjaQwXA=",
      "name": "test.user.js",
      "version": "1.0"
  }

The problem is that my script runs after a moment and until then the browser (Chrome) downloads a part of video/audio file. 问题是我的脚本片刻后运行,直到那时浏览器(Chrome)下载了一部分视频/音频文件。

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. 这应该是不可能的,因为"run_at": "document_start""run_at": "document_end"应该在加载任何内容之前运行代码。

From the documentation in developer.chrome.com : 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. 在“document_start”的情况下,文件在来自css的任何文件之后但在构造任何其他DOM或运行任何其他脚本之前注入。

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. 在“document_end”的情况下,在DOM完成之后立即注入文件,但是在加载了图像和帧之类的子资源之前。

In addition, because your code runs in document_start , the document.getElementsByTagName("Video") should fail because no DOM is even constructed yet. 此外,因为您的代码在document_start运行,所以document.getElementsByTagName("Video")应该会失败,因为还没有构建DOM。

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 另外,请在此处详细了解"run_at"属性: 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; 尝试存储<audio><video> src值,然后从<audio><video>元素中删除src属性以设置preloadautoplay属性; using DOMContentLoaded event 使用DOMContentLoaded事件

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. 完全加载和解析初始HTML文档时会触发DOMContentLoaded事件,而无需等待样式表,图像和子帧完成加载。

 <!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; 利用content_scripts"run_at": "document_start"manifest.json返回预期的结果为铬,镀铬的扩展; that is, src attribute of <audio> , <video> , <source> elements should be removed from document . 也就是说,应从document删除<audio><video><source>元素的src属性。

manifest.json 的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 的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);
});

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. 一个似乎有效的脏解决方案是,一旦你确定它在document-start上运行,就可以使用你的用户脚本中的MutationObserver

This TamperMonkey script does work for me : 这个TamperMonkey脚本对我有用:

// ==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. 您可能希望在DOMContentLoaded上调用observer.disconnect() ,如果您不希望其他视频元素随后被脚本插入。

You're battling against the Chrome parser preloader. 你正在与Chrome解析器预加载器作斗争。

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. 即使您在文档启动时使用Mutation Observer或上面建议的其他技术注入内容脚本,您仍然无法在浏览器预加载器之前操作HTML。

Read this article, which helped me. 阅读这篇帮助我的文章。

https://andydavies.me/blog/2013/10/22/how-the-browser-pre-loader-makes-pages-load-faster/ 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. 要实现您的目标,您需要使用Chrome webRequest API来阻止请求。

https://developer.chrome.com/extensions/webRequest 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. 您需要根据媒体类型过滤请求,然后在标题中搜索要阻止的文件类型。

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

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