I have written a user script extension for Chrome with JavaScript in order to prevent video and audio tags from downloading automatically on pageload
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:
{
"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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With