您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds quality of life features for YouTube frame timing
// ==UserScript== // @name YouTube Speedrun Timer // @namespace http://tampermonkey.net/ // @version 0.2.4 // @description Adds quality of life features for YouTube frame timing // @author Michael "Msbmteam" Y. // @match https://*.youtube.com/* // @match http://*.youtube.com/* // @grant none // ==/UserScript== // This script is based on the "YouTube Detailed Timecode" script by Charlie Laabs (https://greasyfork.org/en/scripts/40740-youtube-detailed-timecode) (function() { 'use strict'; // console.log('Running YouTube Speedrun Timer'); var ytPlayer; var ytPlayerUnwrapped; var ytpCurrentTime; var timeHour = document.createElement('span'); var timeMinute = document.createElement('span'); var timeSecond = document.createElement('span'); var frameCount = document.createElement('span'); var lastDisplayedTime = 0; var playerInitialized = false; var fps; var frame; function getElements() { // get the YouTube player element from the page ytPlayer = document.getElementById("movie_player") || document.getElementsByClassName("html5-video-player")[0]; ytPlayerUnwrapped = ytPlayer.wrappedJSObject; if (ytPlayer) { frameCount.innerHTML = ""; ytPlayer.addEventListener("onStateChange", playerChanged, true ); document.addEventListener("keyup", keyUp, true ); document.addEventListener("keydown", keyDown, true); setFps(); } } function playerStarted() { var timeDisp = ytPlayerUnwrapped.getElementsByClassName("ytp-time-display")[0]; timeHour.className = 'ytsrt-hr'; timeHour.style.paddingLeft = "0px"; timeMinute.className = 'ytsrt-min'; timeMinute.style.paddingLeft = "0px"; timeSecond.className = 'ytsrt-sec'; timeSecond.style.paddingLeft = "0px"; frameCount.className = 'ytsrt-frame'; frameCount.style.paddingLeft = '20px'; timeDisp.appendChild(frameCount); playerInitialized = true; } function playerChanged(state) { //console.log("stateChanged: ", state); if (state != -1 && !playerInitialized ) { playerStarted(); } if (state == 2) { displayTime(); } } function keyUp(e) { displayTime(); } function keyDown(e) { // "D" -- advance 1 second forward if (e.keyCode == 68) { ytPlayerUnwrapped.seekTo(ytPlayerUnwrapped.getCurrentTime() + 1); } // "A" -- advance 1 second backward if (e.keyCode == 65) { ytPlayerUnwrapped.seekTo(ytPlayerUnwrapped.getCurrentTime() - 1); } // "S" -- Toggle between regular speed, slow-mo, or super slow-mo (1.0, 0.5, or 0.1) if (e.keyCode == 83) { var playback_rate = ytPlayerUnwrapped.getPlaybackRate(); if (playback_rate == 1.0) { ytPlayerUnwrapped.setPlaybackRate(0.5); } else if (ytPlayerUnwrapped.getPlaybackRate() == 0.5) { playback_rate.setPlaybackRate(0.1); } else { playback_rate.setPlaybackRate(1.0); } } } function setFps() { // Find fps from Stats for Nerds (can get manually by right clicking on YT player) var resolution = ytPlayerUnwrapped.getStatsForNerds().resolution; fps = resolution.substr(resolution.search('@')+1, 2); fps = Number.parseInt(fps); frame = 1/fps; } function frameAdvance(keycode, dir) { var num = Number(String.fromCharCode(keycode)); if (num === 0) num = 10; if (dir == -1) num *= -1; ytPlayerUnwrapped.seekTo(ytPlayerUnwrapped.getCurrentTime() + num * frame, true); } function displayTime() { ytpCurrentTime = document.getElementsByClassName("ytp-time-current")[0]; var currentTime = ytPlayerUnwrapped.getCurrentTime(); ytpCurrentTime.innerHTML = ""; var hour = Math.floor(currentTime / 3600); var minute = Math.floor(currentTime / 60) - (hour * 60); var second = (currentTime - (hour * 3600) - (minute * 60)); if (hour > 0) { timeHour.innerHTML = hour.toString() + ":"; ytpCurrentTime.appendChild(timeHour); } timeMinute.innerHTML = minute.toString() + ":"; ytpCurrentTime.appendChild(timeMinute); if (second < 10) { timeSecond.innerHTML = "0" + (second.toFixed(3)).toString(); } else { timeSecond.innerHTML = second.toFixed(3); } ytpCurrentTime.appendChild(timeSecond); setFps(); var frameNum = Math.floor(currentTime * fps); frameCount.innerHTML = 'Current frame: ' + frameNum + ' (' + fps + ' FPS)'; } getElements(); //for embedded videos document.addEventListener("yt-navigate-finish", getElements, true ); //for YouTube })();