From 1495699d223e7ec1a5302e48ecc4efe8ee0dffad Mon Sep 17 00:00:00 2001 From: Hiers <47784553+Hiers@users.noreply.github.com> Date: Fri, 13 Nov 2020 22:29:41 +0000 Subject: [PATCH] Implement frame by frame advance using keyboard shortcuts (#758) * Added frame by frame advance functionality. * Changed keybindings for frame by frame advancing. * Fix comments. * On Invidious videos using dash at high qualities the default is now skipping 1 frame at 60fps instead of 30fps. Avoided error on trying to read non-local dash manifest. * On dash reading error, defaults to 60fps within determineMaxFramerate. maxFrameRate initialised in data object. * Cleanup of framebyframe logic. --- .../ft-video-player/ft-video-player.js | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/renderer/components/ft-video-player/ft-video-player.js b/src/renderer/components/ft-video-player/ft-video-player.js index 86726268..76c12c36 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -4,6 +4,7 @@ import FtCard from '../ft-card/ft-card.vue' import $ from 'jquery' import videojs from 'video.js' import qualitySelector from '@silvermine/videojs-quality-selector' +import fs from 'fs' import 'videojs-vtt-thumbnails-freetube' import 'videojs-contrib-quality-levels' import 'videojs-http-source-selector' @@ -60,6 +61,7 @@ export default Vue.extend({ useDash: false, useHls: false, selectedDefaultQuality: '', + maxFramerate: 0, activeSourceList: [], mouseTimeout: null, dataSetup: { @@ -142,6 +144,7 @@ export default Vue.extend({ } this.determineFormatType() + this.determineMaxFramerate() }, beforeDestroy: function () { if (this.player !== null && !this.player.isInPictureInPicture()) { @@ -251,6 +254,20 @@ export default Vue.extend({ } }, + determineMaxFramerate: function() { + fs.readFile(this.dashSrc[0].url, (err, data) => { + if (err) { + this.maxFramerate = 60 + return + } + if (data.includes('frameRate="60"')) { + this.maxFramerate = 60 + } else { + this.maxFramerate = 30 + } + }) + }, + determineDefaultQualityLegacy: function () { if (this.useDash) { return @@ -426,6 +443,22 @@ export default Vue.extend({ } }, + framebyframe: function (step) { + this.player.pause() + const qualityHeight = this.useDash ? this.player.qualityLevels()[this.player.qualityLevels().selectedIndex].height : 0 + let fps + // Non-Dash formats are 30fps only + if (qualityHeight >= 480 && this.maxFramerate === 60) { + fps = 60 + } else { + fps = 30 + } + // The 3 lines below were taken from the videojs-framebyframe node module by Helena Rasche + const frameTime = 1 / fps + const dist = frameTime * step + this.player.currentTime(this.player.currentTime() + dist) + }, + changeVolume: function (volume) { const currentVolume = this.player.volume() const newVolume = currentVolume + volume @@ -637,6 +670,16 @@ export default Vue.extend({ event.preventDefault() this.changeDurationByPercentage(0) break + case 188: + // , Key + // Return to previous frame + this.framebyframe(-1) + break + case 190: + // . Key + // Advance to next frame + this.framebyframe(1) + break } } }