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'
+}