Video time tracker (localStorage)

Remembers the last watched time of videos on any website (including YouTube) and auto-deletes after 3 months

  1. // ==UserScript==
  2. // @name Video time tracker (localStorage)
  3. // @namespace https://gf.qytechs.cn/
  4. // @version 1.0
  5. // @description Remembers the last watched time of videos on any website (including YouTube) and auto-deletes after 3 months
  6. // @author Bui Quoc Dung
  7. // @match *://*/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. 'use strict';
  13.  
  14. const EXPIRATION_DAYS = 90; // Days
  15. const SAVE_INTERVAL = 1*1000; // Seconds*1000
  16. const SHORT_VIDEO_TIME = 10; // Days
  17. const YOUTUBE_URL_REGEX = /youtube\.com\/watch\?v=([^&]+)/;
  18.  
  19. // Function to save time
  20. function saveTime(video, key) {
  21. if (!video || video.duration < SHORT_VIDEO_TIME) return;
  22. let data = { time: video.currentTime, timestamp: Date.now() };
  23. localStorage.setItem(key, JSON.stringify(data));
  24. }
  25.  
  26. // Function to load and restore time
  27. function loadTime(video, key) {
  28. let savedData = localStorage.getItem(key);
  29. if (savedData) {
  30. let data = JSON.parse(savedData);
  31. let elapsedDays = (Date.now() - data.timestamp) / (1000 * 60 * 60 * 24);
  32. if (elapsedDays < EXPIRATION_DAYS && !isNaN(data.time)) {
  33. video.currentTime = parseFloat(data.time);
  34. } else {
  35. localStorage.removeItem(key); // Delete expired data
  36. }
  37. }
  38. }
  39.  
  40. // Standard video handling
  41. function handleVideo(video) {
  42. if (!video || video.dataset.processed) return;
  43. video.dataset.processed = true;
  44.  
  45. let key = `videoTime_${location.href}`;
  46. loadTime(video, key);
  47. let saveInterval = setInterval(() => saveTime(video, key), SAVE_INTERVAL);
  48.  
  49. video.addEventListener('pause', () => clearInterval(saveInterval));
  50. }
  51.  
  52. // YouTube-specific handling using the IFrame API
  53. function handleYouTube() {
  54. let match = location.href.match(YOUTUBE_URL_REGEX);
  55. if (!match) return;
  56.  
  57. let videoId = match[1];
  58. let key = `youtubeTime_${videoId}`;
  59.  
  60. // Wait for the YouTube player to load
  61. let checkPlayer = setInterval(() => {
  62. let player = document.querySelector('.html5-main-video');
  63. if (player) {
  64. clearInterval(checkPlayer);
  65. loadTime(player, key);
  66. let saveInterval = setInterval(() => saveTime(player, key), SAVE_INTERVAL);
  67. player.addEventListener('pause', () => clearInterval(saveInterval));
  68. }
  69. }, 1000);
  70. }
  71.  
  72. // Observer to track new video elements
  73. function init() {
  74. if (location.hostname.includes('youtube.com')) {
  75. handleYouTube();
  76. } else {
  77. let observer = new MutationObserver(() => {
  78. document.querySelectorAll('video').forEach(video => handleVideo(video));
  79. });
  80. observer.observe(document.body, { childList: true, subtree: true });
  81. }
  82. }
  83.  
  84. window.addEventListener('load', init);
  85. })();

QingJ © 2025

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