YouTube Player Controls

Adds features to YouTube player page: fill window with video, stretch, float video, set HD 4K 8K resolution, hide annotations and ads, click skip ads, click show more, loop, replay a video segment, pause at start/end, zoom and pan video.

安装此脚本?
作者推荐脚本

您可能也喜欢AIGPT Everywhere

安装此脚本
  1. // ==UserScript==
  2. // @name YouTube Player Controls
  3. // @namespace https://gf.qytechs.cn/en/users/670188-hacker09?sort=daily_installs
  4. // @version 1
  5. // @description Adds features to YouTube player page: fill window with video, stretch, float video, set HD 4K 8K resolution, hide annotations and ads, click skip ads, click show more, loop, replay a video segment, pause at start/end, zoom and pan video.
  6. // @author hacker09
  7. // @match http://www.youtube.com/*
  8. // @match https://www.youtube.com/*
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // @grant GM_registerMenuCommand
  12. // @grant GM_unregisterMenuCommand
  13. // @noframes
  14. // ==/UserScript==
  15.  
  16. //==================================================================
  17. //Userscript specific functions
  18.  
  19. var doc = document;
  20. var win = window;
  21.  
  22. if (win.frameElement) throw new Error("Stopped JavaScript.");
  23.  
  24. function set_pref(preference, new_value) {
  25. GM_setValue(preference, new_value);
  26. }
  27.  
  28. function get_pref(preference) {
  29. return GM_getValue(preference);
  30. }
  31.  
  32. function init_pref(preference, new_value) {
  33. var value = get_pref(preference);
  34. if (value == null) {
  35. set_pref(preference, new_value);
  36. value = new_value;
  37. }
  38. return value;
  39. }
  40.  
  41. var option_menu_command_ID = null;
  42. var button_menu_command_ID = null;
  43.  
  44. function build_menu_commands() {
  45. if (option_menu_command_ID || button_menu_command_ID) return;
  46. if (doc.getElementById("ytcp_fromcontrolslink")) return;
  47.  
  48. option_menu_command_ID = GM_registerMenuCommand("Options", function() {ytplayer_options(true);});
  49.  
  50. if (get_pref("ytButton"))
  51. show_button_menu_command();
  52. else
  53. hide_button_menu_command();
  54. }
  55.  
  56. function hide_button_menu_command() {
  57. if (get_pref("ytButton")) set_pref("ytButton", false);
  58. if (button_menu_command_ID) GM_unregisterMenuCommand(button_menu_command_ID);
  59. button_menu_command_ID = GM_registerMenuCommand("Show Button",show_button_menu_command);
  60. build_yt_control();
  61. }
  62.  
  63. function show_button_menu_command() {
  64. if (!get_pref("ytButton")) set_pref("ytButton", true);
  65. if (button_menu_command_ID) GM_unregisterMenuCommand(button_menu_command_ID);
  66. button_menu_command_ID = GM_registerMenuCommand("Hide Button",hide_button_menu_command);
  67. build_yt_control();
  68. }
  69.  
  70. function delete_menu_commands() {
  71. if (button_menu_command_ID) GM_unregisterMenuCommand(button_menu_command_ID);
  72. if (option_menu_command_ID) GM_unregisterMenuCommand(option_menu_command_ID);
  73. option_menu_command_ID = null;
  74. button_menu_command_ID = null;
  75. }
  76.  
  77.  
  78. //==================================================================
  79. // Styles
  80.  
  81. var style_annotations = "\
  82. .html5-video-player .annotation,\
  83. .html5-video-player .video-annotations,\
  84. .html5-video-player .ytp-cards-button,\
  85. .html5-video-player .ytp-cards-teaser,\
  86. .html5-video-player .iv-drawer,\
  87. .html5-video-player .ima-container,\
  88. .html5-video-player .ytp-paid-content-overlay,\
  89. .html5-video-player .ytp-ad-overlay-slot,\
  90. .html5-video-player .ytp-suggested-action {display:none !important;}\
  91. ";
  92.  
  93. var style_extra_ads = "\
  94. #player-ads,\
  95. #offer-module,\
  96. ytd-compact-promoted-video-renderer,\
  97. ytd-promoted-sparkles-web-renderer,\
  98. *[target-id='engagement-panel-ads'] {display:none !important;}\
  99. ";
  100.  
  101. var style_basic = "\
  102. /* messages */\
  103. .ytpc_message {position:fixed; top:0px; left:0px; font:12px/15px arial,sans-serif; color:white !important; background-color:black !important; margin:0px; padding:10px; border-radius:3px; z-index:2147483647;}\
  104. .ytpc_message[hide] {display:none;}\
  105. /* options */\
  106. #ytpc_options_popup {direction:ltr; width:240px; box-shadow:0px 0px 6px 2px gray; font-size:11px; color:black; background:white; padding:5px; border-radius:5px; user-select:none; -moz-user-select:none;}\
  107. #ytpc_options_popup.ytpc_popup_top {position:fixed; top:0px; right:10px; z-index:1000000;}\
  108. #ytpc_options_popup.ytpc_popup_normal {position:absolute; top:5px; z-index:10;}\
  109. body[dir='ltr'] #ytpc_options_popup.ytpc_popup_normal {right:5px;}\
  110. body[dir='rtl'] #ytpc_options_popup.ytpc_popup_normal {left:5px;}\
  111. html[dark] #ytpc_options_popup {color:#e0e0e0; background:#1b1b1b;}\
  112. #ytpc_options_popup input {margin:3px 2px -2px 5px !important;}\
  113. .ytpc_options_group.space {margin-bottom:3px; border:1px solid lightgray; border-radius:3px;}\
  114. html[dark] .ytpc_options_group.space {border:1px solid #606060 !important;}\
  115. .ytpc_options_group.space *[hide] {color:steelblue; margin-left:7px;}\
  116. .ytpc_options_group[hide] *[hide] {opacity:0.5;}\
  117. .ytpc_options_group.column > span:first-child {display:inline-block; min-width:120px;}\
  118. .ytpc_options_text {font-weight:500; font-size:12px; margin-left:5px; margin-top:7px;}\
  119. .ytpc_options_close {font-size:14px; color:#ff8888; position:absolute; top:0px; right:4px; cursor:pointer;}\
  120. .ytpc_options_close:hover {font-weight:bold; color:red;}\
  121. .ytpc_options_title {font-weight:500; font-size:14px; padding:3px 5px !important;}\
  122. .ytpc_float_button {margin-left: 5px; padding:0px 2px; background-color:gray; color:white !important; border-radius:2px; opacity:0.7;}\
  123. .ytpc_float_button:hover {opacity:1;}\
  124. /* cog button */\
  125. #ytpc_ytcontrol_container {position:relative; float:right; z-index:700;}\
  126. body[dir='rtl'] #ytpc_ytcontrol_container {float:left !important;}\
  127. #ytpc_cog_container {position:absolute; top:5px;}\
  128. body[dir='ltr'] #ytpc_cog_container {right:5px;}\
  129. body[dir='rtl'] #ytpc_cog_container {left:5px;}\
  130. #ytpc_ytcontrol_button {overflow:hidden; position:relative; float:right; margin:-3px -2px 0px 0px; width:24px; height:23px; cursor:pointer; opacity:0.7; background-size:100%; user-select:none; -moz-user-select:none; background-image:url('data:image/png;base64,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'); }\
  131. #ytpc_ytcontrol_button:hover {opacity:1;}\
  132. /* masthead */\
  133. #content[ytpc_cinema]:not([float]) #masthead-container[ytpc_hide] {display:none !important;}\
  134. #content[ytpc_cinema][ytpc_top]:not([float]) #page-manager {margin-top:0px !important;}\
  135. ";
  136.  
  137.  
  138. //==============================================================
  139. //basic
  140.  
  141. function newNode(kind, id, classname, refnode, position) {
  142.  
  143. var node = doc.createElement(kind);
  144.  
  145. if (node == null) return null;
  146.  
  147. if (id != null) node.id = id;
  148.  
  149. if (classname != null) node.className = classname;
  150.  
  151. if (refnode != null) {
  152. switch (position) {
  153. //insert after refnode
  154. case 'after':
  155. if (refnode.nextSibling != null)
  156. refnode.parentNode.insertBefore(node, refnode.nextSibling);
  157. else
  158. refnode.parentNode.appendChild(node);
  159. break;
  160.  
  161. //insert before refnode
  162. case 'before':
  163. refnode.parentNode.insertBefore(node, refnode);
  164. break;
  165.  
  166. //insert as first child of refnode
  167. case 'first':
  168. var child = refnode.childNodes[0];
  169. if (child != null)
  170. refnode.insertBefore(node, child);
  171. else
  172. refnode.appendChild(node);
  173. break;
  174.  
  175. //insert as last child of refnode
  176. case 'last':
  177. default:
  178. refnode.appendChild(node);
  179. break;
  180. }
  181. }
  182.  
  183. return node;
  184. }
  185.  
  186. var message_timeout_ID;
  187.  
  188. function message(str, time) {
  189. var node = doc.getElementById("ytpc_message_node");
  190. if (!node)
  191. node = newNode("div", "ytpc_message_node", "ytpc_message", doc.body);
  192. node.removeAttribute("hide");
  193. node.textContent = str + "\n";
  194.  
  195. if (time) {
  196. clearTimeout(message_timeout_ID);
  197. message_timeout_ID = setTimeout(function () {
  198. var n = doc.getElementById("ytpc_message_node");
  199. if (n)
  200. n.setAttribute("hide","true");
  201. },
  202. time);
  203. }
  204. }
  205.  
  206.  
  207. function insertStyle(str, id) {
  208. var styleNode = null;
  209.  
  210. if (id != null) {
  211. styleNode = doc.getElementById(id);
  212. }
  213.  
  214. if (styleNode == null) {
  215. styleNode = newNode("style", id, null, doc.head);
  216. styleNode.setAttribute("type", "text/css");
  217. }
  218.  
  219. if (styleNode.textContent != str)
  220. styleNode.textContent = str;
  221. }
  222.  
  223. function deleteStyle(id) {
  224. var styleNode = doc.getElementById(id);
  225. if (styleNode) styleNode.parentElement.removeChild(styleNode);
  226. }
  227.  
  228.  
  229. function injectScript(str, src) {
  230. var script = doc.createElement("script");
  231. if (str) script.textContent = str;
  232. if (src) script.src = src;
  233. doc.body.appendChild(script);
  234. if (!src) doc.body.removeChild(script);
  235. }
  236.  
  237.  
  238. function simulClick(el) {
  239. var clickEvent = doc.createEvent('MouseEvents');
  240. clickEvent.initEvent('click', true, true);
  241. clickEvent.artificialevent = true;
  242. el.dispatchEvent(clickEvent);
  243. }
  244.  
  245.  
  246. function xpath(outer_dom, inner_dom, query) {
  247. //XPathResult.ORDERED_NODE_SNAPSHOT_TYPE = 7
  248. return outer_dom.evaluate(query, inner_dom, null, 7, null);
  249. }
  250.  
  251.  
  252. function docsearch(query) {
  253. return xpath(doc, doc, query);
  254. }
  255.  
  256.  
  257. function innersearch(inner, query) {
  258. return xpath(doc, inner, query);
  259. }
  260.  
  261.  
  262.  
  263. //==================================================================
  264. //YT Player
  265.  
  266. function ytplayer_script() {
  267. injectScript(" var time1=0;\
  268. var time2=0;\
  269. \
  270. function f() {\
  271. var a = document.getElementById('c4-player') || document.getElementById('movie_player');\
  272. var b = document.getElementById('ytpc_ytplayer_state');\
  273. if (a == null || b == null) return;\
  274. \
  275. if (b.getAttribute('loop') == 'true') {\
  276. if (window.location.href.indexOf('list=') == -1) {\
  277. if (a.getPlayerState() == 0) {\
  278. a.playVideo();\
  279. }\
  280. }\
  281. else {\
  282. var d = a.getDuration();\
  283. if ((d - a.getCurrentTime() <= 1) && d > 0) {\
  284. a.playVideoAt(a.getPlaylistIndex());\
  285. }\
  286. }\
  287. }\
  288. else {\
  289. if (b.getAttribute('pause_end') == 'true' && b.getAttribute('pause_end_mark') != 'true') {\
  290. var d = a.getDuration();\
  291. if ((d - a.getCurrentTime() <= 1) && d > 0) {\
  292. a.pauseVideo();\
  293. b.setAttribute('pause_end_mark', 'true');\
  294. }\
  295. }\
  296. }\
  297. \
  298. if (b.getAttribute('replay') == 'true')\
  299. if(a.getCurrentTime() >= time2 && time2 > time1)\
  300. a.seekTo(time1,true);\
  301. }\
  302. \
  303. document.addEventListener('ReplayMark', function (e) {\
  304. var a = document.getElementById('c4-player') || document.getElementById('movie_player');\
  305. var b = document.getElementById('ytpc_ytplayer_state');\
  306. switch (e.detail.pos){\
  307. case '0': time1 = 0; time2 = 0; b.setAttribute('replay','false'); break;\
  308. case '1': time1 = a.getCurrentTime(); break;\
  309. case '2': time2 = a.getCurrentTime();\
  310. if (time2 <= time1) b.setAttribute('replay','false');\
  311. break;\
  312. }},\
  313. false);\
  314. \
  315. f();\
  316. setInterval(f, 1000);\
  317. ");
  318. }
  319.  
  320.  
  321. function ytplayer_state(attr, value) {
  322. var node = doc.getElementById('ytpc_ytplayer_state');
  323. if (!node) {
  324. node = newNode("div", 'ytpc_ytplayer_state', null, doc.body);
  325. node.style.display = "none";
  326. }
  327.  
  328. if (!node) return null;
  329.  
  330. if (attr && value) node.setAttribute(attr, value);
  331. else if (attr) return node.getAttribute(attr);
  332. }
  333.  
  334.  
  335. function set_loop() { ytplayer_state('loop', 'true'); }
  336. function set_noloop() { ytplayer_state('loop', 'false'); }
  337. function set_pause_end() { ytplayer_state('pause_end', 'true'); }
  338. function set_nopause_end() { ytplayer_state('pause_end', 'false'); }
  339. function reset_pause_end_mark() { ytplayer_state('pause_end_mark', 'false'); }
  340. function success_pause() { return ytplayer_state('pause_status') == 'success'; }
  341. function success_quality() { return ytplayer_state('quality_status') == 'success'; }
  342.  
  343.  
  344. function adjust_pause_end() {
  345. var islive = docsearch("//yt-view-count-renderer/*[contains(.,'watching now')]").snapshotLength > 0;
  346. //message("Is live: " + islive);
  347. //alert("Is live: " + islive);
  348. get_pref("ytPauseEnd") && !islive ? set_pause_end() : set_nopause_end();
  349. reset_pause_end_mark();
  350. }
  351.  
  352. function adjust_loop() {
  353. get_pref("ytLoop") ? set_loop() : set_noloop();
  354. }
  355.  
  356.  
  357. function ytplayer_pause() {
  358. ytplayer_state('pause_status', 'fail');
  359.  
  360. injectScript("var a = document.getElementById('c4-player') || document.getElementById('movie_player');\
  361. if (a != null)\
  362. if (a.pauseVideo != null){\
  363. a.pauseVideo();\
  364. var n = document.getElementById('ytpc_ytplayer_state');\
  365. if (n) n.setAttribute('pause_status', 'success');\
  366. }\
  367. ");
  368. }
  369.  
  370.  
  371. function ytplayer_quality(def) {
  372. if (def == "off") return;
  373.  
  374. ytplayer_state('quality_status', 'fail');
  375.  
  376. injectScript("var a = document.getElementById('c4-player') || document.getElementById('movie_player');\
  377. if (a != null)\
  378. if (a.setPlaybackQualityRange != null){\
  379. var def = '" + def + "';\
  380. var l = a.getAvailableQualityLevels();\
  381. if (l){\
  382. /*alert(l);*/\
  383. if (!l.includes(def) && l.length > 0) {\
  384. def = l[0];\
  385. /*alert(def);*/\
  386. }\
  387. }\
  388. a.setPlaybackQualityRange(def);\
  389. var n = document.getElementById('ytpc_ytplayer_state');\
  390. if (n) n.setAttribute('quality_status', 'success');\
  391. }\
  392. ");
  393. }
  394.  
  395. var pl_mouseover = false;
  396. var pl_mouse_events_started = false;
  397.  
  398. function pl_reset_mouseevents() {
  399. pl_mouseover = false;
  400. pl_mouse_events_started = false;
  401. }
  402.  
  403. function pl_enable_mouseevents() {
  404. var node = doc.getElementById("ytd-player");
  405. if (!node) {
  406. pl_reset_mouseevents();
  407. return;
  408. }
  409.  
  410. if (!pl_mouse_events_started) {
  411. node.addEventListener("mouseover", function (e) {pl_mouseover = true;});
  412. node.addEventListener("mouseenter", function (e) {pl_mouseover = true;});
  413. node.addEventListener("mousemove", function (e) {pl_mouseover = true;});
  414. node.addEventListener("mouseleave", function (e) {pl_mouseover = false;});
  415. node.addEventListener("mouseout", function (e) {pl_mouseover = false;});
  416.  
  417. pl_mouse_events_started = true;
  418. }
  419. }
  420.  
  421. doc.addEventListener('keydown', keyDownMark, false);
  422.  
  423. var key_message_timeout = 2000;
  424.  
  425. function keyDownMark(event) {
  426. if (!pl_mouseover || !get_pref("ytKeys")) return;
  427.  
  428. var name = event.key;
  429. var code = event.code;
  430. //message(name);
  431. //message(code);
  432. if (code == "KeyE" || name == "Escape") {
  433. ytplayer_state('replay', 'false');
  434. doc.dispatchEvent(new CustomEvent("ReplayMark",{detail:{pos:"1"}}));
  435. if (code == "KeyE") message("Replay Start Time", key_message_timeout);
  436. }
  437. else if (code == "KeyR"){
  438. ytplayer_state('replay', 'true');
  439. doc.dispatchEvent(new CustomEvent("ReplayMark",{detail:{pos:"2"}}));
  440. message("Replay End Time", key_message_timeout);
  441. }
  442. }
  443.  
  444. function reset_keyDownMark() {
  445. doc.dispatchEvent(new CustomEvent("ReplayMark",{detail:{pos:"0"}}));
  446. ytplayer_state('replay', 'false');
  447. }
  448.  
  449.  
  450. //==============================================================
  451. //preferences
  452.  
  453. init_pref("ytPause", false);
  454. init_pref("ytPauseEnd", false);
  455. init_pref("ytDef", "off");
  456. init_pref("ytLoop", false);
  457. init_pref("ytCine", false);
  458. init_pref("ytStretch", true);
  459. init_pref("ytHide", true);
  460. init_pref("ytAnnot", false);
  461. init_pref("ytAds", false);
  462. init_pref("ytAdsExtra", false);
  463. init_pref("ytFloat", true);
  464. init_pref("ytFSmall", true);
  465. init_pref("ytFloatPos",1);
  466. init_pref("ytLoad", false);
  467. init_pref("ytKeys", false);
  468. init_pref("ytZoom", false);
  469. init_pref("ytButton", true);
  470.  
  471. function close_ytplayer_options(e) {
  472. var popup = doc.getElementById("ytpc_options_popup");
  473. if (!popup) return;
  474.  
  475. if (!e) {
  476. popup.parentNode.removeChild(popup);
  477. return;
  478. }
  479.  
  480. if (e.artificialevent) return;
  481.  
  482. var p = e.target;
  483. for (var i = 0; i < 5; i++) {
  484. if (p) {
  485. if (p.id)
  486. if (p.id.search(/ytpc/) == 0) {
  487. e.stopPropagation();
  488. return;
  489. }
  490. if (p.className)
  491. if (p.className.search(/ytpc/) == 0) {
  492. e.stopPropagation();
  493. return;
  494. }
  495. }
  496. p = p.parentNode;
  497. }
  498.  
  499. popup.parentNode.removeChild(popup);
  500. }
  501.  
  502.  
  503. function new_checkbox(prefname, str, node_kind, title, parent, value, func, hide1, hide2) {
  504. var div = newNode(node_kind, null, "ytpc_generic", parent);
  505. if (title) div.title = title;
  506. var input = newNode("input", null, "ytpc_generic", div);
  507. input.type = "checkbox";
  508. if (!value) {
  509. input.checked = get_pref(prefname);
  510. if (hide1 && !input.checked) parent.setAttribute("hide", "true");
  511. input.onclick = function (e) {
  512. var val = get_pref(prefname);
  513. if (hide2 && parent.getAttribute("hide")) val = !val; //no change if hidden
  514. set_pref(prefname, !val);
  515. e.target.checked = !val;
  516. if (hide1)
  517. if (!val)
  518. parent.removeAttribute("hide");
  519. else
  520. parent.setAttribute("hide", "true");
  521. if (func) func();
  522. };
  523. }
  524. else {
  525. input.value = value;
  526. input.checked = (get_pref(prefname) == input.value);
  527. input.onclick = function (e) {
  528. var val = get_pref(prefname);
  529. set_pref(prefname, e.target.value);
  530. e.target.checked = true;
  531. var other = innersearch(parent.parentNode, ".//input[@value='" + val + "']").snapshotItem(0);
  532. if (other && (other != e.target)) other.checked = false;
  533. if (func) func();
  534. };
  535. }
  536. var span = newNode("span", null, "ytpc_generic", div);
  537. span.textContent = str;
  538. if (hide2) div.setAttribute("hide", "true");
  539. }
  540.  
  541. function new_float_pos_button(title, parent){
  542. var span = newNode("span", null, "ytpc_float_button", parent);
  543. if (title) span.title = title;
  544. span.textContent = "pos "+ get_pref("ytFloatPos");
  545.  
  546. span.onclick = function(e) {
  547. var val = get_pref("ytFloatPos")+1;
  548. if (val == 5) val=1;
  549. set_pref("ytFloatPos",val);
  550. this.textContent = "pos "+ get_pref("ytFloatPos");
  551. }
  552. }
  553.  
  554.  
  555. function ytplayer_options(top) {
  556. var popup = doc.getElementById("ytpc_options_popup");
  557. if (popup) return;
  558.  
  559. if (top)
  560. popup = newNode("div", "ytpc_options_popup", "ytpc_popup_top", doc.body);
  561. else {
  562. var parent = doc.getElementById("ytpc_ytcontrol_container");
  563. if (!parent) return;
  564. popup = newNode("span", "ytpc_options_popup", "ytpc_popup_normal", parent);
  565. }
  566.  
  567. var title_node = newNode("div", null, "ytpc_options_title", popup);
  568. title_node.textContent = "YouTube Player Controls";
  569.  
  570. var closemark = newNode("span", null, "ytpc_options_close", popup);
  571. closemark.textContent = "\u2716";
  572. closemark.title = "close";
  573. closemark.onclick = function (e) { e.stopPropagation(); close_ytplayer_options(); }
  574.  
  575. var groupCine = newNode("div", null, "ytpc_options_group space", popup);
  576. new_checkbox("ytCine", "Fill Window", "span", "fits video horizontally in window", groupCine, null, function () { resetTheaterMode(); cinema(0); }, true, false);
  577. new_checkbox("ytStretch", "Stretch", "span", "fills the whole viewing area", groupCine, null, function () { cinema(0); }, false, true);
  578. new_checkbox("ytHide", "Hide Search", "span", "auto hides the search bar on top", groupCine, null, function () { cinema(1); }, false, true);
  579.  
  580. var groupFloat = newNode("div", null, "ytpc_options_group column", popup);
  581. new_checkbox("ytFloat", "Float Video", "span", "allows video to float while scrolling", groupFloat, null, function () { float(0); }, true, false);
  582. new_checkbox("ytFSmall", "Small Float", "span", "shows a small size video while floating", groupFloat, null, null, false, true);
  583. new_float_pos_button("float position\nclick to change", groupFloat);
  584.  
  585. var groupAnnot = newNode("div", null, "ytpc_options_group column", popup);
  586. new_checkbox("ytAnnot", "Hide Annotations", "span", "hide the video annotations", groupAnnot, null, annotation);
  587. new_checkbox("ytAdsExtra", "Hide Related Ads", "span", "hide ads in the related videos section", groupAnnot, null, extra_ads);
  588.  
  589. var groupClick = newNode("div", null, "ytpc_options_group column", popup);
  590. new_checkbox("ytLoad", "Click Show More", "span", "auto click \'more\' in video description", groupClick, null, function() { auto_load(10); });
  591. new_checkbox("ytAds", "Click Skip Ads", "span", "auto click the \'skip ads\' button", groupClick);
  592.  
  593. var groupKeys = newNode("div", null, "ytpc_options_group column", popup);
  594. new_checkbox("ytKeys", "Replay Keys", "span", "Replay a video segment:\nE marks start time\nR marks end time\npress ESC or E to cancel replay", groupKeys, null, function() {reset_keyDownMark();});
  595. new_checkbox("ytZoom", "Pan and Zoom", "span", "Pan and Zoom in fill window mode:\nZ zoom-in, X zoom-out\nto pan use the mouse or keys\nG left, H right, Y up, B down\npress ESC or CTRL+SHIFT to reset", groupKeys, null, function() {cinema(0);});
  596.  
  597. var groupPause = newNode("div", null, "ytpc_options_group", popup);
  598. new_checkbox("ytLoop", "Loop Video", "span", "replay the whole video from beginning", groupPause, null, adjust_loop);
  599. new_checkbox("ytPause", "Pause Start", "span", "pause the video when it starts", groupPause);
  600. new_checkbox("ytPauseEnd", "Pause End", "span", "pause the video when it ends", groupPause, null, adjust_pause_end);
  601.  
  602. var div = newNode("div", null, "ytpc_options_text", popup);
  603. div.textContent = "Resolution";
  604. div.title = "set highest preferred video resolution";
  605. var groupDef1 = newNode("div", null, "ytpc_options_group", popup);
  606. var groupDef2 = newNode("div", null, "ytpc_options_group", popup);
  607. var groupDef3 = newNode("div", null, "ytpc_options_group", popup);
  608. new_checkbox("ytDef", "OFF", "span", "inactive", groupDef1, "off");
  609. new_checkbox("ytDef", "Auto", "span", null, groupDef1, "auto", function() {ytplayer_quality("auto");});
  610. new_checkbox("ytDef", "144p", "span", null, groupDef1, "tiny", function() {ytplayer_quality("tiny");});
  611. new_checkbox("ytDef", "240p", "span", null, groupDef1, "small", function() {ytplayer_quality("small");});
  612. new_checkbox("ytDef", "360p", "span", null, groupDef1, "medium", function() {ytplayer_quality("medium");});
  613. new_checkbox("ytDef", "480p", "span", null, groupDef2, "large", function() {ytplayer_quality("large");});
  614. new_checkbox("ytDef", "720p", "span", null, groupDef2, "hd720", function() {ytplayer_quality("hd720");});
  615. new_checkbox("ytDef", "HD 1080p", "span", null, groupDef2, "hd1080", function() {ytplayer_quality("hd1080");});
  616. new_checkbox("ytDef", "HD 1440p", "span", null, groupDef2, "hd1440", function() {ytplayer_quality("hd1440");});
  617. new_checkbox("ytDef", "4K 2160p", "span", null, groupDef3, "hd2160", function() {ytplayer_quality("hd2160");});
  618. new_checkbox("ytDef", "5K 2880p", "span", null, groupDef3, "hd2880", function() {ytplayer_quality("hd2880");});
  619. new_checkbox("ytDef", "8K 4320p", "span", null, groupDef3, "highres", function() {ytplayer_quality("highres");});
  620. }
  621.  
  622. function build_yt_control() {
  623. if (get_pref("ytButton")) {
  624. var parent = doc.getElementById("ytpc_ytcontrol_container");
  625. if (parent) return;
  626.  
  627. //button container
  628. //var pp = null;
  629. var pp = doc.getElementById("below");
  630.  
  631. if (!pp) pp = doc.getElementById("primary-inner");
  632.  
  633. if (!pp) return;
  634.  
  635. parent = newNode("span", "ytpc_ytcontrol_container", null, pp, 'first');
  636. var node = newNode("span", "ytpc_cog_container", null, parent);
  637. var control = newNode("span", "ytpc_ytcontrol_button", null, node);
  638.  
  639. control.title = "YouTube Player Controls";
  640. control.onclick = function() {ytplayer_options(false);};
  641. }
  642. else {
  643. node = doc.getElementById("ytpc_ytcontrol_container");
  644. if (node) node.parentElement.removeChild(node);
  645. }
  646. }
  647.  
  648.  
  649. //==================================================================
  650. //Theater mode
  651.  
  652. function setTheaterMode() {
  653. if (docsearch("//ytd-page-manager/ytd-watch-flexy[@theater]").snapshotLength > 0) return; //already in theater mode
  654. var thnode = docsearch("//ytd-page-manager/ytd-watch-flexy//*[@class='ytp-chrome-controls']//*[contains(@class,'ytp-size-button')]").snapshotItem(0);
  655. if (thnode) simulClick(thnode);
  656. }
  657.  
  658. function resetTheaterMode() {
  659. if (get_pref("ytCine")) return;
  660.  
  661. if (docsearch("//ytd-page-manager/ytd-watch-flexy[@theater]").snapshotLength == 0) return; //already in default view
  662. var thnode = docsearch("//ytd-page-manager/ytd-watch-flexy//*[@class='ytp-chrome-controls']//*[contains(@class,'ytp-size-button')]").snapshotItem(0);
  663. if (thnode) simulClick(thnode);
  664.  
  665. deleteStyle("ytpc_style_cinemode");
  666. showmast(false);
  667. }
  668.  
  669. function showmast(movetop) {
  670. var mastoffset = doc.getElementById("masthead-container");
  671. if (mastoffset) {
  672. mastoffset.removeAttribute("ytpc_hide");
  673. if (!movetop)
  674. mastoffset.parentNode.removeAttribute("ytpc_top");
  675. }
  676. }
  677.  
  678. function hidemast(movetop) {
  679. var mastoffset = doc.getElementById("masthead-container");
  680. if (mastoffset) {
  681. mastoffset.setAttribute("ytpc_hide", "");
  682. if (movetop)
  683. mastoffset.parentNode.setAttribute("ytpc_top", "");
  684. }
  685. }
  686.  
  687. var search_height = 56;
  688. var key_left_offset = 0;
  689. var key_up_offset = 0;
  690. var key_zoom = 1;
  691.  
  692. function reset_key_offset_zoom() {
  693. key_left_offset = 0;
  694. key_up_offset = 0;
  695. key_zoom = 1;
  696. }
  697.  
  698. function cinema(start_count) {
  699. if (start_count == 0) {
  700. reset_key_offset_zoom();
  701. }
  702.  
  703. //not video page
  704. if (win.location.href.indexOf("watch?") == -1) {
  705. showmast(false);
  706. insertStyle("", "ytpc_style_cinemode");
  707. return;
  708. }
  709.  
  710. //video page
  711. if (!get_pref("ytCine")) return;
  712.  
  713. var page = docsearch("//ytd-page-manager/ytd-watch-flexy").snapshotItem(0);
  714. if (!page) return;
  715.  
  716. setTheaterMode();
  717.  
  718. var intheater = page.getAttribute("theater") != null;
  719. var fullscreen = page.getAttribute("fullscreen") != null;
  720.  
  721. if (intheater || fullscreen)
  722. page.parentNode.parentNode.setAttribute("ytpc_cinema", "");
  723. else
  724. page.parentNode.parentNode.removeAttribute("ytpc_cinema");
  725.  
  726. //check at most 5 times
  727. if (start_count >= 5) return;
  728.  
  729. var hide = get_pref("ytHide") || fullscreen;
  730.  
  731. if (hide && !fullscreen) { //hide or show search bar
  732. hidemast(true);
  733. if (win.pageYOffset > 0)
  734. showmast(true);
  735. }
  736. else
  737. showmast(false);
  738.  
  739. var H = doc.documentElement.clientHeight || doc.body.clientHeight;
  740. var W = doc.documentElement.clientWidth || doc.body.clientWidth;
  741. var view_height = H - (hide ? 0 : search_height); //visible height, adjust for search bar
  742. var view_width = W;
  743. var view_ratio = view_width / view_height;
  744.  
  745. var pl = docsearch("//ytd-watch-flexy//*[contains(@class,'html5-main-video')]").snapshotItem(0);
  746. if (!pl) return;
  747. registerMouse(pl);
  748.  
  749. var pwidth = Number(pl.style.width.replace(/[^\d\.\-]/g, '')); //video width
  750. var pheight = Number(pl.style.height.replace(/[^\d\.\-]/g, '')); //video height
  751. var pratio = pwidth / pheight; //video aspect ratio
  752.  
  753. var height = 1; // actual video height in view area
  754. var width = 1;
  755. var left = 0;
  756. var top = 0;
  757.  
  758. var stretch = get_pref("ytStretch"); //horizontal stretch of videos
  759.  
  760. if (stretch) {
  761. if (pratio < view_ratio) {
  762. width = view_width;
  763. height = width / pratio;
  764. top = -(height - view_height) / 2;
  765. }
  766. else {
  767. height = view_height;
  768. width = height * pratio;
  769. left = -(width - view_width) / 2;
  770. }
  771. }
  772. else{
  773. if (pratio < view_ratio) {
  774. height = view_height;
  775. width = height * pratio;
  776. left = -(width - view_width) / 2;
  777. }
  778. else{
  779. width = view_width;
  780. height = width / pratio;
  781. //top = -(height - view_height) / 2;
  782. view_height = height;
  783. if (hide && (!fullscreen) && (view_height <= H - search_height))
  784. showmast(false);
  785. }
  786. }
  787.  
  788. var zheight = height * key_zoom;
  789. var zwidth = width * key_zoom;
  790. var ztop = -(zheight - height) / 2;
  791. var zleft = -(zwidth - width) / 2;
  792. height = zheight;
  793. width = zwidth;
  794. top = top + ztop + key_up_offset*key_zoom;
  795. left = left + zleft + key_left_offset*key_zoom;
  796.  
  797. height = Math.round(height);
  798. width = Math.round(width);
  799. left = Math.round(left);
  800. top = Math.round(top);
  801.  
  802. insertStyle("\
  803. ytd-watch-flexy[theater]:not([float]) #full-bleed-container {height:" + view_height + "px !important; min-height:" + view_height + "px !important; max-height:" + view_height + "px !important;}\
  804. ytd-watch-flexy[theater]:not([float]) .html5-main-video {width:" + width + "px !important; min-width:" + width + "px !important; max-width:" + width + "px !important; height:" + height + "px !important; min-height:" + height + "px !important; max-height:" + height + "px !important; left:" + left + "px !important; top:" + top + "px !important;}\
  805. ", "ytpc_style_cinemode");
  806. }
  807.  
  808. var key_shift_offset_value = 50;
  809. var key_zoom_value = 0.1;
  810.  
  811. doc.addEventListener('keydown', keyDownShift, false);
  812.  
  813. function keyDownShift(event) {
  814. if (!pl_mouseover || !get_pref("ytCine") || !get_pref("ytZoom")) return;
  815.  
  816. var name = event.key;
  817. var code = event.code;
  818. //message(name);
  819. //message(code);
  820. switch (code) {
  821. case "KeyG" : shiftPlayer(key_shift_offset_value,0); break; //shift left
  822. case "KeyH" : shiftPlayer(-key_shift_offset_value,0); break;//shift right
  823. case "KeyY" : shiftPlayer(0,key_shift_offset_value); break; //shift up
  824. case "KeyB" : shiftPlayer(0,-key_shift_offset_value); break; //shift down
  825. case "KeyZ" : ZoomIn(); break;
  826. case "KeyX" : ZoomOut(); break;
  827. }
  828.  
  829. if (name == "Escape") shiftReset(true);
  830.  
  831. if (event.ctrlKey) {
  832. //message(code);
  833. switch (code) {
  834. case "ShiftLeft" :
  835. case "ShiftRight" : shiftReset(); break;
  836. }
  837. }
  838.  
  839. //event.stopImmediatePropagation();
  840. }
  841.  
  842. function shiftPlayer(x,y) {
  843. key_left_offset += x;
  844. key_up_offset += y;
  845. message("Pan X=" + key_left_offset + " Y=" + key_up_offset, key_message_timeout);
  846. cinema(1);
  847. }
  848.  
  849. function ZoomIn() {
  850. key_zoom += key_zoom_value;
  851. message("Zoom In " + (Math.round(key_zoom * 10) / 10).toFixed(1), key_message_timeout);
  852. cinema(1);
  853. }
  854.  
  855. function ZoomOut() {
  856. key_zoom -= key_zoom_value;
  857. if (key_zoom < 1) key_zoom = 1;
  858. message("Zoom Out " + (Math.round(key_zoom * 10) / 10).toFixed(1), key_message_timeout);
  859. cinema(1);
  860. }
  861.  
  862. function shiftReset(NOmsg) {
  863. reset_key_offset_zoom();
  864. if (!NOmsg) message("Reset Pan & Zoom X=" + key_left_offset + " Y=" + key_up_offset + " Zoom=" + key_zoom, key_message_timeout);
  865. cinema(1);
  866. }
  867.  
  868.  
  869. var mouseLastX = 0;
  870. var mouseLastY = 0;
  871. var mouseIsDown = false;
  872. var mouseMoved = false;
  873. var mouseRegistered = false;
  874.  
  875. function registerMouse(node) {
  876. if (!get_pref("ytCine") || !get_pref("ytZoom")) return;
  877.  
  878. if (mouseRegistered) return;
  879. mouseRegistered = true;
  880.  
  881. node.addEventListener("mousemove", function (e) {
  882. if(mouseIsDown) {
  883. if (get_pref("ytCine") && get_pref("ytZoom")) {
  884. var diffX = e.pageX - mouseLastX;
  885. var diffY = e.pageY - mouseLastY;
  886. shiftPlayer(diffX, diffY);
  887. if (diffX != 0 || diffY !=0 )
  888. mouseMoved = true;
  889. }
  890. mouseLastX = e.pageX;
  891. mouseLastY = e.pageY;
  892. }
  893. }, false);
  894.  
  895. node.addEventListener("mousedown", function (e) {
  896. mouseIsDown = true;
  897. mouseMoved = false;
  898. mouseLastX = e.pageX;
  899. mouseLastY = e.pageY;
  900. }, false);
  901.  
  902. node.addEventListener("mouseup", function (e) {
  903. mouseIsDown = false;
  904. }, false);
  905.  
  906. node.addEventListener("mouseout", function (e) {
  907. mouseIsDown = false;
  908. mouseMoved = false;
  909. }, false);
  910.  
  911. node.addEventListener("click", function (e) {
  912. if (mouseMoved) {
  913. //e.preventDefault();
  914. //e.stopPropagation();
  915. e.stopImmediatePropagation();
  916. mouseMoved = false;
  917. }
  918. }, false);
  919. }
  920.  
  921.  
  922. //==================================================================
  923. // Float
  924.  
  925. var floatheight = 0;
  926. var floatbot = 0;
  927.  
  928. function reset_float() {
  929. var page = docsearch("//ytd-page-manager/ytd-watch-flexy").snapshotItem(0);
  930. if (!page) return;
  931.  
  932. if (page.getAttribute("float") != null) setTimeout(function () { win.dispatchEvent(new Event('resize')) }, 100);
  933. page.removeAttribute("float");
  934. page.parentNode.parentNode.removeAttribute("float");
  935. insertStyle("", "ytpc_style_float");
  936. floatheight = 0;
  937. floatbot = 0;
  938. }
  939.  
  940.  
  941. function float(start_count) {
  942. if (start_count == 0) reset_float();
  943.  
  944. if (!get_pref("ytFloat")) return;
  945. var small = get_pref("ytFSmall");
  946. var flpos = get_pref("ytFloatPos");
  947. var cine = get_pref("ytCine");
  948.  
  949. var page = docsearch("//ytd-page-manager/ytd-watch-flexy").snapshotItem(0);
  950. if (!page) return;
  951.  
  952. var intheater = page.getAttribute("theater") != null;
  953. var fullscreen = page.getAttribute("fullscreen") != null;
  954. if (start_count == 20 && !fullscreen) return;
  955.  
  956. var vid = intheater || fullscreen ? docsearch("//*[@id='full-bleed-container']").snapshotItem(0)
  957. : docsearch("//*[@id='primary-inner']/*[@id='player']").snapshotItem(0);
  958. if (!vid) return;
  959.  
  960. var val = vid.getBoundingClientRect();
  961. var vwidth = val.right - val.left;
  962. var vheight = val.bottom - val.top;
  963. var vleft = val.left;
  964. var vright = val.right;
  965.  
  966. //player dimensions for fill window float
  967. var W = doc.body.clientWidth || doc.documentElement.clientWidth;
  968. var H = doc.body.clientHeight || doc.documentElement.clientHeight;
  969. var height = 240;
  970. var width = 427;
  971. var left = Math.round((W - width) / 2);
  972.  
  973. var infloat = page.getAttribute("float") != null;
  974. var inpltop = (docsearch("//*[@ytpc_top]").snapshotLength > 0);
  975.  
  976. //store initial values
  977. if (!infloat) {
  978. floatheight = vheight;
  979. floatbot = inpltop ? vheight - search_height : vheight;
  980. }
  981.  
  982. var thres = -1;
  983.  
  984. if (intheater || fullscreen) {
  985. if (floatheight > 0)
  986. thres = inpltop || fullscreen ? floatheight - 296 : floatheight - 240;
  987. }
  988. else
  989. if (small) {
  990. if (floatheight > 0)
  991. thres = floatheight - 220;
  992. }
  993. else {
  994. if (vheight > 0)
  995. thres = 1;
  996. }
  997.  
  998. var scrollY = win.pageYOffset;
  999. if (fullscreen) { //in fullscreen the regular scroll value is not correct
  1000. var ref = doc.getElementById("content");
  1001. if (ref) scrollY = - ref.getBoundingClientRect().top;
  1002. }
  1003.  
  1004. if (scrollY >= thres && thres > 0) {
  1005. page.setAttribute("float", "");
  1006. page.parentNode.parentNode.setAttribute("float", "");
  1007.  
  1008. if (intheater || fullscreen)
  1009. insertStyle("\
  1010. ytd-watch-flexy[float] #full-bleed-container {position: fixed !important; top:56px !important; z-index:1000 !important;\
  1011. height: " + height + "px !important; max-height:" + height + "px !important; min-height:" + height + "px !important;}\
  1012. ytd-watch-flexy[float] .html5-main-video {width: " + width + "px !important; height: " + height + "px !important; left: " + left + "px !important; top:0px !important; margin-left:0px !important;}\
  1013. ytd-watch-flexy[float] #columns {margin-top: " + floatbot + "px !important;}\
  1014. ", "ytpc_style_float");
  1015. else {
  1016. var rtl = (doc.body.getAttribute('dir') == 'rtl');
  1017. var lroff = "";
  1018. if (small) {
  1019. var hoff = (flpos == 1 || flpos == 4) ? W - width : 0;
  1020. var voff = (flpos == 1 || flpos == 2) ? H - height : 56;
  1021. lroff = rtl ? "right:" + hoff + "px !important;" : "left:" + hoff + "px !important;";
  1022.  
  1023. insertStyle("\
  1024. ytd-watch-flexy[float] #player-container {position: fixed !important; top: " + voff + "px !important; " + lroff + " width: " + width + "px !important; height: " + height + "px !important; z-index:1000 !important;}\
  1025. ytd-watch-flexy[float] .html5-main-video {width: " + width + "px !important; height: " + height + "px !important;}\
  1026. ", "ytpc_style_float");
  1027. }
  1028. else {
  1029. lroff = rtl ? "right: " + (W - vright) + "px !important;" : "left: " + vleft + "px !important;";
  1030. insertStyle("\
  1031. ytd-watch-flexy[float] #player-container {position: fixed !important; top:80px !important; " + lroff + " width: " + vwidth + "px !important; height: " + vheight + "px !important; z-index:1000 !important;}\
  1032. ", "ytpc_style_float");
  1033. }
  1034. }
  1035. }
  1036. else
  1037. reset_float();
  1038. }
  1039.  
  1040.  
  1041. //=================================================================
  1042. //ads & annotations
  1043.  
  1044. var adds_on = false;
  1045. var fs_on = false;
  1046.  
  1047. function skip_ads(start_count) {
  1048.  
  1049. //adjust cinema after adds by forcing resize event
  1050. if (get_pref("ytCine")) {
  1051. if (start_count == 0) adds_on = false;
  1052. var adds = doc.getElementsByClassName("video-ads ytp-ad-module");
  1053. if (adds.length > 0) {
  1054. if (adds[0].style.display != "none") {
  1055. adds_on = true;
  1056. }
  1057. }
  1058. else {
  1059. if (adds_on) { //adds turned off
  1060. //win.dispatchEvent(new Event('resize'));
  1061. setTimeout(function () { win.dispatchEvent(new Event('resize')) }, 100);
  1062. }
  1063. adds_on = false;
  1064. }
  1065. }
  1066.  
  1067. //fullscreen also forces resize event
  1068. var fs = (docsearch("//ytd-page-manager/ytd-watch-flexy[@fullscreen]").snapshotLength > 0);
  1069. if (fs != fs_on) {
  1070. //win.dispatchEvent(new Event('resize'));
  1071. setTimeout(function () { win.dispatchEvent(new Event('resize')) }, 100);
  1072. //alert("fullscreen");
  1073. float(0);
  1074. }
  1075. fs_on = fs;
  1076.  
  1077. //main skip ads
  1078. if (!get_pref("ytAds")) return;
  1079.  
  1080. var button = doc.getElementsByClassName("ytp-ad-skip-button ytp-button");
  1081. if (button.length == 0)
  1082. button = doc.getElementsByClassName("ytp-ad-skip-button-modern ytp-button");
  1083. if (button.length > 0)
  1084. if (button[0].parentNode)
  1085. if (button[0].parentNode.style.display != "none") {
  1086. //message("will click");
  1087. simulClick(button[0]);
  1088. }
  1089. }
  1090.  
  1091. function extra_ads() {
  1092. insertStyle(get_pref("ytAdsExtra") ? style_extra_ads : "", "ytpc_style_extra_ads");
  1093. }
  1094.  
  1095. function annotation() {
  1096. insertStyle(get_pref("ytAnnot") ? style_annotations : "", "ytpc_style_annotations");
  1097. }
  1098.  
  1099.  
  1100. //==================================================================
  1101. //Load More
  1102.  
  1103. function auto_load(start_count) {
  1104. if (win.location.href.indexOf("watch?") == -1) return;
  1105.  
  1106. var button = docsearch("//div[(@id='meta') or (@id='above-the-fold')]//tp-yt-paper-button[(@id='more') or (@id='expand')]").snapshotItem(0);
  1107. if (!button) return;
  1108.  
  1109. if (start_count < 2) {
  1110. button.removeAttribute("buttonclicked");
  1111. return;
  1112. }
  1113.  
  1114. if (!get_pref("ytLoad")) return;
  1115. if (button.getAttribute("buttonclicked") == "true") return;
  1116.  
  1117. button.setAttribute("buttonclicked","true");
  1118. simulClick(button);
  1119. }
  1120.  
  1121.  
  1122.  
  1123. //==================================================================
  1124. // Main
  1125.  
  1126. var old_addr = win.location.href;
  1127. var nochanges_count = -1;
  1128. var start_count = -1;
  1129. //for yt_start
  1130. var pause_count = 0;
  1131. var def_count = 0;
  1132. var has_focus = false;
  1133.  
  1134. ytplayer_script();
  1135. insertStyle(style_basic, "ytpc_style_basic");
  1136.  
  1137. win.addEventListener("focus", function () { reset_nochanges(); cinema(1); float(1); }, false);
  1138. win.addEventListener("blur", function () { reset_nochanges(); cinema(1); float(1); }, false);
  1139. win.addEventListener("resize", function () { reset_nochanges(); cinema(1); float(1); }, false);
  1140. win.addEventListener("scroll", function () { reset_nochanges(); cinema(1); float(1); }, false);
  1141. win.addEventListener("click", function (e) { reset_nochanges(); cinema(1); float(1); close_ytplayer_options(e); }, false);
  1142.  
  1143. function reset_nochanges() {
  1144. nochanges_count = -1;
  1145. }
  1146.  
  1147. function yt_start() {
  1148. if (start_count == 0) {
  1149. pause_count = 0;
  1150. def_count = 0;
  1151. }
  1152.  
  1153. if (get_pref('ytPause') && pause_count <= 2) {
  1154. ytplayer_pause();
  1155. if (success_pause()) pause_count++;
  1156. }
  1157.  
  1158. if (def_count <= 2) {
  1159. var ytdef = get_pref('ytDef');
  1160. if (ytdef != "off") {
  1161. ytplayer_quality(ytdef);
  1162. if (success_quality()) def_count++;
  1163. }
  1164. }
  1165. }
  1166.  
  1167. //main routine
  1168. function check_changes() {
  1169. if (old_addr == win.location.href) {
  1170. if (nochanges_count < 20) nochanges_count++;
  1171. if (start_count < 20) start_count++;
  1172. }
  1173. else {
  1174. old_addr = win.location.href;
  1175. nochanges_count = 0;
  1176. start_count = 0;
  1177. }
  1178.  
  1179. if (!has_focus) {
  1180. has_focus = doc.hasFocus();
  1181. if (has_focus) {
  1182. nochanges_count = 0;
  1183. start_count = 0;
  1184. }
  1185. }
  1186.  
  1187. //no video page
  1188. if (win.location.href.indexOf("watch?") == -1) {
  1189. if (start_count < 20) {
  1190. set_noloop();
  1191. set_nopause_end();
  1192. pl_reset_mouseevents();
  1193. reset_keyDownMark();
  1194. cinema(20); //for showmast
  1195. delete_menu_commands();
  1196. }
  1197. return;
  1198. }
  1199.  
  1200. //video page
  1201. skip_ads(start_count);
  1202. float(start_count);
  1203.  
  1204. if (start_count < 20) {
  1205. if (start_count == 0) {
  1206. close_ytplayer_options();
  1207. adjust_loop();
  1208. adjust_pause_end();
  1209. reset_keyDownMark();
  1210. }
  1211. build_yt_control();
  1212. yt_start();
  1213. annotation();
  1214. extra_ads();
  1215. auto_load(start_count);
  1216. pl_enable_mouseevents();
  1217. if (start_count > 0) build_menu_commands();
  1218. }
  1219.  
  1220. if (nochanges_count < 20) {
  1221. cinema(start_count);
  1222. }
  1223. }
  1224.  
  1225. setInterval(check_changes, 1000);
  1226. check_changes();

QingJ © 2025

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