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.
This commit is contained in:
		
							parent
							
								
									758796c515
								
							
						
					
					
						commit
						1495699d22
					
				|  | @ -4,6 +4,7 @@ import FtCard from '../ft-card/ft-card.vue' | ||||||
| import $ from 'jquery' | import $ from 'jquery' | ||||||
| import videojs from 'video.js' | import videojs from 'video.js' | ||||||
| import qualitySelector from '@silvermine/videojs-quality-selector' | import qualitySelector from '@silvermine/videojs-quality-selector' | ||||||
|  | import fs from 'fs' | ||||||
| import 'videojs-vtt-thumbnails-freetube' | import 'videojs-vtt-thumbnails-freetube' | ||||||
| import 'videojs-contrib-quality-levels' | import 'videojs-contrib-quality-levels' | ||||||
| import 'videojs-http-source-selector' | import 'videojs-http-source-selector' | ||||||
|  | @ -60,6 +61,7 @@ export default Vue.extend({ | ||||||
|       useDash: false, |       useDash: false, | ||||||
|       useHls: false, |       useHls: false, | ||||||
|       selectedDefaultQuality: '', |       selectedDefaultQuality: '', | ||||||
|  |       maxFramerate: 0, | ||||||
|       activeSourceList: [], |       activeSourceList: [], | ||||||
|       mouseTimeout: null, |       mouseTimeout: null, | ||||||
|       dataSetup: { |       dataSetup: { | ||||||
|  | @ -142,6 +144,7 @@ export default Vue.extend({ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.determineFormatType() |     this.determineFormatType() | ||||||
|  |     this.determineMaxFramerate() | ||||||
|   }, |   }, | ||||||
|   beforeDestroy: function () { |   beforeDestroy: function () { | ||||||
|     if (this.player !== null && !this.player.isInPictureInPicture()) { |     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 () { |     determineDefaultQualityLegacy: function () { | ||||||
|       if (this.useDash) { |       if (this.useDash) { | ||||||
|         return |         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) { |     changeVolume: function (volume) { | ||||||
|       const currentVolume = this.player.volume() |       const currentVolume = this.player.volume() | ||||||
|       const newVolume = currentVolume + volume |       const newVolume = currentVolume + volume | ||||||
|  | @ -637,6 +670,16 @@ export default Vue.extend({ | ||||||
|             event.preventDefault() |             event.preventDefault() | ||||||
|             this.changeDurationByPercentage(0) |             this.changeDurationByPercentage(0) | ||||||
|             break |             break | ||||||
|  |           case 188: | ||||||
|  |             // , Key
 | ||||||
|  |             // Return to previous frame
 | ||||||
|  |             this.framebyframe(-1) | ||||||
|  |             break | ||||||
|  |           case 190: | ||||||
|  |             // . Key
 | ||||||
|  |             // Advance to next frame
 | ||||||
|  |             this.framebyframe(1) | ||||||
|  |             break | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue