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 4009c081..cc57f376 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -73,6 +73,7 @@ export default Vue.extend({ useDash: false, useHls: false, selectedDefaultQuality: '', + selectedQuality: '', maxFramerate: 0, activeSourceList: [], mouseTimeout: null, @@ -198,7 +199,8 @@ export default Vue.extend({ vhs: { limitRenditionByPlayerDimensions: false, smoothQualityChange: false, - allowSeeksWithinUnsafeLiveWindow: true + allowSeeksWithinUnsafeLiveWindow: true, + handlePartialData: true } } }) @@ -214,14 +216,12 @@ export default Vue.extend({ } if (this.useDash) { - this.dataSetup.plugins.httpSourceSelector = { - default: 'auto' - } + // this.dataSetup.plugins.httpSourceSelector = { + // default: 'auto' + // } - this.player.httpSourceSelector() - setTimeout(() => { - this.determineDefaultQualityDash() - }, 400) + // this.player.httpSourceSelector() + this.createDashQualitySelector(this.player.qualityLevels()) } if (this.autoplayVideos) { @@ -417,7 +417,7 @@ export default Vue.extend({ determineDefaultQualityDash: function () { if (this.defaultQuality === 'auto') { - return + this.setDashQualityLevel('auto') } this.player.qualityLevels().levels_.sort((a, b) => { @@ -433,27 +433,62 @@ export default Vue.extend({ } if (this.defaultQuality === quality) { - ql.enabled = true + this.setDashQualityLevel(height) } else if (upperLevel !== null) { const upperHeight = upperLevel.height const upperWidth = upperLevel.width const upperQuality = upperWidth < upperHeight ? upperWidth : upperHeight if (this.defaultQuality >= quality && this.defaultQuality < upperQuality) { - ql.enabled = true - } else { - ql.enabled = false + this.setDashQualityLevel(height) } } else if (index === 0 && quality > this.defaultQuality) { - ql.enabled = true + this.setDashQualityLevel(height) } else if (index === (arr.length - 1) && quality < this.defaultQuality) { - ql.enabled = true - } else { - ql.enabled = false + this.setDashQualityLevel(height) } }) }, + setDashQualityLevel: function (qualityLevel) { + if (this.selectedQuality === qualityLevel) { + return + } + this.player.qualityLevels().levels_.sort((a, b) => { + return a.height - b.height + }).forEach((ql, index, arr) => { + if (qualityLevel === 'auto' || ql.height === qualityLevel) { + ql.enabled = true + ql.enabled_(true) + } else { + ql.enabled = false + ql.enabled_(false) + } + }) + + const selectedQuality = qualityLevel === 'auto' ? 'auto' : qualityLevel + 'p' + + const qualityElement = document.getElementById('vjs-current-quality') + qualityElement.innerText = selectedQuality + this.selectedQuality = qualityLevel + + const qualityItems = $('.quality-item').get() + + $('.quality-item').removeClass('quality-selected') + + qualityItems.forEach((item) => { + const qualityText = $(item).find('.vjs-menu-item-text').get(0) + if (qualityText.innerText === selectedQuality) { + $(item).addClass('quality-selected') + } + }) + + // const currentTime = this.player.currentTime() + + // this.player.currentTime(0) + // this.player.currentTime(currentTime) + }, + enableDashFormat: function () { if (this.dashSrc === null) { console.log('No dash format available.') @@ -629,6 +664,58 @@ export default Vue.extend({ videojs.registerComponent('fullWindowButton', fullWindowButton) }, + createDashQualitySelector: function (levels) { + const v = this + if (levels.levels_.length === 0) { + setTimeout(() => { + this.createDashQualitySelector(this.player.qualityLevels()) + }, 200) + return + } + const VjsButton = videojs.getComponent('Button') + const dashQualitySelector = videojs.extend(VjsButton, { + constructor: function(player, options) { + VjsButton.call(this, player, options) + }, + handleClick: function(event) { + const selectedQuality = event.target.innerText + const quality = selectedQuality === 'auto' ? 'auto' : parseInt(selectedQuality.replace('p', '')) + v.setDashQualityLevel(quality) + // console.log(this.player().qualityLevels()) + }, + createControlTextEl: function (button) { + const beginningHtml = `
+ 1080p +
+
+
' + + let qualityHtml = `
  • + Auto + +
  • ` + + levels.levels_.sort((a, b) => { + return b.height - a.height + }).forEach((quality) => { + qualityHtml = qualityHtml + `
  • + ${quality.height}p + +
  • ` + }) + return $(button).html( + $(beginningHtml + qualityHtml + endingHtml).attr( + 'title', + 'Select Quality' + )) + } + }) + videojs.registerComponent('dashQualitySelector', dashQualitySelector) + this.player.controlBar.addChild('dashQualitySelector', {}, this.player.controlBar.children_.length - 1) + this.determineDefaultQualityDash() + }, + toggleFullWindow: function() { if (!this.player.isFullscreen_) { if (this.player.isFullWindow) { diff --git a/src/renderer/videoJS.css b/src/renderer/videoJS.css index 767006db..3203ae64 100644 --- a/src/renderer/videoJS.css +++ b/src/renderer/videoJS.css @@ -643,6 +643,46 @@ body.vjs-full-window { display: none; } +.vjs-quality-level-value { + width: 100%; + height: 100%; +} + +.vjs-quality-level-value span { + line-height: 40px; +} + +.vjs-quality-level-value:hover + .vjs-quality-level-menu { + display: block; +} + +.vjs-quality-level-menu { + display: none; + position: absolute; + bottom: 30px; + left: -8px; + z-index: 5; + background-color: #151b17; + width: 50px; +} + +.vjs-quality-level-menu:hover { + display: block; +} + +.vjs-quality-level-menu .vjs-menu-item { + padding: 5px; +} + +.quality-selected { + background-color: var(--primary-color); + color: var(--text-with-main-color); +} + +.quality-selected:hover { + background-color: var(--primary-color-hover) !important; +} + .vjs-menu .vjs-menu-content { display: block; padding: 0;