Redirect YouTube Shorts

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

  1. // ==UserScript==
  2. // @name Redirect YouTube Shorts
  3. // @version 2.0.4
  4. // @description Seamlessly redirect YouTube Shorts to the regular video player WITHOUT a 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. * @param {boolean} returnParent
  28. * @returns {any}
  29. */
  30. function dig(obj, target, returnParent = false) {
  31. if (obj && typeof obj === "object") {
  32. if (target in obj && !dig(obj[target], target)) {
  33. return returnParent ? obj : obj[target];
  34. }
  35. for (const k in obj) {
  36. const result = dig(obj[k], target, returnParent);
  37. if (result !== undefined) return result;
  38. }
  39. }
  40. }
  41.  
  42. /**
  43. * @param {HTMLAnchorElement} element
  44. * @returns {object | undefined}
  45. */
  46. function findShortData(element) {
  47. while (element && element.tagName !== "YTD-APP") {
  48. const data = dig(element.data, "reelWatchEndpoint", true);
  49. if (data) return data;
  50. element = element.parentElement;
  51. }
  52. }
  53.  
  54. /**
  55. * @param {string} id
  56. */
  57. function redirectShorts(id) {
  58. const elements = document.querySelectorAll(`a[href*="shorts/${id}"]`);
  59.  
  60. for (const element of elements) {
  61. const command = findShortData(element);
  62.  
  63. if (command && command.reelWatchEndpoint.videoId === id) {
  64. const metadata = dig(command, "url", true);
  65. metadata.url = `/watch?v=${id}`;
  66. metadata.webPageType = "WEB_PAGE_TYPE_WATCH";
  67. command.watchEndpoint = { videoId: id };
  68. command.reelWatchEndpoint = {};
  69. }
  70. }
  71. }
  72.  
  73. const idRegex = /(?:shorts\/|watch\?v=)([^#\&\?]*)/;
  74.  
  75. function handleShorts(/** @type {MouseEvent} */ ev) {
  76. /** @type {HTMLElement} */
  77. const target = ev.target;
  78.  
  79. if (target.closest) {
  80. const query = "a[href*='/shorts/'], a[href*='/watch?v=']";
  81. const url = target.closest(query);
  82. if (url) redirectShorts(url.href.match(idRegex)[1]);
  83. }
  84. }
  85.  
  86. window.addEventListener("click", handleShorts, true);
  87. })();

QingJ © 2025

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