diff --git a/src/components/htmlMediaHelper.js b/src/components/htmlMediaHelper.js index 70be9c45f1..09eb2a6095 100644 --- a/src/components/htmlMediaHelper.js +++ b/src/components/htmlMediaHelper.js @@ -88,7 +88,7 @@ export function handleHlsJsMediaError(instance, reject) { if (reject) { reject(); } else { - onErrorInternal(instance, MediaError.MEDIA_DECODE_ERROR); + onErrorInternal(instance, MediaError.FATAL_HLS_ERROR); } } } @@ -99,11 +99,7 @@ export function onErrorInternal(instance, type) { instance.destroyCustomTrack(instance._mediaElement); } - Events.trigger(instance, 'error', [ - { - type: type - } - ]); + Events.trigger(instance, 'error', [{ type }]); } export function isValidDuration(duration) { @@ -319,7 +315,7 @@ export function bindEventsToHlsPlayer(instance, hls, elem, onErrorFn, resolve, r reject(); reject = null; } else { - onErrorInternal(instance, MediaError.MEDIA_DECODE_ERROR); + onErrorInternal(instance, MediaError.FATAL_HLS_ERROR); } break; } diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 32108e77d5..cfdfcbdb52 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1,3 +1,4 @@ +import { PlaybackErrorCode } from '@jellyfin/sdk/lib/generated-client/models/playback-error-code.js'; import merge from 'lodash-es/merge'; import Screenfull from 'screenfull'; @@ -591,9 +592,18 @@ function supportsDirectPlay(apiClient, item, mediaSource) { return Promise.resolve(false); } +/** + * @param {PlaybackManager} instance + * @param {import('@jellyfin/sdk/lib/generated-client/index.js').PlaybackInfoResponse} result + * @returns {boolean} + */ function validatePlaybackInfoResult(instance, result) { if (result.ErrorCode) { - showPlaybackInfoErrorMessage(instance, 'PlaybackError' + result.ErrorCode); + // NOTE: To avoid needing to retranslate the "NoCompatibleStream" message, + // we need to keep the key in the same format. + const errMessage = result.ErrorCode === PlaybackErrorCode.NoCompatibleStream ? + 'PlaybackErrorNoCompatibleStream' : `PlaybackError.${result.ErrorCode}`; + showPlaybackInfoErrorMessage(instance, errMessage); return false; } @@ -1723,7 +1733,7 @@ class PlaybackManager { streamInfo.resetSubtitleOffset = false; if (!streamInfo.url) { - showPlaybackInfoErrorMessage(self, 'PlaybackErrorNoCompatibleStream'); + showPlaybackInfoErrorMessage(self, `PlaybackError.${MediaError.NO_MEDIA_ERROR}`); return; } @@ -1771,7 +1781,7 @@ class PlaybackManager { playerData.isChangingStream = false; onPlaybackError.call(player, e, { - type: MediaError.MEDIA_DECODE_ERROR, + type: MediaError.PLAYER_ERROR, streamInfo: streamInfo }); }); @@ -2182,7 +2192,7 @@ class PlaybackManager { // If it's still null then there's nothing to play if (!firstItem) { - showPlaybackInfoErrorMessage(self, 'PlaybackErrorNoCompatibleStream'); + showPlaybackInfoErrorMessage(self, `PlaybackError.${MediaError.NO_MEDIA_ERROR}`); return Promise.reject(); } @@ -2554,7 +2564,7 @@ class PlaybackManager { onPlaybackStarted(player, playOptions, streamInfo, mediaSource); setTimeout(function () { onPlaybackError.call(player, err, { - type: MediaError.MEDIA_DECODE_ERROR, + type: MediaError.PLAYER_ERROR, streamInfo }); }, 100); @@ -2788,7 +2798,7 @@ class PlaybackManager { return mediaSource; } } else { - showPlaybackInfoErrorMessage(self, 'PlaybackErrorNoCompatibleStream'); + showPlaybackInfoErrorMessage(self, `PlaybackError.${MediaError.NO_MEDIA_ERROR}`); return Promise.reject(); } }); diff --git a/src/plugins/htmlVideoPlayer/plugin.js b/src/plugins/htmlVideoPlayer/plugin.js index 6185ecdafe..6f78cb80c1 100644 --- a/src/plugins/htmlVideoPlayer/plugin.js +++ b/src/plugins/htmlVideoPlayer/plugin.js @@ -1022,8 +1022,7 @@ 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) { - // FIXME: This shouldn't really be a decode error... - onErrorInternal(this, MediaError.MEDIA_DECODE_ERROR); + onErrorInternal(this, MediaError.NO_MEDIA_ERROR); } } } @@ -1279,7 +1278,7 @@ export class HtmlVideoPlayer { // HACK: Give JavascriptSubtitlesOctopus time to dispose itself setTimeout(() => { // FIXME: Probably not a decode error... - onErrorInternal(this, MediaError.MEDIA_DECODE_ERROR); + onErrorInternal(this, MediaError.ASS_RENDER_ERROR); }, 0); }, timeOffset: (this._currentPlayOptions.transcodingOffsetTicks || 0) / 10000000, diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 13363d303f..e0318abe6d 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1228,6 +1228,16 @@ "Play": "Play", "PlayAllFromHere": "Play all from here", "PlaybackData": "Playback Info", + "PlaybackError.ASS_RENDER_ERROR": "", + "PlaybackError.FATAL_HLS_ERROR": "", + "PlaybackError.MEDIA_DECODE_ERROR": "", + "PlaybackError.MEDIA_NOT_SUPPORTED": "", + "PlaybackError.NETWORK_ERROR": "", + "PlaybackError.NO_MEDIA_ERROR": "", + "PlaybackError.PLAYER_ERROR": "", + "PlaybackError.SERVER_ERROR": "", + "PlaybackError.NotAllowed": "", + "PlaybackError.RateLimitExceeded": "", "PlaybackErrorNoCompatibleStream": "This client isn't compatible with the media and the server isn't sending a compatible media format.", "PlaybackErrorPlaceHolder": "This is a placeholder for physical media that Jellyfin cannot play. Please insert the disc to play.", "PlaybackRate": "Playback Speed", diff --git a/src/types/mediaError.ts b/src/types/mediaError.ts index 8124d38f13..d12d74f17f 100644 --- a/src/types/mediaError.ts +++ b/src/types/mediaError.ts @@ -2,8 +2,12 @@ * 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' + ASS_RENDER_ERROR = 'ASS_RENDER_ERROR', + FATAL_HLS_ERROR = 'FATAL_HLS_ERROR', + MEDIA_DECODE_ERROR = 'MEDIA_DECODE_ERROR', + MEDIA_NOT_SUPPORTED = 'MEDIA_NOT_SUPPORTED', + NETWORK_ERROR = 'NETWORK_ERROR', + NO_MEDIA_ERROR = 'NO_MEDIA_ERROR', + PLAYER_ERROR = 'PLAYER_ERROR', + SERVER_ERROR = 'SERVER_ERROR' }