您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
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
当前为
// ==UserScript== // @license MIT // @name YoutubePlayBack // @namespace http://tampermonkey.net/ // @version 1.3 // @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 // @author Costin Alexandru Sandu // @match https://www.youtube.com/watch* // @icon https://tse4.mm.bing.net/th/id/OIG3.UOFNuEtdysdoeX0tMsVU?pid=ImgGn // @grant none // ==/UserScript== (function () { 'strict' var configData = { savedProgressAlreadySet: false, savingInterval: 1500, currentVideoId: null } function executeFnInPageContext(fn) { const fnStringified = fn.toString() return window.eval('(' + fnStringified + ')' + '()') } function getVideoCurrentTime() { const currentTime = executeFnInPageContext(() => { const player = document.querySelector('#movie_player') return player.getCurrentTime() }) return currentTime } function getVideoId() { if (configData.currentVideoId) { return configData.currentVideoId } const id = executeFnInPageContext(() => { const player = document.querySelector('#movie_player') return player.getVideoData().video_id }) return id } function playerExists() { const exists = executeFnInPageContext(() => { const player = document.querySelector('#movie_player') return Boolean(player) }) return exists } function setVideoProgress(progress) { window.eval('var progress =' + progress) executeFnInPageContext(() => { const player = document.querySelector('#movie_player') player.seekTo(window.progress) }) window.eval('delete progress') } function saveVideoProgress() { const videoProgress = getVideoCurrentTime() const videoId = getVideoId() configData.currentVideoId = videoId window.localStorage.setItem(videoId, videoProgress) } function getSavedVideoProgress() { const videoId = getVideoId() const savedVideoProgress = window.localStorage.getItem(videoId) return savedVideoProgress } function setSavedProgress() { const savedProgress = getSavedVideoProgress(); setVideoProgress(savedProgress) configData.savedProgressAlreadySet = true } // code ref: https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists function waitForElm(selector) { return new Promise(resolve => { if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } const observer = new MutationObserver(mutations => { if (document.querySelector(selector)) { observer.disconnect(); resolve(document.querySelector(selector)); } }); // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336 observer.observe(document.body, { childList: true, subtree: true }); }); } async function onPlayerElementExist(callback) { await waitForElm('#movie_player') callback() } function isReadyToSetSavedProgress() { return !configData.savedProgressAlreadySet && playerExists() && getSavedVideoProgress() } function initialize() { onPlayerElementExist(() => { if (isReadyToSetSavedProgress()) { setSavedProgress() } }) setInterval(saveVideoProgress, configData.savingInterval) } initialize() })();