diff options
-rw-r--r-- | README.md | 9 | ||||
-rw-r--r-- | index.html | 56 | ||||
-rw-r--r-- | main.js | 65 |
3 files changed, 104 insertions, 26 deletions
@@ -1,2 +1,9 @@ # yt-frame-timer -A JavaScript-based program to determine the time between start and end points of a YouTube video down to the frame. Based on [https://github.com/Slush0Puppy/retime](https://github.com/Slush0Puppy/retime) by Slush Puppy (big thanks to them for their work). Formatting done by [StackEdit](https://stackedit.io/).
\ No newline at end of file +A JavaScript-based program to determine the time between start and end points of a YouTube video down to the frame. The tool was originally created to help moderators retime speedruns on [speedrun.com](https://www.speedrun.com). Based on [Slush Puppy's Retime Tool (SPRT)](https://github.com/Slush0Puppy/retime) by Slush Puppy (big thanks to them for their work). + +## Contributors +* [SlushPuppy](https://www.speedrun.com/user/SlushPuppy) - Created [Slush Puppy's Retime Tool (SPRT)](https://github.com/Slush0Puppy/retime) in Python +* [dadinfinitum](https://www.speedrun.com/user/dadinfinitum) - Rewrote SPRT into web-hosted JavaScript / yt-frame-retimer lead +* [Oxknifer](https://www.speedrun.com/user/Oxknifer) - Original idea / beta tester on SPRT / yt-frame-retimer contributor + +Interested in contributing? Message @dadinfinitum or @Oxknifer @@ -1,27 +1,53 @@ <!DOCTYPE html> <html> + <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <version>1.1.0</version> <title>YouTube Frame Timer</title> <link rel="stylesheet" href="https://stackedit.io/style.css" /> - <script src="main.js"></script> + <script src="main.js"></script> </head> <body class="stackedit"> - <div class="stackedit__html"><h1 id="youtube-interval-timer">YouTube Interval Timer</h1> -<h3 id="about">About</h3> -<p>Takes start and stop points of a YouTube video, down to the frame, and gives the time between them in the format <code>1h 23m 45s 678ms</code>. Source code is <a href="https://github.com/slashinfty/yt-frame-timer">available</a>.</p> -<h3 id="video-framerate">Video Framerate</h3> -<p>Right click the YouTube video and select “Stats for nerds.” The third line is “Current / Optimal Res” - find the two numbers after the @ and enter them for framerate.</p> -<p><label for="framerate">Framerate: </label><input type="text" id="framerate" size="3" /></p> -<h3 id="video-endpoints">Video Endpoints</h3> -<p>Find the starting point (you can use the <code>,</code> and <code>.</code> keys to find the exact frame). Right click the video and select “Copy debug info” and paste it for starting frame. Repeat for ending frame.</p> -<p><label for="startobj">Starting frame: </label><input type="text" id="startobj" style='width:100%'/></p> -<p><label for="endobj">Ending frame: </label><input type="text" id="endobj" style='width:100%'/></p> -<h3 id="video-time">Video Time</h3> -<p><button onclick="compute()">Compute time</button> <input type="text" id="time" readonly size="20" /></p> -</div> + <div class="stackedit__html"> + <h1 id="youtube-interval-timer">YouTube Interval Timer</h1> + <h3 id="about">About</h3> + <p>Takes start and stop points of a YouTube video, down to the frame, and gives the time between them in the format + <code>1h 23m 45s 678ms</code>. Source code is <a + href="https://github.com/slashinfty/yt-frame-timer">available</a>. + </p> + <h3 id="video-framerate">Video Framerate</h3> + <p>Right click the YouTube video and select “Stats for nerds.” The third line is “Current / Optimal Res” - find the + two numbers after the @ and enter them for framerate.</p> + <p> + <label for="framerate">Framerate: </label> + <input type="text" id="framerate" size="3" value="60" onchange='validateFPS(event)' /> + </p> + <h3 id="video-endpoints">Video Endpoints</h3> + <p> + Find the starting point (you can use the <code>,</code> and <code>.</code> keys to find the exact frame). Right + click the video and select “Copy debug info” and paste it for starting frame. Repeat for ending frame. + </p> + <p> + <label for="startobj">Starting frame: </label> + <input type="text" id="startobj" style='width:100%' onchange='parseForTime(event)' /> + </p> + <p> + <label for="endobj">Ending frame: </label> + <input type="text" id="endobj" style='width:100%' onchange='parseForTime(event)' /> + </p> + <h3 id="video-time">Video Time</h3> + <p> + <button id="computeButton" onclick="compute()">Compute time</button> <input type="text" id="time" readonly + size="20" /> + </p> + <p id="modMessage"></p> + <b> + <p id="postModMessage"></p> + </b> + </div> </body> -</html> +</html>
\ No newline at end of file @@ -1,16 +1,21 @@ function compute() { - let startObj = JSON.parse(document.getElementById('startobj').value); - let endObj = JSON.parse(document.getElementById('endobj').value); - let framerate = document.getElementById('framerate').value; - if (startObj == undefined || endObj == undefined || framerate == undefined) return; + + // Initiate basic time variables let hours = 0; let minutes = 0; let seconds = 0; let milliseconds = 0; - let frameRate = parseInt(framerate); - let frameFromObj = (time, fps) => Math.floor(time * fps) / fps; //round to the nearest frame - let startFrame = frameFromObj(startObj.lct, frameRate); - let endFrame = frameFromObj(endObj.lct, frameRate); + + // Get framerate, start frame, and end frame from corresponding elements + // Double check they all have a value + let frameRate = parseInt(document.getElementById('framerate').value); + let startFrame = document.getElementById('startobj').value; + let endFrame = document.getElementById('endobj').value; + if (typeof (startFrame) === 'undefined' || endFrame === 'undefined' || framerate === 'undefined') { + return + }; + + // Calculate framerate let frames = (endFrame - startFrame) * frameRate; if (frames >= frameRate) { seconds = Math.floor(frames / frameRate); @@ -39,6 +44,46 @@ function compute() { milliseconds = '0' + milliseconds; } } - let print = hours.toString() + 'h ' + minutes.toString() + 'm ' + seconds.toString() + 's ' + milliseconds.toString() + 'ms'; - document.getElementById('time').value = print; + + // Show the time and mod message in the DOM + let finalTime = hours.toString() + 'h ' + minutes.toString() + 'm ' + seconds.toString() + 's ' + milliseconds.toString() + 'ms'; + let modMessage = `Mod Message: Time starts at ${parseFloat(startFrame).toFixed(3)} and ends at ${parseFloat(endFrame).toFixed(3)} at ${frameRate} fps to get a final time of ${finalTime}.`; + let credits = `Retimed using [yt-frame-timer](https://mattbraddock.com/yt-frame-timer)`; + document.getElementById('time').value = finalTime; + document.getElementById('postModMessage').innerHTML = "The mod message has been copied to clipboard! Please paste the it into the comment of the run you are verifying."; + document.getElementById('modMessage').innerHTML = modMessage + ' ' + credits; + + // Copy mod message to clipboard + navigator.clipboard.writeText(modMessage) + .then(() => { alert(`Copied to clipboard!`) }) + .catch((error) => { alert(`Copy failed! ${error}`) }) +} + +const validateFPS = (event) => { + // If framerate is invalid, show an error message and disable start and end frame fields + if (event.target.value === '' || parseInt(event.target.value) <= 0 || isNaN(parseInt(event.target.value))) { + document.getElementById('framerate').setCustomValidity('Please enter a valid framerate.'); + document.getElementById('framerate').reportValidity(); + document.getElementById('startobj').disabled = true; + document.getElementById('endobj').disabled = true; + document.getElementById('computeButton').disabled = true; + } else { + document.getElementById('startobj').disabled = false; + document.getElementById('endobj').disabled = false; + document.getElementById('computeButton').disabled = false; + } +} + +const parseForTime = (event) => { + // Get current frame from input field (either start time or end time) + let frameFromInputText = (JSON.parse(event.target.value)).lct; + if (typeof frameFromInputText !== 'undefined') { + // Get the framerate + let frameRate = parseInt(document.getElementById('framerate').value); + // Calculate the frame + let frameFromObj = (time, fps) => Math.floor(time * fps) / fps; //round to the nearest frame + let finalFrame = frameFromObj(frameFromInputText, frameRate); + // Update the DOM + document.getElementById(event.target.id).value = `${finalFrame}`; + } }
\ No newline at end of file |