RTVE.es Download video and subtitles

Shows a download link to download mp4 and vtt files

  1. // ==UserScript==
  2. // @name RTVE.es Download video and subtitles
  3. // @description Shows a download link to download mp4 and vtt files
  4. // @namespace cuzi
  5. // @version 2
  6. // @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
  7. // @grant unsafeWindow
  8. // @include http://www.rtve.es/*
  9. // @include https://www.rtve.es/*
  10. // ==/UserScript==
  11.  
  12. main();
  13.  
  14. // ####### Util: #######
  15.  
  16. function unicodeFlag(xx) {
  17. const offset = function charoff(c) {
  18. return String.fromCodePoint(0x1F1E6 - 65 + c.toUpperCase().charCodeAt(0));
  19. };
  20. return offset(xx[0]) + offset(xx[1]);
  21. }
  22.  
  23. function httpGet(url, cb) {
  24. const xmlHttp = new XMLHttpRequest();
  25. xmlHttp.onreadystatechange = function onreadystatechange() {
  26. if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
  27. cb(xmlHttp.responseText);
  28. };
  29. xmlHttp.open("GET", url, true);
  30. xmlHttp.send(null);
  31. return xmlHttp;
  32. }
  33.  
  34.  
  35. // ####### Func: #######
  36.  
  37. function getVideoSrc(ev) {
  38. if(!document.querySelector("video")) {
  39. ev.preventDefault();
  40. alert("Video tag <video> not found!\n\nPlease start the video and select the quality that you want to download. Then click here again.");
  41. return false;
  42. }
  43.  
  44. const player = unsafeWindow.videojs(document.querySelector("video").id);
  45. let url = player.currentSource().src; // "https://rtve-hlsvod.secure.footprint.net/resources/XY_ABCD/mp4/1/2/3456789123456.mp4/playlist.m3u8"
  46. let parts = url.split("/");
  47. parts.pop();
  48. url = parts.join("/");
  49.  
  50. this.href = url;
  51. this.innerHTML = url;
  52. this.target = "_blank";
  53. return true;
  54. }
  55.  
  56. function getSubtitles(rootEl) {
  57. const mediaBox = document.querySelector(".mediaBox.videoBox[data-config]");
  58. const config = JSON.parse(mediaBox.dataset.config);
  59. const subtitleRefUrl = document.location.origin + config.mediaConfig.subtitleRefUrl;
  60.  
  61. httpGet(subtitleRefUrl, function onLoadSubtitle(text) {
  62. const data = JSON.parse(text);
  63.  
  64. if(!data.page.items || !data.page.items.length) {
  65. return;
  66. }
  67. rootEl.style.opacity = 1.0;
  68.  
  69. const p = document.createElement("p");
  70. p.setAttribute("style", "margin:5px 0px;");
  71. rootEl.append(p);
  72. p.appendChild(document.createTextNode("Subtitulos:"));
  73. const ul = document.createElement("ul");
  74. p.appendChild(ul);
  75. for(const item of data.page.items) {
  76. const li = document.createElement("li");
  77. ul.appendChild(li);
  78. li.appendChild(document.createTextNode(unicodeFlag(item.lang)));
  79. const a = document.createElement("a");
  80. a.target = "_black";
  81. a.href = item.src;
  82. a.style = "color:#f7780a";
  83. a.appendChild(document.createTextNode(item.src));
  84. li.appendChild(a);
  85.  
  86. }
  87.  
  88. });
  89. }
  90.  
  91. function hideMe() {
  92. this.parentNode.parentNode.removeChild(this.parentNode);
  93. }
  94.  
  95. function waitForVideoTag() {
  96. const div = document.getElementById("userscript_rtve_cuzi_ui");
  97. if(div && div.dataset.url != document.location.href) {
  98. showUI();
  99. return;
  100. }
  101. if(!document.querySelector("video")) {
  102. div.style.opacity = 0.3;
  103. return;
  104. }
  105. div.style.opacity = 1.0;
  106. }
  107.  
  108. function showUI() {
  109. if(!document.querySelector(".mediaBox.videoBox")) {
  110. return;
  111. }
  112. const oldui = document.getElementById("userscript_rtve_cuzi_ui");
  113. if(oldui) {
  114. oldui.parentNode.removeChild(oldui);
  115. }
  116. const div = document.createElement("div");
  117. div.dataset.url = document.location.href;
  118. div.setAttribute("id", "userscript_rtve_cuzi_ui");
  119. div.setAttribute("style", "position:fixed; top:100px; left:10px; background:rgb(250,230,230); color:black; border:2px solid black; font-size:12px; padding:10px; border-radius:5px; z-index:9999; opacity:0.3;");
  120. document.body.appendChild(div);
  121.  
  122. const close = document.createElement("div");
  123. close.setAttribute("style", "position:absolute; top:3px; right:3px; color:red; border:2px solid red; font-size:12px; padding:2px; border-radius:5px; cursor:pointer;");
  124. close.setAttribute("title", "Hide");
  125. close.addEventListener("click", hideMe);
  126. close.appendChild(document.createTextNode("X"));
  127. div.appendChild(close);
  128.  
  129.  
  130. const p = document.createElement("p");
  131. p.setAttribute("style", "margin:5px 0px;");
  132. div.append(p);
  133. p.appendChild(document.createTextNode("Video:"));
  134. p.appendChild(document.createElement("br"));
  135. const aGetSrc = document.createElement("a");
  136. p.appendChild(aGetSrc);
  137. aGetSrc.appendChild(document.createTextNode("Download"));
  138. aGetSrc.href = "#";
  139. aGetSrc.style = "color:#f7780a";
  140. aGetSrc.addEventListener("click", getVideoSrc);
  141.  
  142. getSubtitles(div);
  143. }
  144.  
  145.  
  146. // ####### Main: #######
  147.  
  148. function main() {
  149. showUI();
  150. window.setInterval(function interval() { waitForVideoTag(); }, 2000);
  151. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址