diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 48e2913188..f0cf735522 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1488,6 +1488,24 @@ class PlaybackManager { return getPlayerData(player).subtitleStreamIndex; }; + self.getSecondarySubtitleStreamIndex = function (player) { + player = player || self._currentPlayer; + + try { + if (player && !enableLocalPlaylistManagement(player)) { + return player.getSecondarySubtitleStreamIndex(); + } + } catch (e) { + console.error(`Failed to get secondary stream index: ${e}`); + } + + if (!player) { + throw new Error('player cannot be null'); + } + + return getPlayerData(player).secondarySubtitleStreamIndex; + }; + function getDeliveryMethod(subtitleStream) { // This will be null for internal subs for local items if (subtitleStream.DeliveryMethod) { diff --git a/src/plugins/htmlVideoPlayer/plugin.js b/src/plugins/htmlVideoPlayer/plugin.js index 5b9fb3d471..ac178d8511 100644 --- a/src/plugins/htmlVideoPlayer/plugin.js +++ b/src/plugins/htmlVideoPlayer/plugin.js @@ -186,6 +186,10 @@ function tryRemoveElement(elem) { * @type {number | undefined} */ #subtitleTrackIndexToSetOnPlaying; + /** + * @type {number | undefined} + */ + #secondarySubtitleTrackIndexToSetOnPlaying; /** * @type {number | null} */ @@ -474,6 +478,15 @@ function tryRemoveElement(elem) { this.#subtitleTrackIndexToSetOnPlaying = -1; } } + // Continue using the secondary track that has been set during this watch session + const currentSecondaryTrackIndex = playbackManager.getSecondarySubtitleStreamIndex(); + this.#secondarySubtitleTrackIndexToSetOnPlaying = currentSecondaryTrackIndex == null ? -1 : currentSecondaryTrackIndex; + if (this.#secondarySubtitleTrackIndexToSetOnPlaying != null && this.#secondarySubtitleTrackIndexToSetOnPlaying >= 0) { + const initialSecondarySubtitleStream = options.mediaSource.MediaStreams[this.#secondarySubtitleTrackIndexToSetOnPlaying]; + if (!initialSecondarySubtitleStream || initialSecondarySubtitleStream.DeliveryMethod !== 'External') { + this.#secondarySubtitleTrackIndexToSetOnPlaying = -1; + } + } this.#audioTrackIndexToSetOnPlaying = options.playMethod === 'Transcode' ? null : options.mediaSource.DefaultAudioStreamIndex; @@ -889,6 +902,16 @@ function tryRemoveElement(elem) { if (this.#audioTrackIndexToSetOnPlaying != null && this.canSetAudioStreamIndex()) { this.setAudioStreamIndex(this.#audioTrackIndexToSetOnPlaying); } + + if (this.#secondarySubtitleTrackIndexToSetOnPlaying != null && this.#secondarySubtitleTrackIndexToSetOnPlaying >= 0) { + /** + * Using a 0ms timeout to set the secondary subtitles because of some weird race condition when + * setting both primary and secondary tracks at the same time. + * The `TextTrack` content and cues will somehow get mixed up and each track will play a mix of both languages. + * Putting this in a timeout fixes it completely. + */ + setTimeout(() => this.setSecondarySubtitleStreamIndex(this.#secondarySubtitleTrackIndexToSetOnPlaying), 0); + } } /**