Rai.tv native video player and direct links

This script allows you to watch and download videos on Rai.tv.

目前为 2016-04-12 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Rai.tv native video player and direct links
  3. // @namespace http://andrealazzarotto.com
  4. // @description This script allows you to watch and download videos on Rai.tv.
  5. // @include http://www*.rai.*/dl/RaiTV/programmi/media/*
  6. // @include http://www*.rai.*/dl/RaiTV/tematiche/*
  7. // @include http://www*.rai.*/dl/*PublishingBlock-*
  8. // @include http://www*.rai.*/dl/replaytv/replaytv.html*
  9. // @exclude http://www*.rai.*/dl/RaiTV/dirette/*
  10. // @include http://*.rai.it/*
  11. // @include http://www.rainews.it/dl/rainews/*
  12. // @version 8.9.6
  13. // @require http://code.jquery.com/jquery-latest.min.js
  14. // @grant GM_xmlhttpRequest
  15. // @connect rai.it
  16. // @connect rai.tv
  17. // @connect video.lazza.dk
  18. // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
  19. // ==/UserScript==
  20.  
  21. var MP4isOk = document.createElement('video').canPlayType('video/mp4');
  22.  
  23. function playerElement() {
  24. var selectors = [
  25. "div.Player:has(video)",
  26. "div.Player:has(embed)",
  27. "div.Player",
  28. "div#Player",
  29. "div#idPlayer",
  30. "div.videoContainer:has(iframe)",
  31. "div.mediaRaiTV:has(iframe)",
  32. "div.player-video",
  33. "div.flex-video"
  34. ];
  35. for (var k in selectors) {
  36. var PL = $(selectors[k]).get(0);
  37. if(PL)
  38. return $( PL );
  39. }
  40. return null;
  41. }
  42.  
  43. function appendMsg(text, PL) {
  44. if(!PL)
  45. PL = playerElement();
  46. PL.append("<div id='subcontent'>" + text + "</div>");
  47. var wi = PL.width();
  48. var w = wi*0.6;
  49. $("#subcontent").css({
  50. "padding": "5px",
  51. "color": "white",
  52. 'width': w+'px',
  53. "background": "rgba(0,0,0,0.5)",
  54. 'margin': '15px auto'
  55. });
  56. $("#subcontent p").css({
  57. 'margin': '.2em auto',
  58. 'padding': 0
  59. });
  60. $("#subcontent a").css({
  61. 'color': 'white',
  62. 'font-weight': 'bold'
  63. });
  64. }
  65.  
  66. function placeHolder(url, kind, PL, remove) {
  67. remove = typeof remove !== 'undefined' ? remove : true;
  68.  
  69. if(!PL)
  70. PL = playerElement();
  71. if(remove)
  72. $("#direct-link").remove();
  73. PL.append("<div id='direct-link' />");
  74. var wi = PL.width();
  75. var w = wi*0.6;
  76. // some styling
  77. $("#direct-link")
  78. .css({
  79. 'padding': '5px',
  80. 'margin': '10px auto 15px',
  81. 'width': w+'px',
  82. 'border': '1px solid #888',
  83. 'text-align': 'center',
  84. 'box-shadow': '0px 5px 15px 0px rgba(0, 0, 0, .7)',
  85. 'background-color': '#cfc',
  86. });
  87. // place the link
  88. $("#direct-link")
  89. .append('<a href="'+url+'">' + kind + " Direct Link</a>");
  90. $("#direct-link a")
  91. .css({
  92. 'font-size': '13px',
  93. 'font-weight': 'normal',
  94. 'color': 'black'
  95. });
  96. PL.css('border', '0');
  97. // workaround -> http://stackoverflow.com/a/18792741/1101509
  98. PL[0].style.setProperty('background-color', 'transparent', 'important');
  99. if(PL.parent().height() < PL.height() + $("#direct-link").height())
  100. PL.parent().css('height', 'auto');
  101. }
  102.  
  103. function setUP(url, kind, title) {
  104. if(kind.toLowerCase().indexOf("smooth") != -1 ||
  105. kind.toLowerCase().indexOf("csm") != -1)
  106. return;
  107. // fix spaces
  108. url = url.split(' ').join('%20');
  109. var autoplay = (window.location.href.indexOf("autoplay=false") > 0) ? "" : 'autoplay="true"';
  110.  
  111. // place the video
  112. var PL = playerElement();
  113. var w = PL.width();
  114. var h = PL.height();
  115. PL.empty();
  116. var tag = '<embed type="application/x-mplayer2" ' + autoplay;
  117. var style = 'width: ' + w + 'px; height: ' + h + 'px';
  118. if(kind == "MP4" && MP4isOk) {
  119. tag = '<video controls ' + autoplay;
  120. style = 'width: ' + w + 'px; display: block';
  121. }
  122. PL.append(tag + ' id="Player" style="' + style + '"' +
  123. 'src="' + url + '">');
  124. PL.css('height', 'auto');
  125. // fix TG1
  126. $('.topRubrica').css('height', 'auto');
  127. // fix player
  128. PL.find('video, embed').css({
  129. 'float': 'none',
  130. 'position': 'relative'
  131. });
  132. // kill the flash player, if any
  133. setTimeout(function() {
  134. if(unsafeWindow.player) {
  135. unsafeWindow.player.pause();
  136. }
  137. else {
  138. setTimeout(arguments.callee, 400);
  139. }
  140. }, 400);
  141.  
  142. placeHolder(url, kind, PL);
  143. // fix TIMMusicOnStage and similar new sites
  144. $('.flex-video').css('padding', '0');
  145. $('.flex-video').get(0).style.setProperty('background-color', 'white', 'important');
  146. // check for server problems
  147. if(url.indexOf('Host') > 0 && url.indexOf('video.lazza.dk') > 0) {
  148. $("#direct-link").remove();
  149. appendMsg('Si è verificato un <b>problema temporaneo</b> con il server');
  150. }
  151. }
  152.  
  153. function decide(videoURL, videoURL_MP4, estensioneVideo) {
  154. if (videoURL_MP4) {
  155. // handle the relinker server-side
  156. GM_xmlhttpRequest({
  157. method: 'GET',
  158. url: 'http://video.lazza.dk/rai/?r=' + encodeURIComponent(videoURL_MP4),
  159. onload: function(responseDetails) {
  160. var r = responseDetails.responseText;
  161. if (r.length > 0)
  162. setUP(r, "MP4");
  163. }
  164. });
  165. }
  166. else if (videoURL) {
  167. // handle the relinker server-side
  168. GM_xmlhttpRequest({
  169. method: 'GET',
  170. url: 'http://video.lazza.dk/rai/?r=' + encodeURIComponent(videoURL),
  171. onload: function(responseDetails) {
  172. var r = responseDetails.responseText;
  173. if (r.substr(r.length - 4).substr(0,1) == '.')
  174. estensioneVideo = r.substr(r.length - 3).toUpperCase();
  175. if(r.toLowerCase().indexOf("mms") === 0)
  176. setUP(r, "MMS Stream");
  177. else
  178. if(r.length > 0)
  179. setUP(r, estensioneVideo);
  180. }
  181. });
  182. } // end if (videoURL)
  183. }
  184.  
  185. function parseQuery(hash) {
  186. var result = {};
  187. var parts = hash.split("&");
  188. for(var i = 0; i<parts.length; i++) {
  189. var pair = parts[i].split("=");
  190. result[pair[0]] = pair[1];
  191. }
  192. return result;
  193. }
  194.  
  195. function purifyTitle(title) {
  196. return title.replace(/[^A-Za-z0-9]/gi," ").trim().replace(/\ +/gi,"_");
  197. }
  198.  
  199. function setUpFromURL(url) {
  200. // get the original page content
  201. GM_xmlhttpRequest({
  202. method: 'GET',
  203. url: url,
  204. onload: function(responseDetails) {
  205. var r = responseDetails.responseText;
  206. // kill script tags to avoid execution (and errors!)
  207. r = r.replace(new RegExp('script', 'g'), 'dummy');
  208. r = $('<div></div>').append(r);
  209. var data = $(r).find("div#silverlightControlHost dummy").text();
  210. var videoURL = null;
  211. var videoURL_MP4 = null;
  212. var estensioneVideo = null;
  213. // set the correct variables
  214. try {
  215. videoURL = data.match(/videoURL = ["'](.*?)["']/)[1];
  216. }
  217. catch(e) {}
  218. try {
  219. videoURL_MP4 = data.match(/videoURL_MP4 = ["'](.*?)["']/)[1];
  220. }
  221. catch(e) {}
  222. try {
  223. estensioneVideo = data.match(/estensioneVideo = ["'](.*?)["']/)[1];
  224. }
  225. catch(e) {}
  226. decide(videoURL, videoURL_MP4, estensioneVideo);
  227. }
  228. });
  229. }
  230.  
  231. $(document).ready(function(){
  232.  
  233. unsafeWindow.refreshByJS = false;
  234. var isReplay = !!$("script[src*='/replaytv.js']").length;
  235. var isTematiche = window.location.href.indexOf("tematiche") > 0;
  236. var isPublishingBlock = window.location.href.indexOf("PublishingBlock") > 0;
  237. var isRubriche = window.location.href.indexOf("rubriche") > 0;
  238. var isMultiple = (isTematiche || isPublishingBlock || isRubriche);
  239. console.log("isReplay: " + isReplay);
  240. console.log("isTematiche: " + isTematiche);
  241. console.log("isPublishingBlock: " + isPublishingBlock);
  242. console.log("isRubriche: " + isRubriche);
  243. console.log("isMultiple: " + isMultiple);
  244. var frames = $("iframe[src*='/dl/objects/embed.html'], iframe[src*='/dl/ray/'], " +
  245. "iframe[src*='/dl/Rai/'], iframe[src*='/dl/siti/'], iframe[src*='ContentItem']");
  246.  
  247. if(!isMultiple && !isReplay &&
  248. (unsafeWindow.videoURL || unsafeWindow.videoURL_MP4)) {
  249.  
  250. var videoURL = $("meta[name=videourl]").attr("content");
  251. if(!videoURL)
  252. videoURL = unsafeWindow.videoURL;
  253. var videoURL_MP4 = $("meta[name=videourl_h264]").attr("content");
  254. if(!videoURL_MP4)
  255. videoURL_MP4 = unsafeWindow.videoURL_MP4;
  256. if(!videoURL_MP4)
  257. videoURL_MP4 = $("meta[name=videourl_mp4]").attr("content");
  258. var estensioneVideo = unsafeWindow.estensioneVideo;
  259. if(estensioneVideo)
  260. estensioneVideo = estensioneVideo.toUpperCase();
  261. else
  262. estensioneVideo = "Unknown";
  263. if(unsafeWindow.MediaItem.type == 'WMV')
  264. // avoid bug when estensioneVideo = CSM and MediaItem.type = WMV
  265. estensioneVideo = "WMV";
  266. decide(videoURL, videoURL_MP4, estensioneVideo);
  267.  
  268. }
  269. // end Rai.tv "standard"
  270. else if(frames.length && !isReplay && !isMultiple) {
  271. var url = frames.attr("src");
  272. if(url.indexOf("embed.html") > 0)
  273. url = "http://www.rai.tv" + url.replace(/.*embed.html\?/, "");
  274. setUpFromURL(url);
  275. }
  276.  
  277. // end iframes
  278. else if(isMultiple && !isReplay) {
  279. if(unsafeWindow.videoURL) {
  280. document.videoURL = '';
  281. setInterval(function() {
  282. if(!playerElement())
  283. return;
  284. document.prevURL = document.videoURL;
  285. document.videoURL = unsafeWindow.videoURL;
  286. if(document.videoURL && (document.prevURL != document.videoURL)) {
  287. decide(document.videoURL);
  288. }
  289. }, 400);
  290. }
  291. else
  292. setInterval(function() {
  293. if(!playerElement())
  294. return;
  295. document.HprevId = document.Hid;
  296. document.Hid = $("div.Player").attr("data-id");
  297. if(!document.Hid)
  298. try {
  299. document.Hid = $("div.player-video iframe").attr("src").split("media/")[1].split(".html")[0];
  300. }
  301. catch(e) {}
  302.  
  303. // remove video list click events to allow opening of "real" pages
  304. // if not on "tematiche"
  305. if(!isTematiche) {
  306. $(".listaVideo a").unbind("click");
  307. }
  308. if(document.Hid && (document.Hid != document.HprevId)) {
  309. var completeURL = "http://www.rai.tv/dl/RaiTV/" +
  310. "programmi/media/" + document.Hid + ".html";
  311. setUpFromURL(completeURL);
  312. }
  313. }, 400);
  314. }
  315. // end Tematiche
  316. else if($("script:contains('draw')").length > 0 ||
  317. $("div.infoVideo").length > 0) {
  318. var videoURL = $("script:contains('draw')").text().split("'")[1];
  319. if(videoURL !== null && videoURL.indexOf("relinker") > 0) {
  320. GM_xmlhttpRequest({
  321. method: 'GET',
  322. url: videoURL,
  323. headers: {
  324. 'Accept': 'application/atom+xml,application/xml,text/xml'
  325. },
  326. onload: function(responseDetails) {
  327. var r = responseDetails.responseText;
  328. var doc = $.parseXML(r);
  329. var $xml = $( doc );
  330. var url = $xml.find("REF").attr("HREF");
  331. url = url.replace("http://", "mms://");
  332. setUP(url, "MMS Stream");
  333. }
  334. });
  335. }
  336. else if(videoURL !== null && videoURL.indexOf(".html") > 0) {
  337. setUpFromURL(videoURL);
  338. }
  339. else { // last try
  340. var PL = playerElement();
  341. var initParams = PL.find("param[name=initParams]").attr("value");
  342. if (initParams.indexOf("mediaUri") != -1) {
  343. var url = initParams.split("mediaUri=")[1].split(",")[0];
  344. decide(url, null, null); // decide will find the type
  345. }
  346. }
  347. }
  348. // end pages like report.rai.it
  349. else if(isReplay) {
  350. $(window).bind('hashchange', function(){
  351. var hash = window.location.hash.slice(1);
  352. var hashdata = parseQuery(hash);
  353. $("#direct-link + #subcontent").remove();
  354. $("#direct-link").remove();
  355.  
  356. var isvideo = hashdata.v;
  357. document.TheVideoNow = hashdata.v;
  358. if(isvideo && document.TheVideoNow != document.TheVideoBefore) {
  359. var dataURL = "http://video.lazza.dk/rai/?i=" + hashdata.v;
  360.  
  361. GM_xmlhttpRequest({
  362. method: 'GET',
  363. url: dataURL,
  364. onload: function(responseDetails) {
  365. var r = responseDetails.responseText;
  366. if(r.length > 0)
  367. setUP(r, "MP4");
  368. }
  369. });
  370. document.TheVideoBefore = document.TheVideoNow;
  371. }
  372. $("a[name]").click(function() {
  373. setTimeout(unsafeWindow.onClickShowAll, 500); // show the complete listing
  374. });
  375. });
  376. $(window).trigger( 'hashchange' );
  377. setTimeout(unsafeWindow.onClickShowAll, 500); // show the complete listing
  378. }
  379. // end Rai Replay
  380.  
  381. // handle RTMP based flash objects on Rai.it
  382. $("object").not("object object").each(function() {
  383. var o = $(this);
  384. var flashvars = o.find("param[name=flashvars]").attr("value");
  385. if(!flashvars)
  386. flashvars = o.find("embed").attr("flashvars");
  387. if(!flashvars)
  388. flashvars = "";
  389. var path = flashvars.replace(/.*percorso[^=]*=/gi, "")
  390. .replace(/&.*/gi, "").replace(/\?.*/gi, "");
  391. if(path.toLowerCase().indexOf("rtmp")!=-1) {
  392. var url = path.replace('mp4:','').replace('rtmp','http')
  393. .replace('.mp4','') + '.mp4';
  394. placeHolder(url, "MP4", o, false);
  395. }
  396. });
  397. // end code for flash videos
  398. // handle new pages with projekktor
  399. var pj;
  400. try {
  401. pj = unsafeWindow.projekktor();
  402. }
  403. catch (e) {
  404. pj = false;
  405. }
  406. if(pj) {
  407. var files = pj.media;
  408. var src = files[files.length - 1].file[0].src;
  409. var el = $('div.projekktor').parent();
  410. placeHolder(src, 'MP4', el);
  411. el.css('background', 'transparent');
  412. }
  413. // end projekktor
  414. // handle WP-Video
  415. $('div[class^="wp-video"]').each(function() {
  416. var url = $(this).find('video').attr('src');
  417. placeHolder(url, "MP4", $(this), false);
  418. });
  419. // handle jwplayer
  420. $('script:contains("jwplayer(")').each(function() {
  421. try {
  422. var content = $(this).text().split('sources:')[1].split('[{')[1].split('}]')[0];
  423. }
  424. catch (e) { return; }
  425. parts = content.split('file:').filter(function(x){return x.indexOf('m3u8') > 0});
  426. if(parts.length) {
  427. try {
  428. var m3u8_url = parts[0].split('"')[1];
  429. }
  430. catch (e) { return; }
  431. placeHolder(m3u8_url, 'M3U8 Stream', $(this).parent(), false);
  432. appendMsg(
  433. "<p>Ricordo che per registrare i video in formato M3U8 va utilizzato <code>avconv</code> o <code>ffmpeg</code>. " +
  434. "Maggiori informazioni <a href='http://lazza.me/1PLyi12'>cliccando qui</a>.</p>" +
  435. "<p style='text-align:right'>&mdash; Andrea</p>"
  436. , $(this).parent());
  437. }
  438. });
  439.  
  440. }); // end document.ready