1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Support subtitle offset

This commit is contained in:
Luke Pulverenti 2014-06-11 15:31:33 -04:00
parent c55d6e3511
commit 741ba6a543
3 changed files with 79 additions and 56 deletions

View file

@ -310,7 +310,7 @@
function renderDetails(page, item, context) { function renderDetails(page, item, context) {
renderSimilarItems(page, item, context); renderSimilarItems(page, item, context);
renderSiblingLinks(page, item); renderSiblingLinks(page, item, context);
if (item.Taglines && item.Taglines.length) { if (item.Taglines && item.Taglines.length) {
$('#itemTagline', page).html(item.Taglines[0]).show(); $('#itemTagline', page).html(item.Taglines[0]).show();
@ -479,10 +479,9 @@
}); });
} }
function renderSiblingLinks(page, item) { function renderSiblingLinks(page, item, context) {
$('.lnkSibling', page).addClass('hide'); $('.lnkSibling', page).addClass('hide');
return;
if ((item.Type != "Episode" && item.Type != "Season" && item.Type != "Audio") || item.IndexNumber == null) { if ((item.Type != "Episode" && item.Type != "Season" && item.Type != "Audio") || item.IndexNumber == null) {
return; return;
@ -515,6 +514,8 @@
}); });
} }
context = context || '';
promise.done(function (result) { promise.done(function (result) {
for (var i = 0, length = result.Items.length; i < length; i++) { for (var i = 0, length = result.Items.length; i < length; i++) {
@ -527,11 +528,11 @@
if (curr.IndexNumber < item.IndexNumber) { if (curr.IndexNumber < item.IndexNumber) {
$('.lnkPreviousItem', page).removeClass('hide').attr('href', 'itemdetails.html?id=' + curr.Id); $('.lnkPreviousItem', page).removeClass('hide').attr('href', 'itemdetails.html?id=' + curr.Id + '&context=' + context);
} }
else if (curr.IndexNumber > item.IndexNumber) { else if (curr.IndexNumber > item.IndexNumber) {
$('.lnkNextItem', page).removeClass('hide').attr('href', 'itemdetails.html?id=' + curr.Id); $('.lnkNextItem', page).removeClass('hide').attr('href', 'itemdetails.html?id=' + curr.Id + '&context=' + context);
} }
} }
}); });

View file

