YoutubePlayBack

Have you ever closed a YouTube video by accident, or have you gone to another one and when you come back the video starts from 0? With this extension it won't happen anymore

目前為 2024-02-18 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @license MIT
  3. // @name YoutubePlayBack
  4. // @namespace http://tampermonkey.net/
  5. // @version 1.3
  6. // @description Have you ever closed a YouTube video by accident, or have you gone to another one and when you come back the video starts from 0? With this extension it won't happen anymore
  7. // @author Costin Alexandru Sandu
  8. // @match https://www.youtube.com/watch*
  9. // @icon https://tse4.mm.bing.net/th/id/OIG3.UOFNuEtdysdoeX0tMsVU?pid=ImgGn
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'strict'
  15. var configData = {
  16. savedProgressAlreadySet: false,
  17. savingInterval: 1500,
  18. currentVideoId: null
  19. }
  20.  
  21. function executeFnInPageContext(fn) {
  22. const fnStringified = fn.toString()
  23. return window.eval('(' + fnStringified + ')' + '()')
  24. }
  25.  
  26. function getVideoCurrentTime() {
  27. const currentTime = executeFnInPageContext(() => {
  28. const player = document.querySelector('#movie_player')
  29. return player.getCurrentTime()
  30. })
  31. return currentTime
  32. }
  33.  
  34. function getVideoId() {
  35. if (configData.currentVideoId) {
  36. return configData.currentVideoId
  37. }
  38. const id = executeFnInPageContext(() => {
  39. const player = document.querySelector('#movie_player')
  40. return player.getVideoData().video_id
  41. })
  42. return id
  43. }
  44.  
  45. function playerExists() {
  46. const exists = executeFnInPageContext(() => {
  47. const player = document.querySelector('#movie_player')
  48. return Boolean(player)
  49. })
  50. return exists
  51. }
  52.  
  53. function setVideoProgress(progress) {
  54. window.eval('var progress =' + progress)
  55. executeFnInPageContext(() => {
  56. const player = document.querySelector('#movie_player')
  57. player.seekTo(window.progress)
  58. })
  59. window.eval('delete progress')
  60. }
  61.  
  62. function saveVideoProgress() {
  63. const videoProgress = getVideoCurrentTime()
  64. const videoId = getVideoId()
  65.  
  66. configData.currentVideoId = videoId
  67. window.localStorage.setItem(videoId, videoProgress)
  68. }
  69.  
  70. function getSavedVideoProgress() {
  71. const videoId = getVideoId()
  72. const savedVideoProgress = window.localStorage.getItem(videoId)
  73.  
  74. return savedVideoProgress
  75. }
  76.  
  77. function setSavedProgress() {
  78. const savedProgress = getSavedVideoProgress();
  79. setVideoProgress(savedProgress)
  80. configData.savedProgressAlreadySet = true
  81. }
  82.  
  83. // code ref: https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists
  84. function waitForElm(selector) {
  85. return new Promise(resolve => {
  86. if (document.querySelector(selector)) {
  87. return resolve(document.querySelector(selector));
  88. }
  89.  
  90. const observer = new MutationObserver(mutations => {
  91. if (document.querySelector(selector)) {
  92. observer.disconnect();
  93. resolve(document.querySelector(selector));
  94. }
  95. });
  96.  
  97. // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336
  98. observer.observe(document.body, {
  99. childList: true,
  100. subtree: true
  101. });
  102. });
  103. }
  104.  
  105. async function onPlayerElementExist(callback) {
  106. await waitForElm('#movie_player')
  107. callback()
  108. }
  109.  
  110. function isReadyToSetSavedProgress() {
  111. return !configData.savedProgressAlreadySet && playerExists() && getSavedVideoProgress()
  112. }
  113.  
  114. function initialize() {
  115. onPlayerElementExist(() => {
  116. if (isReadyToSetSavedProgress()) {
  117. setSavedProgress()
  118. }
  119. })
  120.  
  121. setInterval(saveVideoProgress, configData.savingInterval)
  122. }
  123.  
  124. initialize()
  125. })();