From d482a5e893c6ac4c37c7178e26b61784f475c849 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Thu, 9 Mar 2023 21:45:40 +0100 Subject: [PATCH 01/10] Fix DASH default quality and quality selection --- .../ft-video-player/ft-video-player.js | 185 ++++++++++-------- src/renderer/helpers/api/invidious.js | 30 +++ src/renderer/helpers/api/local.js | 3 +- src/renderer/views/Watch/Watch.js | 23 +-- 4 files changed, 142 insertions(+), 99 deletions(-) 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 3bc85f0762d0..8e8b8c123920 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -28,6 +28,10 @@ videojs.Vhs.xhr.beforeRequest = (options) => { } } +// videojs-http-streaming spits out a warning every time you access videojs.Vhs.BANDWIDTH_VARIANCE +// so we'll get the value once here, to stop it spamming the console +const VHS_BANDWIDTH_VARIANCE = videojs.Vhs.BANDWIDTH_VARIANCE + export default defineComponent({ name: 'FtVideoPlayer', props: { @@ -320,6 +324,10 @@ export default defineComponent({ this.dataSetup.playbackRates = this.playbackRates + if (this.format === 'dash') { + this.determineDefaultQualityDash() + } + this.createFullWindowButton() this.createLoopButton() this.createToggleTheatreModeButton() @@ -369,6 +377,15 @@ export default defineComponent({ controlBarItems.splice(index, 1) } + // regardless of what DASH qualities you enable or disable in the qualitLevels plugin + // the first segments videojs-http-streamming request are chosen based on the available bandwidth, which is set to 0.5MB/s by default + // overriding that to be the same as the quality we requested, makes videojs-http-streamming pick the correct quality + const playerBandwidthOption = {} + + if (this.useDash && this.defaultQuality !== 'auto') { + playerBandwidthOption.bandwidth = this.selectedBitrate * VHS_BANDWIDTH_VARIANCE + 1 + } + this.player = videojs(this.$refs.video, { html5: { preloadTextTracks: false, @@ -376,7 +393,8 @@ export default defineComponent({ limitRenditionByPlayerDimensions: false, smoothQualityChange: false, allowSeeksWithinUnsafeLiveWindow: true, - handlePartialData: true + handlePartialData: true, + ...playerBandwidthOption } } }) @@ -397,6 +415,15 @@ export default defineComponent({ } }) + // disable any quality the isn't the default one, as soon as it gets added + // we don't need to disable any qualities for auto + if (this.useDash && this.defaultQuality !== 'auto') { + const qualityLevels = this.player.qualityLevels() + qualityLevels.on('addqualitylevel', ({ qualityLevel }) => { + qualityLevel.enabled = qualityLevel.bitrate === this.selectedBitrate + }) + } + this.player.volume(this.volume) this.player.muted(this.muted) this.player.playbackRate(this.defaultPlayback) @@ -895,92 +922,48 @@ export default defineComponent({ }, determineDefaultQualityDash: function () { - if (this.defaultQuality === 'auto') { - this.setDashQualityLevel('auto') - } - - let formatsToTest + // TODO add settings and filtering for 60fps and HDR - if (typeof this.activeAdaptiveFormats !== 'undefined' && this.activeAdaptiveFormats.length > 0) { - formatsToTest = this.activeAdaptiveFormats.filter((format) => { - return format.height === this.defaultQuality + if (this.defaultQuality === 'auto') { + this.selectedResolution = 'auto' + this.selectedFPS = 'auto' + this.selectedBitrate = 'auto' + this.selectedMimeType = 'auto' + } else { + const videoFormats = this.adaptiveFormats.filter(format => { + return (format.mimeType || format.type).startsWith('video') && typeof format.height !== 'undefined' }) - if (formatsToTest.length === 0) { - formatsToTest = this.activeAdaptiveFormats.filter((format) => { - return format.height < this.defaultQuality - }) - } + // Select the quality that is identical to the users chosen default quality if it's available + // otherwise select the next lowest quality - formatsToTest = formatsToTest.sort((a, b) => { - if (a.height === b.height) { - return b.bitrate - a.bitrate - } else { - return b.height - a.height - } - }) - } else { - formatsToTest = this.player.qualityLevels().levels_.filter((format) => { - return format.height === this.defaultQuality - }) + let formatsToTest = videoFormats.filter(format => format.height === this.defaultQuality) if (formatsToTest.length === 0) { - formatsToTest = this.player.qualityLevels().levels_.filter((format) => { - return format.height < this.defaultQuality - }) + formatsToTest = videoFormats.filter(format => format.height < this.defaultQuality) } - formatsToTest = formatsToTest.sort((a, b) => { + formatsToTest.sort((a, b) => { if (a.height === b.height) { return b.bitrate - a.bitrate } else { return b.height - a.height } }) - } - - // TODO: Test formats to determine if HDR / 60 FPS and skip them based on - // User settings - this.setDashQualityLevel(formatsToTest[0].bitrate) - // Old logic. Revert if needed - /* this.player.qualityLevels().levels_.sort((a, b) => { - if (a.height === b.height) { - return a.bitrate - b.bitrate - } else { - return a.height - b.height - } - }).forEach((ql, index, arr) => { - const height = ql.height - const width = ql.width - const quality = width < height ? width : height - let upperLevel = null - - if (index < arr.length - 1) { - upperLevel = arr[index + 1] - } - - if (this.defaultQuality === quality && upperLevel === null) { - this.setDashQualityLevel(height, true) - } 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) { - this.setDashQualityLevel(height, true) - } else if (this.defaultQuality >= quality && this.defaultQuality < upperQuality) { - this.setDashQualityLevel(height) - } - } else if (index === 0 && quality > this.defaultQuality) { - this.setDashQualityLevel(height) - } else if (index === (arr.length - 1) && quality < this.defaultQuality) { - this.setDashQualityLevel(height) - } - }) */ + const selectedFormat = formatsToTest[0] + this.selectedBitrate = selectedFormat.bitrate + this.selectedResolution = `${selectedFormat.width}x${selectedFormat.height}` + this.selectedFPS = selectedFormat.fps + this.selectedMimeType = selectedFormat.mimeType || selectedFormat.type + } }, setDashQualityLevel: function (bitrate) { + if (bitrate === this.selectedBitrate) { + return + } + let adaptiveFormat = null if (bitrate !== 'auto') { @@ -991,24 +974,39 @@ export default defineComponent({ let qualityLabel = adaptiveFormat ? adaptiveFormat.qualityLabel : '' - this.player.qualityLevels().levels_.sort((a, b) => { - if (a.height === b.height) { - return a.bitrate - b.bitrate - } else { - return a.height - b.height - } - }).forEach((ql, index, arr) => { - if (bitrate === 'auto' || bitrate === ql.bitrate) { + const qualityLevels = Array.from(this.player.qualityLevels()) + if (bitrate === 'auto') { + qualityLevels.forEach(ql => { ql.enabled = true - ql.enabled_(true) - if (bitrate !== 'auto' && qualityLabel === '') { - qualityLabel = ql.height + 'p' + }) + } else { + const previousBitrate = this.selectedBitrate + + // if it was previously set to a specific quality we can disable just that and enable just the new one + // if it was previously set to auto, it means all qualitylevels were enabled, so we need to disable them + + if (previousBitrate !== 'auto') { + const qualityLevel = qualityLevels.find(ql => bitrate === ql.bitrate) + qualityLevel.enabled = true + + if (qualityLabel === '') { + qualityLabel = qualityLevel.height + 'p' } + + qualityLevels.find(ql => previousBitrate === ql.bitrate).enabled = false } else { - ql.enabled = false - ql.enabled_(false) + qualityLevels.forEach(ql => { + if (bitrate === ql.bitrate) { + ql.enabled = true + if (qualityLabel === '') { + qualityLabel = ql.height + 'p' + } + } else { + ql.enabled = false + } + }) } - }) + } const selectedQuality = bitrate === 'auto' ? 'auto' : qualityLabel @@ -1514,6 +1512,8 @@ export default defineComponent({ const adaptiveFormats = this.adaptiveFormats const activeAdaptiveFormats = this.activeAdaptiveFormats const setDashQualityLevel = this.setDashQualityLevel + const defaultQuality = this.defaultQuality + const defaultBitrate = this.selectedBitrate const VjsButton = videojs.getComponent('Button') class dashQualitySelector extends VjsButton { @@ -1531,12 +1531,16 @@ export default defineComponent({ ' - let qualityHtml = `
  • + const defaultIsAuto = defaultQuality === 'auto' + + let qualityHtml = `
  • Auto
  • ` - levels.levels_.sort((a, b) => { + let currentQualityLabel + + Array.from(levels).sort((a, b) => { if (b.height === a.height) { return b.bitrate - a.bitrate } else { @@ -1567,7 +1571,13 @@ export default defineComponent({ bitrate = quality.bitrate } - qualityHtml += `
  • + const isSelected = !defaultIsAuto && bitrate === defaultBitrate + + if (isSelected) { + currentQualityLabel = qualityLabel + } + + qualityHtml += `
  • ${qualityLabel}
  • ` @@ -1590,13 +1600,14 @@ export default defineComponent({ button.title = 'Select Quality' button.innerHTML = beginningHtml + qualityHtml + endingHtml + button.querySelector('#vjs-current-quality').innerText = defaultIsAuto ? 'auto' : currentQualityLabel + return button.children[0] } } videojs.registerComponent('dashQualitySelector', dashQualitySelector) this.player.controlBar.addChild('dashQualitySelector', {}, this.player.controlBar.children_.length - 1) - this.determineDefaultQualityDash() }, sortCaptions: function (captionList) { diff --git a/src/renderer/helpers/api/invidious.js b/src/renderer/helpers/api/invidious.js index 59c7d0c6d6b1..6f25000568f6 100644 --- a/src/renderer/helpers/api/invidious.js +++ b/src/renderer/helpers/api/invidious.js @@ -226,3 +226,33 @@ function parseInvidiousCommunityAttachments(data) { console.error('New Invidious Community Post Type: ' + data.type) } + +/** + * video.js only supports MP4 DASH not WebM DASH + * so we filter out the WebM DASH formats + * @param {any[]} formats + * @param {boolean} allowAv1 Use the AV1 formats if they are available + */ +export function filterInvidiousFormats(formats, allowAv1 = false) { + const audioFormats = [] + const h264Formats = [] + const av1Formats = [] + + formats.forEach(format => { + const mimeType = format.type + + if (mimeType.startsWith('audio/mp4')) { + audioFormats.push(format) + } else if (allowAv1 && mimeType.startsWith('video/mp4; codecs="av01')) { + av1Formats.push(format) + } else if (mimeType.startsWith('video/mp4; codecs="avc')) { + h264Formats.push(format) + } + }) + + if (allowAv1 && av1Formats.length > 0) { + return [...audioFormats, ...av1Formats] + } else { + return [...audioFormats, ...h264Formats] + } +} diff --git a/src/renderer/helpers/api/local.js b/src/renderer/helpers/api/local.js index 26d7d787427d..0929d8e63fa2 100644 --- a/src/renderer/helpers/api/local.js +++ b/src/renderer/helpers/api/local.js @@ -562,6 +562,7 @@ export function mapLocalFormat(format) { bitrate: format.bitrate, mimeType: format.mime_type, height: format.height, + width: format.width, url: format.url } } @@ -606,7 +607,7 @@ export function parseLocalComment(comment, commentThread = undefined) { * @param {Format[]} formats * @param {boolean} allowAv1 Use the AV1 formats if they are available */ -export function filterFormats(formats, allowAv1 = false) { +export function filterLocalFormats(formats, allowAv1 = false) { const audioFormats = [] const h264Formats = [] const av1Formats = [] diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js index 3c242d5e7302..8e9168769a87 100644 --- a/src/renderer/views/Watch/Watch.js +++ b/src/renderer/views/Watch/Watch.js @@ -22,14 +22,14 @@ import { showToast } from '../../helpers/utils' import { - filterFormats, + filterLocalFormats, getLocalVideoInfo, mapLocalFormat, parseLocalSubscriberCount, parseLocalTextRuns, parseLocalWatchNextVideo } from '../../helpers/api/local' -import { invidiousGetVideoInformation, youtubeImageUrlToInvidious } from '../../helpers/api/invidious' +import { filterInvidiousFormats, invidiousGetVideoInformation, youtubeImageUrlToInvidious } from '../../helpers/api/invidious' export default defineComponent({ name: 'Watch', @@ -486,7 +486,7 @@ export default defineComponent({ if (result.streaming_data.formats.length > 0) { this.videoSourceList = result.streaming_data.formats.map(mapLocalFormat).reverse() } else { - this.videoSourceList = filterFormats(result.streaming_data.adaptive_formats, this.allowDashAv1Formats).map(mapLocalFormat).reverse() + this.videoSourceList = filterLocalFormats(result.streaming_data.adaptive_formats, this.allowDashAv1Formats).map(mapLocalFormat).reverse() } this.adaptiveFormats = this.videoSourceList @@ -584,7 +584,7 @@ export default defineComponent({ }).reverse() // we need to alter the result object so the toDash function uses the filtered formats too - result.streaming_data.adaptive_formats = filterFormats(result.streaming_data.adaptive_formats, this.allowDashAv1Formats) + result.streaming_data.adaptive_formats = filterLocalFormats(result.streaming_data.adaptive_formats, this.allowDashAv1Formats) this.adaptiveFormats = result.streaming_data.adaptive_formats.map(mapLocalFormat) if (this.proxyVideos) { @@ -668,13 +668,14 @@ export default defineComponent({ this.videoPublished = result.published * 1000 this.videoDescriptionHtml = result.descriptionHtml this.recommendedVideos = result.recommendedVideos - this.adaptiveFormats = result.adaptiveFormats.map((format) => { - format.bitrate = parseInt(format.bitrate) - if (typeof format.resolution !== 'undefined') { - format.height = parseInt(format.resolution.replace('p', '')) - } - return format - }) + this.adaptiveFormats = filterInvidiousFormats(result.adaptiveFormats, this.allowDashAv1Formats) + .map((format) => { + format.bitrate = parseInt(format.bitrate) + if (typeof format.resolution !== 'undefined') { + format.height = parseInt(format.resolution.replace('p', '')) + } + return format + }) this.isLive = result.liveNow this.isFamilyFriendly = result.isFamilyFriendly this.captionHybridList = result.captions.map(caption => { From cf87d6fa76c39e50639adcf00c99f00a02c2b3a1 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Sat, 11 Mar 2023 16:29:52 +0100 Subject: [PATCH 02/10] Add comments and multiple bandwidth by 10 Co-authored-by: PikachuEXE --- src/renderer/components/ft-video-player/ft-video-player.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 8e8b8c123920..804fef552104 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -30,6 +30,7 @@ videojs.Vhs.xhr.beforeRequest = (options) => { // videojs-http-streaming spits out a warning every time you access videojs.Vhs.BANDWIDTH_VARIANCE // so we'll get the value once here, to stop it spamming the console +// https://github.com/videojs/http-streaming/blob/main/src/config.js#L8-L10 const VHS_BANDWIDTH_VARIANCE = videojs.Vhs.BANDWIDTH_VARIANCE export default defineComponent({ @@ -378,12 +379,13 @@ export default defineComponent({ } // regardless of what DASH qualities you enable or disable in the qualitLevels plugin - // the first segments videojs-http-streamming request are chosen based on the available bandwidth, which is set to 0.5MB/s by default + // the first segments videojs-http-streaming requests are chosen based on the available bandwidth, which is set to 0.5MB/s by default // overriding that to be the same as the quality we requested, makes videojs-http-streamming pick the correct quality const playerBandwidthOption = {} if (this.useDash && this.defaultQuality !== 'auto') { - playerBandwidthOption.bandwidth = this.selectedBitrate * VHS_BANDWIDTH_VARIANCE + 1 + // https://github.com/videojs/http-streaming#bandwidth + playerBandwidthOption.bandwidth = this.selectedBitrate * VHS_BANDWIDTH_VARIANCE * 10 + 1 } this.player = videojs(this.$refs.video, { From ecf1302a227d85b793160092769985c442abaab0 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Tue, 14 Mar 2023 19:44:43 +0100 Subject: [PATCH 03/10] Fix typo Co-authored-by: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com> --- src/renderer/components/ft-video-player/ft-video-player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 804fef552104..182187df4bdd 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -378,7 +378,7 @@ export default defineComponent({ controlBarItems.splice(index, 1) } - // regardless of what DASH qualities you enable or disable in the qualitLevels plugin + // regardless of what DASH qualities you enable or disable in the qualityLevels plugin // the first segments videojs-http-streaming requests are chosen based on the available bandwidth, which is set to 0.5MB/s by default // overriding that to be the same as the quality we requested, makes videojs-http-streamming pick the correct quality const playerBandwidthOption = {} From 07955890609756a4d4d90877be7e6ac2af3b3862 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Wed, 15 Mar 2023 15:27:08 +0800 Subject: [PATCH 04/10] ! Fix default quality `auto` handling --- src/renderer/components/ft-video-player/ft-video-player.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 182187df4bdd..71fcb0080634 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -155,7 +155,10 @@ export default defineComponent({ }, defaultQuality: function () { - return parseInt(this.$store.getters.getDefaultQuality) + const valueFromStore = this.$store.getters.getDefaultQuality + if (valueFromStore === 'auto') { return valueFromStore } + + return parseInt(valueFromStore) }, defaultCaptionSettings: function () { From bb3fbf80cc841bc18fde089d7b1ce50fefa32e7e Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Wed, 15 Mar 2023 15:38:54 +0800 Subject: [PATCH 05/10] ! Fix quality selection for short/vertical videos --- .../ft-video-player/ft-video-player.js | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) 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 71fcb0080634..55df6207bb0d 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -936,16 +936,34 @@ export default defineComponent({ this.selectedMimeType = 'auto' } else { const videoFormats = this.adaptiveFormats.filter(format => { - return (format.mimeType || format.type).startsWith('video') && typeof format.height !== 'undefined' + return (format.mimeType || format.type).startsWith('video') && + typeof format.height === 'number' && + typeof format.width === 'number' }) // Select the quality that is identical to the users chosen default quality if it's available // otherwise select the next lowest quality - let formatsToTest = videoFormats.filter(format => format.height === this.defaultQuality) + let formatsToTest = videoFormats.filter(format => { + // For short videos (or vertical videos?) + // Height > width (e.g. H: 1280, W: 720) + if (format.height > format.width) { + return format.width === this.defaultQuality + } + + return format.height === this.defaultQuality + }) if (formatsToTest.length === 0) { - formatsToTest = videoFormats.filter(format => format.height < this.defaultQuality) + formatsToTest = videoFormats.filter(format => { + // For short videos (or vertical videos?) + // Height > width (e.g. H: 1280, W: 720) + if (format.height > format.width) { + return format.width < this.defaultQuality + } + + return format.height < this.defaultQuality + }) } formatsToTest.sort((a, b) => { From 1529a83a542d2531c9f96a98042b290ec61ec0d0 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Wed, 15 Mar 2023 16:38:16 +0800 Subject: [PATCH 06/10] ! Fix default quality selection for Invidious API --- .../components/ft-video-player/ft-video-player.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) 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 55df6207bb0d..05ddaab3f98e 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -937,8 +937,7 @@ export default defineComponent({ } else { const videoFormats = this.adaptiveFormats.filter(format => { return (format.mimeType || format.type).startsWith('video') && - typeof format.height === 'number' && - typeof format.width === 'number' + typeof format.height === 'number' }) // Select the quality that is identical to the users chosen default quality if it's available @@ -947,7 +946,7 @@ export default defineComponent({ let formatsToTest = videoFormats.filter(format => { // For short videos (or vertical videos?) // Height > width (e.g. H: 1280, W: 720) - if (format.height > format.width) { + if (typeof format.width === 'number' && format.height > format.width) { return format.width === this.defaultQuality } @@ -958,7 +957,7 @@ export default defineComponent({ formatsToTest = videoFormats.filter(format => { // For short videos (or vertical videos?) // Height > width (e.g. H: 1280, W: 720) - if (format.height > format.width) { + if (typeof format.width === 'number' && format.height > format.width) { return format.width < this.defaultQuality } @@ -968,7 +967,7 @@ export default defineComponent({ formatsToTest.sort((a, b) => { if (a.height === b.height) { - return b.bitrate - a.bitrate + return b.fps - a.fps } else { return b.height - a.height } From 386b9529d647fe3de53921b8e82dc229fb0296c9 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Thu, 16 Mar 2023 14:32:28 +0800 Subject: [PATCH 07/10] * Update videojs bandwidth option value to max --- src/renderer/components/ft-video-player/ft-video-player.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) 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 05ddaab3f98e..2b7daa3ffe69 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -28,11 +28,6 @@ videojs.Vhs.xhr.beforeRequest = (options) => { } } -// videojs-http-streaming spits out a warning every time you access videojs.Vhs.BANDWIDTH_VARIANCE -// so we'll get the value once here, to stop it spamming the console -// https://github.com/videojs/http-streaming/blob/main/src/config.js#L8-L10 -const VHS_BANDWIDTH_VARIANCE = videojs.Vhs.BANDWIDTH_VARIANCE - export default defineComponent({ name: 'FtVideoPlayer', props: { @@ -388,7 +383,7 @@ export default defineComponent({ if (this.useDash && this.defaultQuality !== 'auto') { // https://github.com/videojs/http-streaming#bandwidth - playerBandwidthOption.bandwidth = this.selectedBitrate * VHS_BANDWIDTH_VARIANCE * 10 + 1 + playerBandwidthOption.bandwidth = Number.MAX_VALUE } this.player = videojs(this.$refs.video, { From 65b1e480e3f2625e282d7e2c0eebc7420b8e5b0f Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Thu, 16 Mar 2023 22:41:35 +0800 Subject: [PATCH 08/10] ~ Add comment about video format sorting logic when heights from 2 formats equal --- src/renderer/components/ft-video-player/ft-video-player.js | 2 ++ 1 file changed, 2 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 2b7daa3ffe69..442a4cab0d8a 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -962,6 +962,8 @@ export default defineComponent({ formatsToTest.sort((a, b) => { if (a.height === b.height) { + // Higher bitrate for video formats doesn't always make it a better quality format + // Higher FPS is what makes the difference return b.fps - a.fps } else { return b.height - a.height From 4ab8ba04e6f5a7aeec1533ad8e44c48d65f64dc8 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Fri, 17 Mar 2023 10:08:20 +0800 Subject: [PATCH 09/10] * Revert format preference back to higher bitrate with comments --- src/renderer/components/ft-video-player/ft-video-player.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 442a4cab0d8a..e64b3466440d 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -962,9 +962,9 @@ export default defineComponent({ formatsToTest.sort((a, b) => { if (a.height === b.height) { - // Higher bitrate for video formats doesn't always make it a better quality format - // Higher FPS is what makes the difference - return b.fps - a.fps + // Higher bitrate for video formats with HDR qualities + // `height` and `fps` are the same but `bitrate` would be higher + return b.bitrate - a.bitrate } else { return b.height - a.height } From 533956df2426c1c253e0de483e027a2ef3956fd8 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Fri, 17 Mar 2023 10:09:29 +0800 Subject: [PATCH 10/10] * Revert inflated initial bandwidth option value to fix #595 --- .../components/ft-video-player/ft-video-player.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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 e64b3466440d..7d1b9122dddf 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -28,6 +28,11 @@ videojs.Vhs.xhr.beforeRequest = (options) => { } } +// videojs-http-streaming spits out a warning every time you access videojs.Vhs.BANDWIDTH_VARIANCE +// so we'll get the value once here, to stop it spamming the console +// https://github.com/videojs/http-streaming/blob/main/src/config.js#L8-L10 +const VHS_BANDWIDTH_VARIANCE = videojs.Vhs.BANDWIDTH_VARIANCE + export default defineComponent({ name: 'FtVideoPlayer', props: { @@ -383,7 +388,9 @@ export default defineComponent({ if (this.useDash && this.defaultQuality !== 'auto') { // https://github.com/videojs/http-streaming#bandwidth - playerBandwidthOption.bandwidth = Number.MAX_VALUE + // Cannot be too high to fix https://github.com/FreeTubeApp/FreeTube/issues/595 + // (when default quality is low like 240p) + playerBandwidthOption.bandwidth = this.selectedBitrate * VHS_BANDWIDTH_VARIANCE + 1 } this.player = videojs(this.$refs.video, {