bilibili播放视频倍速自定义,可记忆

bilibili播放视频倍速自定义,刷新浏览器也不会丢失之前设置的速度, 弹幕默认打开方式由你控制,视频列表播放单个视频结束时自动跳过充电页面从而快速进入下一个视频

  1. // ==UserScript==
  2. // @name bilibili播放视频倍速自定义,可记忆
  3. // @namespace EsfB2XVPmbThEv39bdxQR2hzid30iMF9
  4. // @version 2.0
  5. // @description bilibili播放视频倍速自定义,刷新浏览器也不会丢失之前设置的速度, 弹幕默认打开方式由你控制,视频列表播放单个视频结束时自动跳过充电页面从而快速进入下一个视频
  6. // @author 朋也
  7. // @include http*://*bilibili.com/video/*
  8. // @include http*://*bilibili.com/list/*
  9. // @include http*://*bilibili.com/bangumi/*
  10. // @grant none
  11. // @license AGPL
  12. // ==/UserScript==
  13.  
  14. (function () {
  15. "use strict";
  16.  
  17. const THIRD_VIDEO_PLUGIN_DANMU_STATUS = "third_video_plugin_danmu_status";
  18. const THIRD_VIDEO_PLUGIN_SPEED = "third_video_plugin_speed";
  19. const THIRD_VIDEO_PLUGIN_SPEEDS = "third_video_plugin_speeds";
  20.  
  21. let videoSpeedElement = document.createElement("div"),
  22. currentHref = "",
  23. viewReportDiv;
  24. videoSpeedElement.setAttribute("id", "video_speed_div");
  25.  
  26. let style = document.createElement("style");
  27. style.type = "text/css";
  28. style.innerHTML = `
  29. .video-info-container,#viewbox_report {
  30. height: auto!important;
  31. }
  32. #video_speed_div {
  33. width:100%;
  34. height:24px;
  35. margin: 8px 0;
  36. }
  37. #video_speed_div button, #third_video_plugin_btn {
  38. outline: 0;
  39. padding: 4px 9px;
  40. margin-left: 10px;
  41. background-color: #f1f2f3;
  42. border: 0;
  43. color: #222;
  44. cursor: pointer;
  45. border-radius: 6px;
  46. }
  47. #third_video_plugin_btn:first-child {
  48. margin-left: 0;
  49. background-color: #000!important;
  50. }
  51. .video_speed_div-button-active {
  52. border: 0!important;
  53. background-color: #00aeec!important;
  54. color: #fff!important;
  55. }
  56. `;
  57. document.getElementsByTagName("head").item(0).appendChild(style);
  58. let keypressed = false;
  59.  
  60. document.addEventListener("keydown", function(e) {
  61. e = e || window.event;
  62. if (e.keyCode) keypressed = true;
  63. })
  64. document.addEventListener("keyup", function(e) {
  65. e = e || window.event;
  66. if (e.keyCode) keypressed = false;
  67. })
  68.  
  69. let _interval = setInterval(function () {
  70. if ((document.querySelector("bili-comments") || document.querySelector(".bili-comment") || document.querySelector(".bb-comment")) && document.getElementById("video_speed_div") === null) {
  71. addSpeedBtns();
  72. }
  73. }, 100);
  74.  
  75. // 默认关闭弹幕
  76. // setTimeout(function () {
  77. // closeDanmu();
  78. // }, 1500);
  79.  
  80. // 打开视频默认全屏
  81. // setTimeout(function() {
  82. // fullScreen();
  83. // }, 500);
  84.  
  85. function applySpeed(third_video_plugin_speed) {
  86. let videoObj = document.querySelector("video");
  87. if (!videoObj) videoObj = document.querySelector("bwp-video");
  88. if (videoObj) {
  89. videoObj.playbackRate = parseFloat(third_video_plugin_speed);
  90.  
  91. if (!videoObj.onloadstart) {
  92. videoObj.onloadstart = function(e) {
  93. let _plugin_speed = getThirdVideoPluginSpeed();
  94. videoObj.playbackRate = parseFloat(_plugin_speed);
  95. };
  96. }
  97.  
  98. let nextBtn = document.querySelector(".bilibili-player-iconfont-next");
  99. if (nextBtn) {
  100. let currentTime = videoObj.currentTime;
  101. let totalTime = videoObj.duration;
  102. if (totalTime - currentTime < 0.5) {
  103. // 视频还剩500ms的时候自动跳转到下一个视频,防止出现充电界面
  104. document.querySelector(".bilibili-player-iconfont-next").click();
  105. }
  106. }
  107.  
  108. let broswerPath = window.location.href;
  109. if (currentHref !== broswerPath) {
  110. currentHref = broswerPath;
  111. pageContentChange();
  112. }
  113.  
  114. let switchBtn = document.querySelector(".bilibili-player-video-danmaku-switch");
  115. if (switchBtn) switchBtn.addEventListener("click", danmuClickHandler, false);
  116. }
  117. }
  118.  
  119. function addSpeedBtns() {
  120. let position = "last";
  121. if (location.href.indexOf("/video") > -1) {
  122. viewReportDiv = document.querySelector("#viewbox_report");
  123. }else if (location.href.indexOf("/list") > -1) {
  124. viewReportDiv = document.querySelector(".video-info-container");
  125. }else if (location.href.indexOf("/bangumi") > -1) {
  126. viewReportDiv = document.querySelector("#player_module");
  127. position = "first";
  128. }
  129. // 创建一个设置倍速的按钮
  130. let speedsettingsbtn = document.createElement("button");
  131. speedsettingsbtn.innerHTML = "&nbsp;&nbsp;S&nbsp;&nbsp;";
  132. speedsettingsbtn.style.backgroundColor = "black";
  133. speedsettingsbtn.style.color = "white";
  134. speedsettingsbtn.setAttribute("id", "third_video_plugin_btn");
  135. speedsettingsbtn.addEventListener("click", speedsettingsevent);
  136. videoSpeedElement.appendChild(speedsettingsbtn);
  137.  
  138. initBtn();
  139.  
  140. videoSpeedElement.style.width = "100%";
  141. videoSpeedElement.style.height = "24px";
  142.  
  143. if (position == "last") {
  144. viewReportDiv.appendChild(videoSpeedElement);
  145. } else if (position == "first") {
  146. viewReportDiv.insertBefore(videoSpeedElement, viewReportDiv.firstChild);
  147. }
  148.  
  149.  
  150. clearInterval(_interval);
  151.  
  152. // 加载之间已经设置的速度, 在同一个页面中切换视频后,设置的速度就没了,这里用一个定时器,200ms设置一下
  153. // setInterval(function () { // 轮询更新视频时间
  154. setTimeout(function () { // 500毫秒后更新视频时间
  155. if (keypressed) return;
  156. let third_video_plugin_speed = getThirdVideoPluginSpeed();
  157. // 设置倍速按钮高亮
  158. hightlightBtn(third_video_plugin_speed);
  159.  
  160. // 应用速度
  161. applySpeed(third_video_plugin_speed);
  162.  
  163. }, 500);
  164. }
  165.  
  166. function getThirdVideoPluginSpeed() {
  167. let third_video_plugin_speed = localStorage.getItem(THIRD_VIDEO_PLUGIN_SPEED);
  168. if (!third_video_plugin_speed) {
  169. third_video_plugin_speed = "1";
  170. localStorage.setItem(THIRD_VIDEO_PLUGIN_SPEED, third_video_plugin_speed);
  171. }
  172. return third_video_plugin_speed;
  173. }
  174.  
  175. function danmuClickHandler(e) {
  176. if (e.isTrusted) {
  177. let span = document.querySelector(".bilibili-player-video-danmaku-switch>.choose_danmaku");
  178. if (span.textContent === "开启弹幕") {
  179. writeDanmuStatus(1);
  180. } else {
  181. writeDanmuStatus(2);
  182. }
  183. }
  184. }
  185.  
  186. function initBtn() {
  187. let speedArr = getStorageSpeeds();
  188. if (speedArr.length === 0) {
  189. speedArr = [0.5, 1, 1.5, 2, 2.5, 3, 4, 5];
  190. localStorage.setItem(THIRD_VIDEO_PLUGIN_SPEEDS, speedArr.join(","));
  191. }
  192. for (let i = 0; i < speedArr.length; i++) {
  193. let speed = speedArr[i];
  194. let btn = document.createElement("button");
  195. btn.innerHTML = "x" + speed;
  196. btn.style.width = "50px";
  197. btn.setAttribute("id", "third_video_plugin_btn_" + speed);
  198. btn.addEventListener("click", changeVideoSpeed);
  199. videoSpeedElement.appendChild(btn);
  200. }
  201. }
  202.  
  203. function getStorageSpeeds() {
  204. let storageSpeeds = localStorage.getItem(THIRD_VIDEO_PLUGIN_SPEEDS);
  205. if (!storageSpeeds) return [];
  206. return storageSpeeds.split(",");
  207. }
  208.  
  209. function speedsettingsevent() {
  210. let a = window.prompt("输入倍速,以英文逗号隔开。", getStorageSpeeds().join(","));
  211. if (!a) return;
  212. a = a.replace(/\s+/g, "");
  213. let speeds = a.split(",");
  214. for (let i = 0; i < speeds.length; i++) {
  215. let speed = parseInt(speeds[i]);
  216. if (isNaN(speed)) return;
  217. }
  218. localStorage.setItem(THIRD_VIDEO_PLUGIN_SPEEDS, a);
  219. // clear btns
  220. let btns_length = videoSpeedElement.childNodes.length;
  221. for (let i = 1; i < btns_length; i++) {
  222. let btn = videoSpeedElement.childNodes[1];
  223. videoSpeedElement.removeChild(btn);
  224. }
  225. let storageSpeed = localStorage.getItem(THIRD_VIDEO_PLUGIN_SPEED);
  226. if (speeds.indexOf(storageSpeed) === -1) localStorage.setItem(THIRD_VIDEO_PLUGIN_SPEED, "1");
  227. // add new btns
  228. initBtn();
  229. }
  230.  
  231. function pageContentChange() {
  232. setTimeout(function () {
  233. // 弹幕设置
  234. let storageDanmuStatus = localStorage.getItem(THIRD_VIDEO_PLUGIN_DANMU_STATUS);
  235. if (!storageDanmuStatus) {
  236. storageDanmuStatus = 1; // 默认开启
  237. writeDanmuStatus(1);
  238. }
  239. if (parseInt(storageDanmuStatus) !== 1) {
  240. document.querySelector(".bui-checkbox").click();
  241. }
  242. }, 1000);
  243. }
  244.  
  245. function writeDanmuStatus(status) {
  246. if (status === 1 || status === 2) {
  247. localStorage.setItem(THIRD_VIDEO_PLUGIN_DANMU_STATUS, status);
  248. }
  249. }
  250.  
  251. function changeVideoSpeed(e) {
  252. let speed = parseFloat(e.target.innerHTML.replace("x", ""));
  253. localStorage.setItem(THIRD_VIDEO_PLUGIN_SPEED, speed);
  254. hightlightBtn(speed);
  255.  
  256. // 应用速度
  257. applySpeed(speed);
  258. }
  259.  
  260. function hightlightBtn(speed) {
  261. let currentSpeedBtn = document.getElementById("third_video_plugin_btn_" + speed);
  262. if (currentSpeedBtn && currentSpeedBtn.className.indexOf("video_speed_div-button-active") === -1) {
  263. for (let i = 0; i < videoSpeedElement.childNodes.length; i++) {
  264. let btn = videoSpeedElement.childNodes[i];
  265. btn.setAttribute("class", "");
  266. }
  267. currentSpeedBtn.setAttribute("class", "video_speed_div-button-active");
  268. }
  269. }
  270.  
  271. function closeDanmu() {
  272. document.querySelector(".bui-checkbox").click();
  273. }
  274.  
  275. function fullScreen() {
  276. document.querySelector(".bilibili-player-iconfont-web-fullscreen-off").click();
  277. }
  278. })();

QingJ © 2025

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