Redirect YouTube Shorts

Seamlessly redirect YouTube Shorts to the regular video player WITHOUT page reload

  1. // ==UserScript==
  2. // @name Redirect YouTube Shorts
  3. // @version 2.0.6
  4. // @description Seamlessly redirect YouTube Shorts to the regular video player WITHOUT page reload
  5. // @run-at document-start
  6. // @inject-into page
  7. // @match https://www.youtube.com/*
  8. // @exclude https://*.youtube.com/live_chat*
  9. // @exclude https://*.youtube.com/embed*
  10. // @exclude https://*.youtube.com/tv*
  11. // @exclude https:/tv.youtube.com/*
  12. // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
  13. // @author Fznhq
  14. // @namespace https://github.com/fznhq
  15. // @homepageURL https://github.com/fznhq/userscript-collection
  16. // @license GNU GPLv3
  17. // ==/UserScript==
  18.  
  19. (function () {
  20. if (location.pathname.startsWith("/shorts")) {
  21. return location.replace(location.href.replace("/shorts/", "/watch?v="));
  22. }
  23.  
  24. /**
  25. * @param {object} obj
  26. * @param {string} target
  27. * @returns {any}
  28. */
  29. function dig(obj, target) {
  30. if (obj && typeof obj === "object") {
  31. if (target in obj && !dig(obj[target], target)) return obj;
  32. for (const k in obj) {
  33. const result = dig(obj[k], target);
  34. if (result !== undefined) return result;
  35. }
  36. }
  37. }
  38.  
  39. /**
  40. * @param {HTMLAnchorElement} element
  41. * @returns {object | undefined}
  42. */
  43. function findShortData(element) {
  44. while (element && element.tagName !== "YTD-APP") {
  45. const data = dig(element.data, "reelWatchEndpoint");
  46. if (data) return data;
  47. element = element.parentElement;
  48. }
  49. }
  50.  
  51. /**
  52. * @param {string} id
  53. */
  54. function redirectShorts(id) {
  55. const elements = document.querySelectorAll(`a[href*="shorts/${id}"]`);
  56.  
  57. for (const element of elements) {
  58. const command = findShortData(element);
  59. const url = (element.href = `/watch?v=${id}`);
  60.  
  61. if (command && command.reelWatchEndpoint.videoId === id) {
  62. const metadata = dig(command, "url");
  63. metadata.url = url;
  64. metadata.webPageType = "WEB_PAGE_TYPE_WATCH";
  65. command.watchEndpoint = { videoId: id };
  66. command.reelWatchEndpoint = {};
  67. }
  68. }
  69. }
  70.  
  71. const idRegex = /(?:shorts\/|watch\?v=)([^#\&\?]*)/;
  72.  
  73. function handleShorts(/** @type {MouseEvent} */ ev) {
  74. /** @type {HTMLElement} */
  75. const target = ev.target;
  76.  
  77. if (target.closest) {
  78. const query = "a[href*='/shorts/'], a[href*='/watch?v=']";
  79. const url = target.closest(query);
  80. if (url) redirectShorts(url.href.match(idRegex)[1]);
  81. }
  82. }
  83.  
  84. window.addEventListener("click", handleShorts, true);
  85. window.addEventListener("mouseover", handleShorts, true);
  86. })();

QingJ © 2025

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