diff --git a/src/components/htmlMediaHelper.js b/src/components/htmlMediaHelper.js index c63eb29db0..70be9c45f1 100644 --- a/src/components/htmlMediaHelper.js +++ b/src/components/htmlMediaHelper.js @@ -1,6 +1,7 @@ import appSettings from '../scripts/settings/appSettings' ; import browser from '../scripts/browser'; import Events from '../utils/events.ts'; +import { MediaError } from 'types/mediaError'; export function getSavedVolume() { return appSettings.get('volume') || 1; @@ -87,7 +88,7 @@ export function handleHlsJsMediaError(instance, reject) { if (reject) { reject(); } else { - onErrorInternal(instance, 'mediadecodeerror'); + onErrorInternal(instance, MediaError.MEDIA_DECODE_ERROR); } } } @@ -269,10 +270,10 @@ export function bindEventsToHlsPlayer(instance, hls, elem, onErrorFn, resolve, r hls.destroy(); if (reject) { - reject('servererror'); + reject(MediaError.SERVER_ERROR); reject = null; } else { - onErrorInternal(instance, 'servererror'); + onErrorInternal(instance, MediaError.SERVER_ERROR); } return; @@ -291,10 +292,10 @@ export function bindEventsToHlsPlayer(instance, hls, elem, onErrorFn, resolve, r hls.destroy(); if (reject) { - reject('network'); + reject(MediaError.NETWORK_ERROR); reject = null; } else { - onErrorInternal(instance, 'network'); + onErrorInternal(instance, MediaError.NETWORK_ERROR); } } else { console.debug('fatal network error encountered, try to recover'); @@ -318,7 +319,7 @@ export function bindEventsToHlsPlayer(instance, hls, elem, onErrorFn, resolve, r reject(); reject = null; } else { - onErrorInternal(instance, 'mediadecodeerror'); + onErrorInternal(instance, MediaError.MEDIA_DECODE_ERROR); } break; } diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 503b844859..32108e77d5 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1,3 +1,6 @@ +import merge from 'lodash-es/merge'; +import Screenfull from 'screenfull'; + import Events from '../../utils/events.ts'; import datetime from '../../scripts/datetime'; import appSettings from '../../scripts/settings/appSettings'; @@ -8,14 +11,14 @@ import * as userSettings from '../../scripts/settings/userSettings'; import globalize from '../../scripts/globalize'; import loading from '../loading/loading'; import { appHost } from '../apphost'; -import Screenfull from 'screenfull'; import ServerConnections from '../ServerConnections'; import alert from '../alert'; import { PluginType } from '../../types/plugin.ts'; import { includesAny } from '../../utils/container.ts'; import { getItems } from '../../utils/jellyfin-apiclient/getItems.ts'; import { getItemBackdropImageUrl } from '../../utils/jellyfin-apiclient/backdropImage'; -import merge from 'lodash-es/merge'; + +import { MediaError } from 'types/mediaError'; const UNLIMITED_ITEMS = -1; @@ -1768,7 +1771,7 @@ class PlaybackManager { playerData.isChangingStream = false; onPlaybackError.call(player, e, { - type: 'mediadecodeerror', + type: MediaError.MEDIA_DECODE_ERROR, streamInfo: streamInfo }); }); @@ -2551,8 +2554,8 @@ class PlaybackManager { onPlaybackStarted(player, playOptions, streamInfo, mediaSource); setTimeout(function () { onPlaybackError.call(player, err, { - type: 'mediadecodeerror', - streamInfo: streamInfo + type: MediaError.MEDIA_DECODE_ERROR, + streamInfo }); }, 100); }); @@ -3194,22 +3197,32 @@ class PlaybackManager { } } + /** + * @param {object} streamInfo + * @param {MediaError} errorType + * @param {boolean} currentlyPreventsVideoStreamCopy + * @param {boolean} currentlyPreventsAudioStreamCopy + * @returns {boolean} Returns true if the stream should be retried by transcoding. + */ function enablePlaybackRetryWithTranscoding(streamInfo, errorType, currentlyPreventsVideoStreamCopy, currentlyPreventsAudioStreamCopy) { - // mediadecodeerror, medianotsupported, network, servererror return streamInfo.mediaSource.SupportsTranscoding && (!currentlyPreventsVideoStreamCopy || !currentlyPreventsAudioStreamCopy); } + /** + * Playback error handler. + * @param {Error} e + * @param {object} error + * @param {object} error.streamInfo + * @param {MediaError} error.type + */ function onPlaybackError(e, error) { const player = this; error = error || {}; - // network - // mediadecodeerror - // medianotsupported const errorType = error.type; - console.debug('playbackmanager playback error type: ' + (errorType || '')); + console.warn('[playbackmanager] onPlaybackError:', error); const streamInfo = error.streamInfo || getPlayerData(player).streamInfo; @@ -3235,8 +3248,7 @@ class PlaybackManager { Events.trigger(self, 'playbackerror', [errorType]); - const displayErrorCode = 'NoCompatibleStream'; - onPlaybackStopped.call(player, e, displayErrorCode); + onPlaybackStopped.call(player, e, `.${errorType}`); } function onPlaybackStopped(e, displayErrorCode) { diff --git a/src/plugins/htmlAudioPlayer/plugin.js b/src/plugins/htmlAudioPlayer/plugin.js index d9104638c8..1399003ad9 100644 --- a/src/plugins/htmlAudioPlayer/plugin.js +++ b/src/plugins/htmlAudioPlayer/plugin.js @@ -5,6 +5,7 @@ import profileBuilder from '../../scripts/browserDeviceProfile'; import { getIncludeCorsCredentials } from '../../scripts/settings/webSettings'; import { PluginType } from '../../types/plugin.ts'; import Events from '../../utils/events.ts'; +import { MediaError } from 'types/mediaError'; function getDefaultProfile() { return profileBuilder({}); @@ -343,7 +344,7 @@ class HtmlAudioPlayer { return; case 2: // MEDIA_ERR_NETWORK - type = 'network'; + type = MediaError.NETWORK_ERROR; break; case 3: // MEDIA_ERR_DECODE @@ -351,12 +352,12 @@ class HtmlAudioPlayer { htmlMediaHelper.handleHlsJsMediaError(self); return; } else { - type = 'mediadecodeerror'; + type = MediaError.MEDIA_DECODE_ERROR; } break; case 4: // MEDIA_ERR_SRC_NOT_SUPPORTED - type = 'medianotsupported'; + type = MediaError.MEDIA_NOT_SUPPORTED; break; default: // seeing cases where Edge is firing error events with no error code diff --git a/src/plugins/htmlVideoPlayer/plugin.js b/src/plugins/htmlVideoPlayer/plugin.js index c00116d515..6185ecdafe 100644 --- a/src/plugins/htmlVideoPlayer/plugin.js +++ b/src/plugins/htmlVideoPlayer/plugin.js @@ -37,6 +37,7 @@ import Events from '../../utils/events.ts'; import { includesAny } from '../../utils/container.ts'; import { isHls } from '../../utils/mediaSource.ts'; import debounce from 'lodash-es/debounce'; +import { MediaError } from 'types/mediaError'; /** * Returns resolved URL. @@ -1021,7 +1022,8 @@ export class HtmlVideoPlayer { // Only trigger this if there is media info // Avoid triggering in situations where it might not actually have a video stream (audio only live tv channel) if (!mediaSource || mediaSource.RunTimeTicks) { - onErrorInternal(this, 'mediadecodeerror'); + // FIXME: This shouldn't really be a decode error... + onErrorInternal(this, MediaError.MEDIA_DECODE_ERROR); } } } @@ -1073,7 +1075,7 @@ export class HtmlVideoPlayer { return; case 2: // MEDIA_ERR_NETWORK - type = 'network'; + type = MediaError.NETWORK_ERROR; break; case 3: // MEDIA_ERR_DECODE @@ -1081,12 +1083,12 @@ export class HtmlVideoPlayer { handleHlsJsMediaError(this); return; } else { - type = 'mediadecodeerror'; + type = MediaError.MEDIA_DECODE_ERROR; } break; case 4: // MEDIA_ERR_SRC_NOT_SUPPORTED - type = 'medianotsupported'; + type = MediaError.MEDIA_NOT_SUPPORTED; break; default: // seeing cases where Edge is firing error events with no error code @@ -1276,7 +1278,8 @@ export class HtmlVideoPlayer { // HACK: Give JavascriptSubtitlesOctopus time to dispose itself setTimeout(() => { - onErrorInternal(htmlVideoPlayer, 'mediadecodeerror'); + // FIXME: Probably not a decode error... + onErrorInternal(this, MediaError.MEDIA_DECODE_ERROR); }, 0); }, timeOffset: (this._currentPlayOptions.transcodingOffsetTicks || 0) / 10000000, diff --git a/src/types/mediaError.ts b/src/types/mediaError.ts new file mode 100644 index 0000000000..8124d38f13 --- /dev/null +++ b/src/types/mediaError.ts @@ -0,0 +1,9 @@ +/** + * Error types used for reporting media playback errors. + */ +export enum MediaError { + MEDIA_DECODE_ERROR = 'mediadecodeerror', + MEDIA_NOT_SUPPORTED = 'medianotsupported', + NETWORK_ERROR = 'network', + SERVER_ERROR = 'servererror' +}