fix: update ssa/ass checks, custom track location, offsets

This commit is contained in:
Ivan Schurawel 2022-11-13 20:22:55 -05:00 committed by Ivan Schurawel
parent 49bae6b67c
commit abc663f6f6
4 changed files with 65 additions and 40 deletions

View File

@ -887,7 +887,7 @@ class PlaybackManager {
* - or if it can be paired with a secondary subtitle when used as a primary subtitle * - or if it can be paired with a secondary subtitle when used as a primary subtitle
*/ */
self.trackHasSecondarySubtitleSupport = function (track, player = self._currentPlayer) { self.trackHasSecondarySubtitleSupport = function (track, player = self._currentPlayer) {
if (!player || !self.playerHasSecondarySubtitleSupport(player)) return false; if (!player) return false;
const format = (track.Codec || '').toLowerCase(); const format = (track.Codec || '').toLowerCase();
// Currently, only non-SSA/non-ASS external subtitles are supported. // Currently, only non-SSA/non-ASS external subtitles are supported.
// Showing secondary subtitles does not work with any SSA/ASS subtitle combinations because // Showing secondary subtitles does not work with any SSA/ASS subtitle combinations because
@ -1578,8 +1578,9 @@ class PlaybackManager {
player.setSubtitleStreamIndex(selectedTrackElementIndex); player.setSubtitleStreamIndex(selectedTrackElementIndex);
// Also disable secondary subtitles when disabling the primary subtitles // Also disable secondary subtitles when disabling the primary
if (selectedTrackElementIndex === -1) { // subtitles, or if it doesn't support a secondary pair
if (selectedTrackElementIndex === -1 || !self.trackHasSecondarySubtitleSupport(newStream)) {
self.setSecondarySubtitleStreamIndex(selectedTrackElementIndex); self.setSecondarySubtitleStreamIndex(selectedTrackElementIndex);
} }
@ -1605,12 +1606,9 @@ class PlaybackManager {
return; return;
} }
const clearingStream = currentStream && !newStream;
const changingStream = currentStream && newStream;
const addingStream = !currentStream && newStream;
// Secondary subtitles are currently only handled client side // Secondary subtitles are currently only handled client side
// Changes to the server code are required before we can handle other delivery methods // Changes to the server code are required before we can handle other delivery methods
if (!clearingStream && (changingStream || addingStream) && getDeliveryMethod(newStream) !== 'External') { if (newStream && getDeliveryMethod(newStream) !== 'External') {
return; return;
} }

View File

@ -1035,10 +1035,26 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
setTimeout(resetIdle, 0); setTimeout(resetIdle, 0);
} }
/**
* Only show option if:
* - player has support
* - has more than 1 subtitle track
* - has valid secondary tracks
* - primary subtitle is not off
* - primary subtitle has support (index + 1 because `'Off'` is index 0 in `streams` array)
*/
function currentTrackCanHaveSecondarySubtitle(player, streams, currentIndex) {
const secondaryStreams = playbackManager.secondarySubtitleTracks(player);
return playbackManager.playerHasSecondarySubtitleSupport(player) &&
streams.length > 1 &&
secondaryStreams.length > 0 &&
currentIndex !== -1 &&
playbackManager.trackHasSecondarySubtitleSupport(streams[currentIndex + 1], player);
}
function showSubtitleTrackSelection() { function showSubtitleTrackSelection() {
const player = currentPlayer; const player = currentPlayer;
const streams = playbackManager.subtitleTracks(player); const streams = playbackManager.subtitleTracks(player);
const secondaryStreams = playbackManager.secondarySubtitleTracks(player);
let currentIndex = playbackManager.getSubtitleStreamIndex(player); let currentIndex = playbackManager.getSubtitleStreamIndex(player);
if (currentIndex == null) { if (currentIndex == null) {
@ -1062,21 +1078,7 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
return opt; return opt;
}); });
/** if (currentTrackCanHaveSecondarySubtitle(player, streams, currentIndex)) {
* Only show option if:
* - player has support
* - has more than 1 subtitle track
* - has valid secondary tracks
* - primary subtitle is not off
* - primary subtitle is `External`
*/
if (
playbackManager.playerHasSecondarySubtitleSupport(player) &&
streams.length > 1 &&
secondaryStreams.length > 0 &&
currentIndex !== -1 &&
playbackManager.isSubtitleStreamExternal(currentIndex, player)
) {
const secondarySubtitleMenuItem = { const secondarySubtitleMenuItem = {
name: globalize.translate('SecondarySubtitles'), name: globalize.translate('SecondarySubtitles'),
id: 'secondarysubtitle' id: 'secondarysubtitle'

View File

@ -225,6 +225,14 @@ function tryRemoveElement(elem) {
* @type {number | undefined} * @type {number | undefined}
*/ */
#currentTrackOffset; #currentTrackOffset;
/**
* @type {HTMLElement | null | undefined}
*/
#secondaryTrackOffset;
/**
* @type {number | null | undefined}
*/
#subtitleVerticalPosition;
/** /**
* @type {HTMLElement | null | undefined} * @type {HTMLElement | null | undefined}
*/ */
@ -539,6 +547,7 @@ function tryRemoveElement(elem) {
resetSubtitleOffset() { resetSubtitleOffset() {
this.#currentTrackOffset = 0; this.#currentTrackOffset = 0;
this.#secondaryTrackOffset = 0;
this.#showTrackOffset = false; this.#showTrackOffset = false;
} }
@ -581,7 +590,7 @@ function tryRemoveElement(elem) {
const trackElements = this.getTextTracks(); const trackElements = this.getTextTracks();
// if .vtt currently rendering // if .vtt currently rendering
if (trackElements.length > 0) { if (trackElements.length > 0) {
trackElements.forEach(function (trackElement, index) { trackElements.forEach((trackElement, index) => {
this.setTextTrackSubtitleOffset(trackElement, offsetValue, index); this.setTextTrackSubtitleOffset(trackElement, offsetValue, index);
}); });
} else if (this.#currentTrackEvents || this.#currentSecondaryTrackEvents) { } else if (this.#currentTrackEvents || this.#currentSecondaryTrackEvents) {
@ -596,24 +605,25 @@ function tryRemoveElement(elem) {
/** /**
* @private * @private
*/ */
updateCurrentTrackOffset(offsetValue, currentTrackIndex = 0) { updateCurrentTrackOffset(offsetValue, currentTrackIndex = PRIMARY_TEXT_TRACK_INDEX) {
const skipRelativeOffset = currentTrackIndex !== PRIMARY_TEXT_TRACK_INDEX; let offsetToCompare = this.#currentTrackOffset;
if (this.isSecondaryTrack(currentTrackIndex)) {
offsetToCompare = this.#secondaryTrackOffset;
}
let relativeOffset = offsetValue; let relativeOffset = offsetValue;
const newTrackOffset = offsetValue; const newTrackOffset = offsetValue;
if (this.#currentTrackOffset && !skipRelativeOffset) {
/** if (offsetToCompare) {
* Only calculate the offset for the first track. relativeOffset -= offsetToCompare;
* The offset gets set after this method is first called.
* Subsequent method calls (when playing multiple tracks)
* will have the calculated relative offset cancel out
* and will be `0`
* @example
* first_call: (relativeOffset = -2) -= (this.#currentTrackOffset = -1) -> 1
* second_call: (relativeOffset = -2) -= (this.#currentTrackOffset = -2) -> 0
*/
relativeOffset -= this.#currentTrackOffset;
} }
this.#currentTrackOffset = newTrackOffset;
if (this.isSecondaryTrack(currentTrackIndex)) {
this.#secondaryTrackOffset = newTrackOffset;
} else {
this.#currentTrackOffset = newTrackOffset;
}
// relative to currentTrackOffset // relative to currentTrackOffset
return relativeOffset; return relativeOffset;
} }
@ -1132,6 +1142,7 @@ function tryRemoveElement(elem) {
this.destroyNativeTracks(videoElement, targetTrackIndex); this.destroyNativeTracks(videoElement, targetTrackIndex);
this.destroyStoredTrackInfo(targetTrackIndex); this.destroyStoredTrackInfo(targetTrackIndex);
this.#subtitleVerticalPosition = null;
this.#currentClock = null; this.#currentClock = null;
this._currentAspectRatio = null; this._currentAspectRatio = null;
@ -1322,6 +1333,14 @@ function tryRemoveElement(elem) {
* @private * @private
*/ */
renderSubtitlesWithCustomElement(videoElement, track, item, targetTextTrackIndex) { renderSubtitlesWithCustomElement(videoElement, track, item, targetTextTrackIndex) {
if (this.#subtitleVerticalPosition == null) {
import('../../scripts/settings/userSettings').then((userSettings) => {
const subtitleAppearance = userSettings.getSubtitleAppearanceSettings();
this.#subtitleVerticalPosition = subtitleAppearance.verticalPosition;
this.#subtitleVerticalPosition = parseInt(subtitleAppearance.verticalPosition, 10);
});
}
this.fetchSubtitles(track, item).then((data) => { this.fetchSubtitles(track, item).then((data) => {
if (!this.#videoSubtitlesElem && !this.isSecondaryTrack(targetTextTrackIndex)) { if (!this.#videoSubtitlesElem && !this.isSecondaryTrack(targetTextTrackIndex)) {
let subtitlesContainer = document.querySelector('.videoSubtitles'); let subtitlesContainer = document.querySelector('.videoSubtitles');
@ -1341,7 +1360,12 @@ function tryRemoveElement(elem) {
if (!subtitlesContainer) return; if (!subtitlesContainer) return;
const secondarySubtitlesElement = document.createElement('div'); const secondarySubtitlesElement = document.createElement('div');
secondarySubtitlesElement.classList.add('videoSecondarySubtitlesInner'); secondarySubtitlesElement.classList.add('videoSecondarySubtitlesInner');
subtitlesContainer.prepend(secondarySubtitlesElement); // determine the order of the subtitles
if (this.#subtitleVerticalPosition < 0) {
subtitlesContainer.prepend(secondarySubtitlesElement);
} else {
subtitlesContainer.appendChild(secondarySubtitlesElement);
}
this.#videoSecondarySubtitlesElem = secondarySubtitlesElement; this.#videoSecondarySubtitlesElem = secondarySubtitlesElement;
this.setSubtitleAppearance(subtitlesContainer, this.#videoSecondarySubtitlesElem); this.setSubtitleAppearance(subtitlesContainer, this.#videoSecondarySubtitlesElem);
this.#currentSecondaryTrackEvents = data.TrackEvents; this.#currentSecondaryTrackEvents = data.TrackEvents;

View File

@ -80,6 +80,7 @@ video[controls]::-webkit-media-controls {
margin: auto; margin: auto;
display: block; display: block;
min-height: 0 !important; min-height: 0 !important;
margin-top: 0.5em !important;
margin-bottom: 0.5em !important; margin-bottom: 0.5em !important;
} }