Skip to content

Commit

Permalink
Better player error handling (#6180)
Browse files Browse the repository at this point in the history
* Better player error handling

* Fix format switching

* Fix legacy quality handling
  • Loading branch information
absidue authored Nov 21, 2024
1 parent dc65eec commit d555278
Showing 1 changed file with 54 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1252,24 +1252,21 @@ export default defineComponent({
}

/**
* @param {'dash'|'audio'|null} previousFormat
* @param {number|null} playbackPosition
* @param {number|undefined} previousQuality
*/
async function setLegacyQuality(previousFormat = null, playbackPosition = null) {
async function setLegacyQuality(playbackPosition = null, previousQuality = undefined) {
if (typeof previousQuality === 'undefined') {
if (defaultQuality.value === 'auto') {
previousQuality = Infinity
} else {
previousQuality = defaultQuality.value
}
}

/** @type {object[]} */
const legacyFormats = props.legacyFormats

let previousQuality
if (previousFormat === 'dash') {
const previousTrack = player.getVariantTracks().find(track => track.active)

previousQuality = previousTrack.height > previousTrack.width ? previousTrack.width : previousTrack.height
} else if (defaultQuality.value === 'auto') {
previousQuality = Infinity
} else {
previousQuality = defaultQuality.value
}

const isPortrait = legacyFormats[0].height > legacyFormats[0].width

let matches = legacyFormats.filter(variant => {
Expand Down Expand Up @@ -2147,17 +2144,28 @@ export default defineComponent({

// #endregion keyboard shortcuts

let ignoreErrors = false

/**
* @param {shaka.util.Error} error
* @param {string} context
* @param {object?} details
*/
function handleError(error, context, details) {
// These two errors are just wrappers around another error, so use the original error instead
// As they can be nested (e.g. multiple googlevideo redirects because the Invidious server was far away from the user) we should pick the inner most one
while (error.code === shaka.util.Error.Code.REQUEST_FILTER_ERROR || error.code === shaka.util.Error.Code.RESPONSE_FILTER_ERROR) {
error = error.data[0]
}

logShakaError(error, context, props.videoId, details)

// text related errors aren't serious (captions and seek bar thumbnails), so we should just log them
// TODO: consider only emitting when the severity is crititcal?
if (error.category !== shaka.util.Error.Category.TEXT) {
if (!ignoreErrors && error.category !== shaka.util.Error.Category.TEXT) {
// don't react to multiple consecutive errors, otherwise we don't give the format fallback from the previous error a chance to work
ignoreErrors = true

emit('error', error)

stopPowerSaveBlocker()
Expand Down Expand Up @@ -2414,7 +2422,7 @@ export default defineComponent({
handleError(error, 'loading dash/audio manifest and setting default quality in mounted')
}
} else {
await setLegacyQuality(null, props.startTime)
await setLegacyQuality(props.startTime)
}
}

Expand Down Expand Up @@ -2532,9 +2540,17 @@ export default defineComponent({
* @param {'dash'|'audio'|'legacy'} oldFormat
*/
async (newFormat, oldFormat) => {
ignoreErrors = true

// format switch happened before the player loaded, probably because of an error
// as there are no previous player settings to restore, we should treat it like this was the original format
if (!hasLoaded.value) {
try {
await player.unload()
} catch { }

ignoreErrors = false

player.configure(getPlayerConfig(newFormat, defaultQuality.value === 'auto'))

await performFirstLoad()
Expand Down Expand Up @@ -2597,6 +2613,12 @@ export default defineComponent({
}
}

try {
await player.unload()
} catch { }

ignoreErrors = false

player.configure(getPlayerConfig(newFormat, useAutoQuality))

try {
Expand Down Expand Up @@ -2634,7 +2656,21 @@ export default defineComponent({
}
activeLegacyFormat.value = null
} else {
await setLegacyQuality(oldFormat, playbackPosition)
let previousQuality

if (oldFormat === 'dash') {
const previousTrack = player.getVariantTracks().find(track => track.active)

previousQuality = previousTrack.height > previousTrack.width ? previousTrack.width : previousTrack.height
}

try {
await player.unload()
} catch { }

ignoreErrors = false

await setLegacyQuality(playbackPosition, previousQuality)
}

if (wasPaused) {
Expand Down Expand Up @@ -2702,6 +2738,8 @@ export default defineComponent({
* To workaround that we destroy the player first and wait for it to finish before we unmount this component.
*/
async function destroyPlayer() {
ignoreErrors = true

if (ui) {
// destroying the ui also destroys the player
await ui.destroy()
Expand Down

0 comments on commit d555278

Please sign in to comment.