mirror of
https://github.com/jellyfin/jellyfin-web.git
synced 2024-11-17 10:58:20 -07:00
fix: update ssa/ass checks, custom track location, offsets
This commit is contained in:
parent
49bae6b67c
commit
abc663f6f6
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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'
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user