<video controls style="width: 100%; margin-bottom: 24px;" src="./vid.mp4"></video> <div class="full-seekbar"> <div class="video-timestamp"> <span id="text-live">--:--</span> <span id="text-full">--:--</span> </div> <div class="seekbar"> <span class="seekbar-current-progress"></span> <span class="seekbar-tooltip"></span> <input id="seek" name="seekbar" type="range"/> </div> </div> <style> body { font-family: arial,sans-serif; } .full-seekbar { display: flex; flex-direction: row-reverse; align-items: center; gap: 6px; } .video-timestamp { background: gray; border-radius: 3rem; color: white; display: flex; flex-direction: row; align-items: center; width: min-content; padding: 4px 12px 4px 4px; font-size: 14px; gap: 6px; } #text-live { width: max-content; background: #414141; border-radius: 3rem; padding: 4px 12px; } .seekbar { width: 100%; position: relative; background: gray; border-radius: 3rem; height: 6px; display: flex; align-items: center; } .seekbar input { position: absolute; left: 0; width: 100%; accent-color: red; opacity: 0; } .seekbar-tooltip { position: absolute; background: #d3d3d3; color: black; border-radius: 3rem; transform: translate(-24px, 0px); padding: 4px 8px; font-size: 12px; border: 6px white solid; transition: 0.3s font-size; } .seekbar-current-progress { background: red; border-radius: 3rem; height: 6px; display: flex; align-items: center; } </style> <script> // Set variables const VideoElement = document.querySelector('video') const SeekbarTooltip = document.querySelector('.seekbar-tooltip') const SeekbarElementInput = document.querySelector('#seek') const SeekbarProgressbarElement = document.querySelector('.seekbar .seekbar-current-progress') //////////////////////////////// // Video Seekbar and Tooltip // //////////////////////////////// // Set max attribute to the range input VideoElement.addEventListener('loadedmetadata', () => { const VideoMaxLength = Math.round(VideoElement.duration).toString() SeekbarElementInput.setAttribute("max", VideoMaxLength) }) // Update progress bar and live timestamp function UpdateSeekbar() { SeekbarElementInput.value = Math.floor(VideoElement.currentTime) SeekbarProgressbarElement.style.width = VideoElement.currentTime / VideoElement.duration * 100 + '%' SeekbarTooltip.style.left = VideoElement.currentTime / VideoElement.duration * 100 + '%' } // Format timestamp for Seekbar Tooltip function TooltipFormat(Second) { const result = new Date(Second * 1e3).toISOString().slice(11, 19) return { hours: result.slice(0, 2), minutes: result.slice(3, 5), seconds: result.slice(6, 8), } } // Tooltip function updateSeekTooltip(event) { const skipTo = Math.round( (event.offsetX / event.target.clientWidth) * parseInt(event.target.getAttribute("max"), 10), ) SeekbarElementInput.setAttribute("data-seek", skipTo.toString()) const t = TooltipFormat(skipTo) if (t.hours === "00") {SeekbarTooltip.textContent = `${t.minutes}:${t.seconds}`} else {SeekbarTooltip.textContent = `${t.hours}:${t.minutes}:${t.seconds}`} const rect = SeekbarProgressbarElement.getBoundingClientRect() SeekbarTooltip.style.left = `${event.pageX - rect.left}px` SeekbarTooltip.style.fontSize = '12' SeekbarElementInput.addEventListener('mouseleave', () => { SeekbarTooltip.style.fontSize = '0' SeekbarTooltip.style.left = VideoElement.currentTime / VideoElement.duration * 100 + '%' }) } // If end-users clicks anywhere on the seekbar, skip video current time to the point SeekbarElementInput.addEventListener("mousemove", updateSeekTooltip) function skipAhead(event) { const skipTo = event.target.dataset.seek ? event.target.dataset.seek : event.target.value VideoElement.currentTime = skipTo SeekbarProgressbarElement.value = skipTo SeekbarElementInput.value = skipTo } SeekbarElementInput.addEventListener("input", skipAhead) /////////////////////////////////// // Video Duration and Timestamp // /////////////////////////////////// // Convert the video duration to a readable format Number.prototype.VideoReadableFormat = function () { let seconds = Math.floor(this), hours = Math.floor(seconds / 3600) seconds -= hours*3600 let minutes = Math.floor(seconds / 60) seconds -= minutes*60 if (hours < 10) {hours = "0"+hours} if (minutes < 10) {minutes = "0"+minutes} if (seconds < 10) {seconds = "0"+seconds} if (hours === '00') { // Hide 'hour' if the video not over an hour long return minutes+':'+seconds } else { return hours+':'+minutes+':'+seconds } } // When the video is playing, automatically update the 'Current Time' text VideoElement.addEventListener('timeupdate', Live) VideoElement.addEventListener('timeupdate', UpdateSeekbar) function Live() {document.getElementById('text-live').innerText = `${VideoElement.currentTime.VideoReadableFormat()}`} // Post the video's full duration VideoElement.onloadedmetadata = function() {document.getElementById('text-full').innerText = `${VideoElement.duration.VideoReadableFormat()}`} </script>