// ==UserScript==
// @name Youtube Restore Flash Player
// @description This script replaces the default HTML5 YouTube player with the OSMF Strobe Media Playback player. For videos that don't have a .MP4 stream available, the script will attempt loading a basic .webm stream.
// @require https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js
// @namespace https://github.com/TraceHeritage/YoutubeRestoreFlash/
// @include https://www.youtube.com/watch*
// @include http://www.youtube.com/watch*
// @version 1.0.0
// ==/UserScript==
//********************************************************************
//Required code to get Greasemonkey's ajax (GM_xmlhttpRequest) working
//********************************************************************
function GM_XHR() {
this.type = null;
this.url = null;
this.async = null;
this.username = null;
this.password = null;
this.status = null;
this.headers = {};
this.readyState = null;
this.abort = function() {
this.readyState = 0;
};
this.getAllResponseHeaders = function(name) {
if (this.readyState!=4) return "";
return this.responseHeaders;
};
this.getResponseHeader = function(name) {
var regexp = new RegExp('^'+name+': (.*)$','im');
var match = regexp.exec(this.responseHeaders);
if (match) { return match[1]; }
return '';
};
this.open = function(type, url, async, username, password) {
this.type = type ? type : null;
this.url = url ? url : null;
this.async = async ? async : null;
this.username = username ? username : null;
this.password = password ? password : null;
this.readyState = 1;
};
this.setRequestHeader = function(name, value) {
this.headers[name] = value;
};
this.send = function(data) {
this.data = data;
var that = this;
// http://wiki.greasespot.net/GM_xmlhttpRequest
GM_xmlhttpRequest({
method: this.type,
url: this.url,
headers: this.headers,
data: this.data,
onload: function(rsp) {
// Populate wrapper object with returned data
// including the Greasemonkey specific "responseHeaders"
for (var k in rsp) {
that[k] = rsp[k];
}
// now we call onreadystatechange
that.onreadystatechange();
},
onerror: function(rsp) {
for (var k in rsp) {
that[k] = rsp[k];
}
}
});
};
};
$.ajaxSetup({
xhr: function(){return new GM_XHR;}
});
window.addEventListener('load', function() {
//************************
//Get info on current page
//************************
var yt_id = window.location.href.split("?v=")[1];
var yt_url = "http://www.youtube.com/get_video_info?video_id=" + yt_id + "&el=detailpage&ps=default&eurl=&gl=US&hl=en";
var yt_webm_url = "";
var yt_mp4_url = "";
var player = document.getElementById("player");
player.style.display = "none";
GM_xmlhttpRequest({
url: yt_url,
method: "GET",
onload: function (responseObject){
//******************************
//Load direct video feed locally
//******************************
var data = responseObject.responseText;
var decoded = decodeURIComponent(data);
var split1 = data.split("&");
var split2 = [];
var split3 = [];
var split4 = [];
var split5 = [];
var split_url = "";
var signature = false;
for (i = 0; i < split1.length; i++) {
split2 = split1[i].split("=");
for (j = 0; j < split2.length; j++) {
if (split2[j].indexOf("url_encoded_fmt_stream_map") >= 0) {
split_url = decodeURIComponent(split2[j+1]);
split3 = split_url.split(",");
for (k = 0; k < split3.length; k++) {
split4 = split3[k].split("&");
for (l = 0; l < split4.length; l++) {
split5 = split4[l].split("=");
if (split5[0].indexOf("sp") >= 0) {
signature = true;
}
if ((split5[1].indexOf("http") >= 0)) {
for (m = 0; m < split4.length; m++) {
//************************************************
//Store medium quality MP4/webm feeds if available
//************************************************
if (split4[m].indexOf("medium") >= 0) {
if (split5[1].indexOf("mp4") >= 0) {
yt_mp4_url = decodeURIComponent(split5[1]);
} else if (split5[1].indexOf("webm") >= 0) {
yt_webm_url = decodeURIComponent(split5[1]);
}
}
}
}
}
}
}
}
}
//*************************************************************
//Load MP4/webm feeds using external API if stream is protected
//*************************************************************
if (signature) {
var url = "https://maple-ytdl.herokuapp.com/api?id=" + yt_id;
yt_mp4_url = "";
yt_webm_url = "";
GM_xmlhttpRequest({
url: url,
method: "GET",
dataType: "text",
cache: true,
onload: function (responseObject){
var data = JSON.parse(responseObject.responseText);
for (i = 0; i < data['stream'].length; i++) {
if ((data['stream'][i]['quality'] === "medium") && (data['stream'][i]['type'].indexOf("mp4") >= 0)) {
yt_mp4_url = data['stream'][i]['url'];
} else if ((data['stream'][i]['quality'] === "medium") && (data['stream'][i]['type'].indexOf("webm") >= 0)) {
yt_webm_url = data['stream'][i]['url'];
}
}
//********************
//Load video onto page
//********************
var player_holder = document.getElementById("placeholder-player");
if (yt_mp4_url != "") {
player_holder.innerHTML = '';
} else {
player_holder.innerHTML = '';
}
},
onerror: function () {
alert("error");
}
});
} else {
//**********************************************
//Load video onto page for locally sourced video
//**********************************************
var player_holder = document.getElementById("placeholder-player");
if (yt_mp4_url != "") {
player_holder.innerHTML = '';
} else {
player_holder.innerHTML = '';
}
}
},
onerror: function () {
alert("error");
}
});
}, false);