// ==UserScript== // @name Lazy Embedded Video // @namespace zeusex81@gmail.com // @description Lazy load embedded videos from Youtube/Dailymotion/Vimeo/Rutube/Twitch/Ustream // @version 1.4 // @grant none // @downloadURL none // ==/UserScript== (function() { var testCSP = function() { if(!document.getElementById("zeusCSP")) { var script = document.createElement("SCRIPT"); script.id = "zeusCSP"; script.text = "CSP_AllowInlineScript = true;"; document.head.appendChild(script); } return CSP_AllowInlineScript; }; var html, a, http = window.location.protocol; var createHtml = function(url, iframe, api, background_img) { /(https?:\/\/(?:[^.\/]+\.)?([^.\/]+)\.[^.\/]+)\//i.test(url); var provider_url = RegExp.$1, provider_name = RegExp.$2, data_convert = "", extra_script = "", button_hsb = []; if(api.includes("yahooapis")) data_convert += "data = data.query.results.json;"; if(provider_name == "twitch") { if(background_img) { // channel live data_convert += "data.title = data.status || 'Untitled Broadcast';"+ "data.author_url = '"+provider_url+"/'+data.name+'/profile';"+ "data.author_name = data.display_name;"+ "data.duration = data.game && 'playing '+data.game+'';"+ "offline_image = data.video_banner;"; extra_script += ""+ ""; } else { // video recorded data_convert += "data.thumbnail_url = data.preview;"+ "data.author_url = '"+provider_url+"/'+data.channel.name+'/profile';"+ "data.author_name = data.channel.display_name;"+ "data.duration = data.length;"; } } if(background_img) // prevent downloading a second image data_convert += "delete data.thumbnail_url;"; switch(provider_name) { case "youtube" : button_hsb.push( 0, 100, 100); break; case "dailymotion": button_hsb.push( 60, 30, 300); break; case "vimeo" : button_hsb.push(220, 50, 220); break; case "rutube" : button_hsb.push( 0, 0, 250); break; case "twitch" : button_hsb.push(270, 50, 100); break; case "ustream" : button_hsb.push( 40, 50, 230); break; } if(!html) html = [ ""+ ""+ ""+ "Lazy Embedded Video"+ ""+ "", extra_script, ""+ ""+ ""+ "
"+ "
"+ ""+ ""+ "
"+ ""+ "" ]; html[ 1] = api; html[ 3] = data_convert; html[ 5] = extra_script; html[ 7] = background_img; html[ 9] = button_hsb[0]; html[11] = button_hsb[1]; html[13] = button_hsb[2]; html[15] = button_hsb[0]; html[17] = button_hsb[1]; html[19] = button_hsb[2]; html[21] = iframe; html[23] = provider_url; html[25] = provider_name; html[27] = url; html[29] = url; }; var createOembed = function(api, url) { return api+encodeURIComponent(url); }; var createNOembed = function(api, url) { return createOembed(http+"//noembed.com/embed?url=", url); }; var createYOembed = function(api, url) { return createOembed(http+"//query.yahooapis.com/v1/public/yql?format=json&q=", 'SELECT * FROM json WHERE url="'+createOembed(api,url)+'"'); }; var createLazyVideo = function(elem) { if(elem.tagName == "IFRAME" && elem.srcdoc) return true; var id, args, url = elem.src || elem.data || elem.dataset.src; if(!url) return true; if(!a) a = document.createElement("A"); a.href = url; /([^.]+)\.[^.]+$/i.test(a.hostname); switch(RegExp.$1) { case "youtube" : if(/\/(?:v|embed)\/([^&]*)/i.test(a.pathname)) id = RegExp.$1 || (/[?&]v=([^&]+)/i.test(a.search) && RegExp.$1); if(!id || !testCSP()) return !id; args = "?autoplay=1"; if(/[?&](list=[^&]+)/i.test(a.search)) args += "&"+RegExp.$1; if(/[?&](start=[^&]+)/i.test(a.search)) args += "&"+RegExp.$1; createHtml(url = http+"//www.youtube.com/watch"+args+"&v="+id, http+"//www.youtube.com/embed/"+id+args, createNOembed(http+"//www.youtube.com/oembed?format=json&url=", url), "url("+http+"//i.ytimg.com/vi/"+id+"/hqdefault.jpg)" ); break; case "dailymotion" : if(/\/(?:swf|embed)\/video\/([^&]+)/i.test(a.pathname)) id = RegExp.$1; if(!id || !testCSP()) return !id; args = "?autoplay=1"; if(/[?&](mute=[^&]+)/i.test(a.search)) args += "&"+RegExp.$1; if(/[?&](start=[^&]+)/i.test(a.search)) args += "&"+RegExp.$1; createHtml(url = http+"//www.dailymotion.com/video/"+id+args, http+"//www.dailymotion.com/embed/video/"+id+args, createOembed(http+"//www.dailymotion.com/services/oembed?format=json&url=", url), "url("+http+"//www.dailymotion.com/thumbnail/video/"+id+")" ); break; case "vimeo" : if(/\/(?:moogaloop\.swf|video\/)([^&]*)/i.test(a.pathname)) id = RegExp.$1 || (/[?&]clip_id=([^&]+)/i.test(a.search) && RegExp.$1); if(!id || !testCSP()) return !id; args = "?autoplay=1"; if(/[?&](loop=[^&]+)/i.test(a.search)) args += "&"+RegExp.$1; if(/(\#t=[\dhms]+)/i.test(a.hash)) args += RegExp.$1; createHtml(url = http+"//vimeo.com/"+id+args, http+"//player.vimeo.com/video/"+id+args, createOembed(http+"//vimeo.com/api/oembed.json?url=", url) ); break; case "rutube" : if(/\/play\/embed\/([^&]+)/i.test(a.pathname)) id = RegExp.$1; if(!id || !testCSP()) return !id; args = "?autoStart=1"; if(/[?&](bmstart=[^&]+)/i.test(a.search)) args += "&"+RegExp.$1; createHtml(url = http+"//rutube.ru/tracks/"+id+".html/"+args, http+"//rutube.ru/play/embed/"+id+args, createOembed(http+"//rutube.ru/api/oembed/?format=jsonp&url=", url) ); break; case "twitch" : if(/[?&](channel|video)=([^&]+)/i.test(a.search)) args = RegExp.$1, id = RegExp.$2; if(!id || !testCSP()) return !id; createHtml(url = http+"//www.twitch.tv/"+(args=="video" ? id.replace("v","c/v/") : id), http+"//player.twitch.tv/?autoplay=true&"+args+"="+id, "https://api.twitch.tv/kraken/"+args+"s/"+id+"?", args=="channel" ? "url("+http+"//static-cdn.jtvnw.net/previews-ttv/live_user_"+id+"-0x0.jpg)" : null ); break; case "ustream" : if(/\/embed\/(recorded\/)?([^&]+)/i.test(a.pathname)) args = RegExp.$1, id = RegExp.$2; if(!id || !testCSP()) return !id; createHtml(url = http+"//www.ustream.tv/"+(args||"channel/")+id, http+"//www.ustream.tv/embed/"+args+id+"?html5ui=1&autoplay=1", createYOembed(http+"//www.ustream.tv/oembed?format=json&url=", url) ); break; default : return true; } if(elem.tagName != "IFRAME") { var iframe = document.createElement("IFRAME"); iframe.id = elem.id; iframe.className = elem.className; iframe.style.cssText = elem.style.cssText; if(!iframe.style.width && elem.width ) iframe.style.width = elem.width+"px"; if(!iframe.style.height && elem.height) iframe.style.height = elem.height+"px"; if(!iframe.style.border) iframe.style.border = "0px"; if(elem.parentNode.tagName == "OBJECT") elem = elem.parentNode; elem.parentNode.replaceChild(iframe, elem); elem = iframe; } elem.allowFullscreen = true; elem.srcdoc = html.join(""); return true; }; // convert NodeList to Array because for some reason sometimes I wasn't able to read src when iterating directly through NodeList var nodes = ["IFRAME", "EMBED", "OBJECT"].reduce(function(sum, value) { return sum.concat([].slice.call(document.getElementsByTagName(value))); }, frameElement ? [frameElement] : []); for(var i = 0; i < nodes.length && createLazyVideo(nodes[i]); i++) {} })();