@ -14,8 +14,6 @@
var self = mediaPlayer; var self = mediaPlayer;
var currentItem;
var currentMediaSource;
var timeout; var timeout;
var video; var video;
var initialVolume; var initialVolume;
@ -30,6 +28,8 @@
var isPositionSliderActive; var isPositionSliderActive;
var currentTimeElement; var currentTimeElement;
self.currentSubtitleStreamIndex = null;
self.initVideoPlayer = function () { self.initVideoPlayer = function () {
video = playVideo(item, mediaSource, startPosition); video = playVideo(item, mediaSource, startPosition);
@ -176,7 +176,7 @@
var newPercent = parseInt(this.value); var newPercent = parseInt(this.value);
var newPositionTicks = (newPercent / 100) * currentMediaSource.RunTimeTicks; var newPositionTicks = (newPercent / 100) * self.currentMediaSource.RunTimeTicks;
self.changeStream(Math.floor(newPositionTicks)); self.changeStream(Math.floor(newPositionTicks));
} }
@ -405,7 +405,7 @@
var currentTicks = self.getCurrentTicks(); var currentTicks = self.getCurrentTicks();
var chapters = currentItem.Chapters || []; var chapters = self.currentItem.Chapters || [];
for (var i = 0, length = chapters.length; i < length; i++) { for (var i = 0, length = chapters.length; i < length; i++) {
@ -430,7 +430,7 @@
if (chapter.ImageTag) { if (chapter.ImageTag) {
imgUrl = ApiClient.getScaledImageUrl(currentItem.Id, { imgUrl = ApiClient.getScaledImageUrl(self.currentItem.Id, {
maxWidth: 100, maxWidth: 100,
tag: chapter.ImageTag, tag: chapter.ImageTag,
type: "Chapter", type: "Chapter",
@ -460,7 +460,7 @@
function getAudioTracksHtml() { function getAudioTracksHtml() {
var streams = currentMediaSource.MediaStreams.filter(function (currentStream) { var streams = self.currentMediaSource.MediaStreams.filter(function (currentStream) {
return currentStream.Type == "Audio"; return currentStream.Type == "Audio";
}); });
@ -528,11 +528,11 @@
function getSubtitleTracksHtml() { function getSubtitleTracksHtml() {
var streams = currentMediaSource.MediaStreams.filter(function (currentStream) { var streams = self.currentMediaSource.MediaStreams.filter(function (currentStream) {
return currentStream.Type == "Subtitle"; return currentStream.Type == "Subtitle";
}); });
var currentIndex = getParameterByName('SubtitleStreamIndex', video.currentSrc) || -1; var currentIndex = self.currentSubtitleStreamIndex;
var html = ''; var html = '';
@ -610,7 +610,7 @@
var currentAudioStreamIndex = getParameterByName('AudioStreamIndex', video.currentSrc); var currentAudioStreamIndex = getParameterByName('AudioStreamIndex', video.currentSrc);
var options = getVideoQualityOptions(currentMediaSource.MediaStreams, currentAudioStreamIndex, transcodingExtension); var options = getVideoQualityOptions(self.currentMediaSource.MediaStreams, currentAudioStreamIndex, transcodingExtension);
if (isStatic) { if (isStatic) {
options[0].name = "Direct"; options[0].name = "Direct";
@ -724,16 +724,28 @@
var mediaStreams = mediaSource.MediaStreams || []; var mediaStreams = mediaSource.MediaStreams || [];
var subtitleStreams = mediaStreams.filter(function (s) {
return s.Type == 'Subtitle';
});
var selectedSubtitleStream = subtitleStreams.filter(function (s) {
return s.Index == mediaSource.DefaultSubtitleStreamIndex;
})[0];
var baseParams = { var baseParams = {
audioChannels: 2, audioChannels: 2,
StartTimeTicks: startPosition, StartTimeTicks: startPosition,
SubtitleStreamIndex: mediaSource.DefaultSubtitleStreamIndex,
AudioStreamIndex: mediaSource.DefaultAudioStreamIndex, AudioStreamIndex: mediaSource.DefaultAudioStreamIndex,
deviceId: ApiClient.deviceId(), deviceId: ApiClient.deviceId(),
Static: false, Static: false,
mediaSourceId: mediaSource.Id mediaSourceId: mediaSource.Id
}; };
if (selectedSubtitleStream && selectedSubtitleStream.IsGraphicalSubtitleStream) {
baseParams.SubtitleStreamIndex = mediaSource.DefaultSubtitleStreamIndex;
}
var mp4Quality = getVideoQualityOptions(mediaStreams).filter(function (opt) { var mp4Quality = getVideoQualityOptions(mediaStreams).filter(function (opt) {
return opt.selected; return opt.selected;
})[0]; })[0];
@ -830,6 +842,22 @@
html += '<source type="video/mp4" src="' + mp4VideoUrl + '" />'; html += '<source type="video/mp4" src="' + mp4VideoUrl + '" />';
var textStreams = subtitleStreams.filter(function (s) {
return !s.IsGraphicalSubtitleStream;
});
for (var i = 0, length = textStreams.length; i < length; i++) {
var textStream = textStreams[i];
var textStreamUrl = ApiClient.getUrl('Videos/' + item.Id + '/Subtitles/' + textStream.Index + '/Stream.vtt', {
mediaSourceId: mediaSource.Id
});
var defaultAttribute = i.Index == mediaSource.DefaultSubtitleStreamIndex ? ' default' : '';
html += '<track data-index="' + textStream.Index + '" kind="subtitles" src="' + textStreamUrl + '" srclang="' + (textStream.Language || 'und') + '"' + defaultAttribute + '>';
}
html += '</video>'; html += '</video>';
var mediaPlayer = $("#mediaPlayer").show(); var mediaPlayer = $("#mediaPlayer").show();
@ -846,17 +874,15 @@
$('#video-qualityButton', videoControls).show(); $('#video-qualityButton', videoControls).show();
if (mediaStreams.filter(function (i) { if (mediaStreams.filter(function (s) {
return i.Type == "Audio"; return s.Type == "Audio";
}).length) { }).length) {
$('#video-audioTracksButton', videoControls).show(); $('#video-audioTracksButton', videoControls).show();
} else { } else {
$('#video-audioTracksButton', videoControls).hide(); $('#video-audioTracksButton', videoControls).hide();
} }
if (mediaStreams.filter(function (i) { if (subtitleStreams.length) {
return i.Type == "Subtitle";
}).length) {
$('#video-subtitleButton', videoControls).show().prop("disabled", false); $('#video-subtitleButton', videoControls).show().prop("disabled", false);
} else { } else {
$('#video-subtitleButton', videoControls).hide().prop("disabled", true);; $('#video-subtitleButton', videoControls).hide().prop("disabled", true);;
@ -1021,8 +1047,7 @@
fullscreenExited = false; fullscreenExited = false;
currentItem = item; self.currentSubtitleStreamIndex = mediaSource.DefaultSubtitleStreamIndex;
currentMediaSource = mediaSource;
return video[0]; return video[0];
} }

View file

@ -7,11 +7,12 @@
var testableVideoElement = document.createElement('video'); var testableVideoElement = document.createElement('video');
var currentMediaElement; var currentMediaElement;
var currentProgressInterval; var currentProgressInterval;
var currentItem;
var currentMediaSource;
var canClientSeek; var canClientSeek;
var currentPlaylistIndex = 0; var currentPlaylistIndex = 0;
self.currentItem = null;
self.currentMediaSource = null;
self.currentDurationTicks = null; self.currentDurationTicks = null;
self.startTimeTicksOffset = null; self.startTimeTicksOffset = null;
@ -110,7 +111,7 @@
var transcodingExtension = self.getTranscodingExtension(); var transcodingExtension = self.getTranscodingExtension();
var isStatic; var isStatic;
if (currentItem.MediaType == "Video") { if (self.currentItem.MediaType == "Video") {
if (params.AudioStreamIndex != null) { if (params.AudioStreamIndex != null) {
currentSrc = replaceQueryString(currentSrc, 'AudioStreamIndex', params.AudioStreamIndex); currentSrc = replaceQueryString(currentSrc, 'AudioStreamIndex', params.AudioStreamIndex);
@ -121,12 +122,12 @@
var maxWidth = params.MaxWidth || getParameterByName('MaxWidth', currentSrc); var maxWidth = params.MaxWidth || getParameterByName('MaxWidth', currentSrc);
var audioStreamIndex = params.AudioStreamIndex == null ? getParameterByName('AudioStreamIndex', currentSrc) : params.AudioStreamIndex; var audioStreamIndex = params.AudioStreamIndex == null ? getParameterByName('AudioStreamIndex', currentSrc) : params.AudioStreamIndex;
var subtitleStreamIndex = params.SubtitleStreamIndex == null ? getParameterByName('SubtitleStreamIndex', currentSrc) : params.SubtitleStreamIndex; var subtitleStreamIndex = self.currentSubtitleStreamIndex;
var videoBitrate = parseInt(getParameterByName('VideoBitrate', currentSrc) || '0'); var videoBitrate = parseInt(getParameterByName('VideoBitrate', currentSrc) || '0');
var audioBitrate = parseInt(getParameterByName('AudioBitrate', currentSrc) || '0'); var audioBitrate = parseInt(getParameterByName('AudioBitrate', currentSrc) || '0');
var bitrate = params.Bitrate || (videoBitrate + audioBitrate); var bitrate = params.Bitrate || (videoBitrate + audioBitrate);
var finalParams = self.getFinalVideoParams(currentMediaSource, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension); var finalParams = self.getFinalVideoParams(self.currentMediaSource, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension);
currentSrc = replaceQueryString(currentSrc, 'MaxWidth', finalParams.maxWidth); currentSrc = replaceQueryString(currentSrc, 'MaxWidth', finalParams.maxWidth);
currentSrc = replaceQueryString(currentSrc, 'VideoBitrate', finalParams.videoBitrate); currentSrc = replaceQueryString(currentSrc, 'VideoBitrate', finalParams.videoBitrate);
@ -167,7 +168,7 @@
}); });
if (currentItem.MediaType == "Video") { if (self.currentItem.MediaType == "Video") {
ApiClient.stopActiveEncodings().done(function () { ApiClient.stopActiveEncodings().done(function () {
self.startTimeTicksOffset = ticks; self.startTimeTicksOffset = ticks;
@ -212,7 +213,7 @@
currentTimeElement.html(timeText); currentTimeElement.html(timeText);
} }
var state = self.getPlayerStateInternal(currentMediaElement, currentItem, currentMediaSource); var state = self.getPlayerStateInternal(currentMediaElement, self.currentItem, self.currentMediaSource);
$(self).trigger('positionchange', [state]); $(self).trigger('positionchange', [state]);
}; };
@ -242,7 +243,7 @@
return false; return false;
} }
if (subtitleStream) { if (subtitleStream && subtitleStream.IsGraphicalSubtitleStream) {
console.log('Transcoding because subtitles are required'); console.log('Transcoding because subtitles are required');
return false; return false;
} }
@ -312,7 +313,7 @@
self.canQueueMediaType = function (mediaType) { self.canQueueMediaType = function (mediaType) {
return currentItem && currentItem.MediaType == mediaType; return self.currentItem && self.currentItem.MediaType == mediaType;
}; };
function translateItemsForPlayback(items) { function translateItemsForPlayback(items) {
@ -449,21 +450,21 @@
if (item.MediaType === "Video") { if (item.MediaType === "Video") {
currentItem = item; self.currentItem = item;
currentMediaSource = getOptimalMediaSource(item.MediaType, item.MediaSources); self.currentMediaSource = getOptimalMediaSource(item.MediaType, item.MediaSources);
videoPlayer(self, item, currentMediaSource, startPosition, user); videoPlayer(self, item, self.currentMediaSource, startPosition, user);
mediaElement = self.initVideoPlayer(); mediaElement = self.initVideoPlayer();
self.currentDurationTicks = currentMediaSource.RunTimeTicks; self.currentDurationTicks = self.currentMediaSource.RunTimeTicks;
} else if (item.MediaType === "Audio") { } else if (item.MediaType === "Audio") {
currentItem = item; self.currentItem = item;
currentMediaSource = getOptimalMediaSource(item.MediaType, item.MediaSources); self.currentMediaSource = getOptimalMediaSource(item.MediaType, item.MediaSources);
mediaElement = playAudio(item, currentMediaSource, startPosition); mediaElement = playAudio(item, self.currentMediaSource, startPosition);
self.currentDurationTicks = currentMediaSource.RunTimeTicks; self.currentDurationTicks = self.currentMediaSource.RunTimeTicks;
} else { } else {
throw new Error("Unrecognized media type"); throw new Error("Unrecognized media type");
@ -485,7 +486,7 @@
var mediaControls = $("#videoControls"); var mediaControls = $("#videoControls");
var state = self.getPlayerStateInternal(currentMediaElement, item, currentMediaSource); var state = self.getPlayerStateInternal(currentMediaElement, item, self.currentMediaSource);
var url = ""; var url = "";
@ -915,7 +916,7 @@
elem.pause(); elem.pause();
var isVideo = currentItem.MediaType == "Video"; var isVideo = self.currentItem.MediaType == "Video";
$(elem).off("ended.playnext").on("ended", function () { $(elem).off("ended.playnext").on("ended", function () {
@ -927,8 +928,8 @@
elem.src = ""; elem.src = "";
currentMediaElement = null; currentMediaElement = null;
currentItem = null; self.currentItem = null;
currentMediaSource = null; self.currentMediaSource = null;
}).trigger("ended"); }).trigger("ended");
@ -948,7 +949,7 @@
var deferred = $.Deferred(); var deferred = $.Deferred();
var result = self.getPlayerStateInternal(currentMediaElement, currentItem, currentMediaSource); var result = self.getPlayerStateInternal(currentMediaElement, self.currentItem, self.currentMediaSource);
deferred.resolveWith(null, [result]); deferred.resolveWith(null, [result]);
@ -977,11 +978,7 @@
if (audioStreamIndex) { if (audioStreamIndex) {
state.PlayState.AudioStreamIndex = parseInt(audioStreamIndex); state.PlayState.AudioStreamIndex = parseInt(audioStreamIndex);
} }
var subtitleStreamIndex = getParameterByName('SubtitleStreamIndex', currentSrc); state.PlayState.SubtitleStreamIndex = self.currentSubtitleStreamIndex;
if (subtitleStreamIndex) {
state.PlayState.SubtitleStreamIndex = parseInt(subtitleStreamIndex);
}
state.PlayState.PlayMethod = getParameterByName('static', currentSrc) == 'true' ? state.PlayState.PlayMethod = getParameterByName('static', currentSrc) == 'true' ?
'DirectStream' : 'DirectStream' :
@ -1076,7 +1073,7 @@
self.saveVolume(playerElement.volume); self.saveVolume(playerElement.volume);
var state = self.getPlayerStateInternal(playerElement, currentItem, currentMediaSource); var state = self.getPlayerStateInternal(playerElement, self.currentItem, self.currentMediaSource);
$(self).trigger('volumechange', [state]); $(self).trigger('volumechange', [state]);
}; };
@ -1091,8 +1088,8 @@
clearProgressInterval(); clearProgressInterval();
var item = currentItem; var item = self.currentItem;
var mediaSource = currentMediaSource; var mediaSource = self.currentMediaSource;
if (item.MediaType == "Video") { if (item.MediaType == "Video") {
ApiClient.stopActiveEncodings(); ApiClient.stopActiveEncodings();
@ -1109,7 +1106,7 @@
self.onPlaystateChange = function (playerElement) { self.onPlaystateChange = function (playerElement) {
var state = self.getPlayerStateInternal(playerElement, currentItem, currentMediaSource); var state = self.getPlayerStateInternal(playerElement, self.currentItem, self.currentMediaSource);
$(self).trigger('playstatechange', [state]); $(self).trigger('playstatechange', [state]);
}; };
@ -1117,7 +1114,7 @@
$(window).on("beforeunload popstate", function () { $(window).on("beforeunload popstate", function () {
// Try to report playback stopped before the browser closes // Try to report playback stopped before the browser closes
if (currentItem && currentMediaElement && currentProgressInterval) { if (self.currentItem && currentMediaElement && currentProgressInterval) {
self.onPlaybackStopped.call(currentMediaElement); self.onPlaybackStopped.call(currentMediaElement);
} }
@ -1125,7 +1122,7 @@
function sendProgressUpdate() { function sendProgressUpdate() {
var state = self.getPlayerStateInternal(currentMediaElement, currentItem, currentMediaSource); var state = self.getPlayerStateInternal(currentMediaElement, self.currentItem, self.currentMediaSource);
var info = { var info = {
QueueableMediaTypes: state.NowPlayingItem.MediaType, QueueableMediaTypes: state.NowPlayingItem.MediaType,