Embedded YouTube Video Quality Preference

Set initial video quality for embedded YouTube videos based on a set of preferred video qualities, as well as minimum and maximum video qualities (configured in the script).

  1. // ==UserScript==
  2. // @name Embedded YouTube Video Quality Preference
  3. // @namespace https://gf.zukizuki.org/en/users/85671-jcunews
  4. // @version 1.0.1
  5. // @license AGPLv3
  6. // @author jcunews
  7. // @description Set initial video quality for embedded YouTube videos based on a set of preferred video qualities, as well as minimum and maximum video qualities (configured in the script).
  8. // @match *://www.youtube.com/embed/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (() => {
  13.  
  14. //=== CONFIGURATION BEGIN ===
  15.  
  16. //One or more video quality IDs. From most to least prioritized video quality.
  17. //e.g. if ["hd720", "medium"], try using "hd720" quality first. If not available, use "medium" quality. If it's also not available, use YouTube's default.
  18. var qualities = [""]; //Set to [] if no preference
  19.  
  20. //Minimum video quality. Set it to "" to use lowest quality available.
  21. //If ID is not empty and is not available, use the available one which is a higher quality.
  22. var minQuality = "";
  23.  
  24. //Maximum video quality. For slow network or low computer specifications. Set it to "" to use highest quality available.
  25. //If ID is not empty and is not available, use the available one which is a lower quality.
  26. var maxQuality = "";
  27.  
  28. //minQuality and maxQuality have higher priority than the qualities variable.
  29. //e.g. if qualities is ["hd2160", "hd720"], minQuality is "hd1080", and maxQuality is "hd1440", YouTube's default will be used.
  30. //maxQuality rule is applied after minQuality rule has been aplied.
  31. //i.e. the rule priorities are: qualities, minQuality, then maxQuality.
  32.  
  33. //To always use the maximum video quality available, set minQuality and maxQuality to "highres". The qualities variable will be ignored.
  34.  
  35. //To always use the minimum video quality available, set minQuality and maxQuality to "tiny". The qualities variable will be ignored.
  36.  
  37. /* Available video quality IDs:
  38. "tiny" (144p)
  39. "small" (240p)
  40. "medium" (360p)
  41. "large" (480p)
  42. "hd720" (720p)
  43. "hd1080" (1080p)
  44. "hd1440" (1440p)
  45. "hd2160" (2160p)
  46. "hd2880" (2880p)
  47. "highres" (4320p; YouTube's highest resolution [2019 April])
  48. */
  49.  
  50. //=== CONFIGURATION END ===
  51.  
  52. var sb = document.querySelector(".ytp-settings-button");
  53. if (!sb) return;
  54. var sq = {
  55. "144p": "tiny", "240p": "small", "360p": "medium", "480p": "large", "720p": "hd720", "1080p": "hd1080",
  56. "1440p": "hd1440", "2160p": "hd2160", "2880p": "hd2880", "4320p": "highres"
  57. }, p = player.querySelector(".html5-video-player"), v = p.querySelector(".html5-main-video"), play = v.play, resm = {};
  58. ["tiny", "small", "medium", "large", "hd720", "hd1080", "hd1440", "hd2160", "highres"].forEach((r, i) => resm[r] = i);
  59. v.play = function() {
  60. var sty = document.head.appendChild(document.createElement("STYLE"));
  61. sty.innerHTML = '.ytp-settings-menu{display:none}';
  62. v.play = play;
  63. sb.click();
  64. document.querySelectorAll(".ytp-settings-menu .ytp-menuitem-label").forEach(l => {
  65. if (l.textContent !== "Quality") return;
  66. l.click();
  67. setTimeout(() => {
  68. var
  69. es = Array.from(document.querySelectorAll(".ytp-quality-menu .ytp-menuitem-label span")),
  70. qs = [], qsm = {}, esm = {}, cq = p.getPlaybackQuality(), q = cq;
  71. es.pop();
  72. es.reverse();
  73. var ss = es.map((e, s, n) => {
  74. s = e.firstChild.data;
  75. qs.push(n = sq[s]);
  76. qsm[n] = resm[n];
  77. esm[n] = e.parentNode;
  78. return s;
  79. });
  80. if (!minQuality || (qsm[minQuality] === undefined)) minQuality = qs[0];
  81. if (!maxQuality || (qsm[maxQuality] === undefined)) maxQuality = qs[qs.length - 1];
  82. qualities = qualities.filter(
  83. v => (qsm[v] !== undefined) && (resm[v] >= resm[minQuality]) && (resm[v] <= resm[maxQuality])
  84. );
  85. if (qualities.length) {
  86. q = qualities[0];
  87. } else {
  88. if (resm[cq] <= resm[minQuality]) q = minQuality;
  89. if (resm[cq] >= resm[maxQuality]) q = maxQuality;
  90. }
  91. if (q !== cq) {
  92. esm[q].click();
  93. } else v.play();
  94. sty.click();
  95. sty.remove();
  96. }, 0);
  97. });
  98. };
  99. })();