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

subtitle and language selector in video player, respect audio and subtitle preference selections

This commit is contained in:
Techywarrior 2013-04-04 19:09:05 -07:00
parent 25e062004f
commit 9c2e442d46
5 changed files with 131 additions and 63 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 857 B

After

Width:  |  Height:  |  Size: 651 B

Before After
Before After

View file

@ -838,8 +838,10 @@ progress {
width: auto !important; width: auto !important;
} }
.vjs-quality-button div { .vjs-default-skin .vjs-menu-button.vjs-quality-button div {
background: red !important; background: url("images/media/quality.png");
height: 16px;
width: 16px;
} }
.vjs-chapter-button div { .vjs-chapter-button div {
@ -873,7 +875,7 @@ progress {
} }
.vjs-subtitle-button div { .vjs-subtitle-button div {
background: green !important; background-position: -25px -75px !important;
} }
.vjs-subtitle-button.vjs-menu-button ul { .vjs-subtitle-button.vjs-menu-button ul {
@ -889,8 +891,10 @@ progress {
padding-right: 10px; padding-right: 10px;
} }
.vjs-language-button div { .vjs-default-skin .vjs-menu-button.vjs-language-button div {
background: yellow !important; background: url("images/media/language.png") !important;
height: 16px;
width: 16px;
} }
.vjs-language-button.vjs-menu-button ul { .vjs-language-button.vjs-menu-button ul {

View file

@ -179,6 +179,37 @@
var screenHeight = Math.min(screen.height, screen.width); var screenHeight = Math.min(screen.height, screen.width);
var volume = localStorage.getItem("volume") || 0.5; var volume = localStorage.getItem("volume") || 0.5;
var user = Dashboard.getCurrentUser();
var defaults = {languageIndex: null, subtitleIndex: null};
var user_config = user.Configuration || {};
if (item.MediaStreams && item.MediaStreams.length) {
$.each(item.MediaStreams, function (i, stream) {
//get default subtitle stream
if (stream.Type == "Subtitle") {
if (user_config.UseForcedSubtitlesOnly == true && user_config.SubtitleLanguagePreference && !defaults.subtitleIndex) {
if (stream.Language == user_config.SubtitleLanguagePreference && stream.IsForced == true) {
defaults.subtitleIndex = i;
}
}else if (user_config.SubtitleLanguagePreference && !defaults.subtitleIndex) {
if (stream.Language == user_config.SubtitleLanguagePreference) {
defaults.subtitleIndex = i;
}
}else if (user_config.UseForcedSubtitlesOnly == true && !defaults.subtitleIndex) {
if (stream.IsForced == true) {
defaults.subtitleIndex = i;
}
}
}else if (stream.Type == "Audio") {
//get default language stream
if (user_config.AudioLanguagePreference && !defaults.languageIndex) {
if (stream.Language == user_config.AudioLanguagePreference) {
defaults.languageIndex = i;
}
}
}
});
}
var baseParams = { var baseParams = {
audioChannels: 2, audioChannels: 2,
@ -186,7 +217,9 @@
videoBitrate: 1500000, videoBitrate: 1500000,
maxWidth: screenWidth, maxWidth: screenWidth,
maxHeight: screenHeight, maxHeight: screenHeight,
StartTimeTicks: 0 StartTimeTicks: 0,
SubtitleStreamIndex: null,
AudioStreamIndex: null
}; };
if (typeof (startPosition) != "undefined") { if (typeof (startPosition) != "undefined") {
@ -235,7 +268,7 @@
{ type: "video/ogg", src: ogvVideoUrl }] { type: "video/ogg", src: ogvVideoUrl }]
).volume(volume); ).volume(volume);
videoJSextension.setup_video($('#videoWindow'), item); videoJSextension.setup_video($('#videoWindow'), item, defaults);
(this).addEvent("loadstart", function () { (this).addEvent("loadstart", function () {
$(".vjs-remaining-time-display").hide(); $(".vjs-remaining-time-display").hide();
@ -276,7 +309,7 @@
ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), item_id, positionTicks); ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), item_id, positionTicks);
clearTimeout(progressInterval); clearTimeout(MediaPlayer.progressInterval);
if (player.techName == "html5") { if (player.techName == "html5") {
player.tag.src = ""; player.tag.src = "";
@ -302,7 +335,7 @@
}, },
updateProgress: function () { updateProgress: function () {
progressInterval = setInterval(function () { MediaPlayer.progressInterval = setInterval(function () {
var player = _V_("videoWindow"); var player = _V_("videoWindow");
var startTimeTicks = player.tag.src.match(new RegExp("StartTimeTicks=[0-9]+", "g")); var startTimeTicks = player.tag.src.match(new RegExp("StartTimeTicks=[0-9]+", "g"));

View file

@ -6,7 +6,7 @@ var videoJSextension = {
a mandatory jQuery object of the <video> element we are setting up the a mandatory jQuery object of the <video> element we are setting up the
videojs video for. videojs video for.
*/ */
setup_video: function ($video, item) { setup_video: function ($video, item, defaults) {
// Add the stop button. // Add the stop button.
_V_.merge(_V_.ControlBar.prototype.options.components, { StopButton: {} }); _V_.merge(_V_.ControlBar.prototype.options.components, { StopButton: {} });
@ -18,6 +18,10 @@ var videoJSextension = {
vjs_source = {}, vjs_source = {},
vjs_chapters = [], // This will be an array of arrays of objects, see the video.js api documentation for myPlayer.src() vjs_chapters = [], // This will be an array of arrays of objects, see the video.js api documentation for myPlayer.src()
vjs_chapter = {}; vjs_chapter = {};
vjs_languages = [], // This will be an array of arrays of objects, see the video.js api documentation for myPlayer.src()
vjs_language = {};
vjs_subtitles = [], // This will be an array of arrays of objects, see the video.js api documentation for myPlayer.src()
vjs_subtitle = {};
// Determine this video's default res (it might not have the globally determined default available) // Determine this video's default res (it might not have the globally determined default available)
default_res = available_res[0]; default_res = available_res[0];
@ -67,53 +71,63 @@ var videoJSextension = {
} }
//chceck if langauges exist and add language selector //chceck if langauges exist and add language selector also subtitles
if (item.Chapters && item.Chapters.length) { if (item.MediaStreams && item.MediaStreams.length) {
// Put together the videojs source arrays for each available chapter var subCount = 1;
$.each(item.Chapters, function (i, chapter) { var langCount = 1;
var defaultLanguageIndex = defaults.languageIndex || 1;
var defaultSubtitleIndex = defaults.subtitleIndex || 0;
vjs_chapters[i] = []; // Put together the videojs source arrays for each available language and subtitle
$.each(item.MediaStreams, function (i, stream) {
var language = stream.Language || '';
vjs_chapter = {}; if (stream.Type == "Audio") {
vjs_chapter.Name = chapter.Name + " (" + ticks_to_human(chapter.StartPositionTicks) + ")"; vjs_languages[i] = [];
vjs_chapter.StartPositionTicks = chapter.StartPositionTicks; vjs_language = {};
vjs_chapters[i].push(vjs_chapter); vjs_language.Name = langCount + ": " + language + " " + stream.Codec + " " + stream.Channels + "ch";
vjs_language.index = i;
vjs_languages[i].push(vjs_language);
langCount++;
}else if (stream.Type == "Subtitle") {
vjs_subtitles[i] = [];
vjs_subtitle = {};
vjs_subtitle.Name = subCount + ": " + language;
vjs_subtitle.index = i;
vjs_subtitles[i].push(vjs_subtitle);
subCount++;
}
}); });
_V_.LanguageSelectorButton = _V_.LanguageSelector.extend({ if (vjs_languages.length) {
buttonText: '',
Chapters: vjs_chapters
});
// Add the chapter selector button. _V_.LanguageSelectorButton = _V_.LanguageSelector.extend({
_V_.merge(_V_.ControlBar.prototype.options.components, { LanguageSelectorButton: {} }); buttonText: vjs_languages[defaultLanguageIndex][0].Name,
} Languages: vjs_languages
});
// Add the language selector button.
_V_.merge(_V_.ControlBar.prototype.options.components, { LanguageSelectorButton: {} });
}
//chceck if subtitles exist and add subtitle selector if (vjs_subtitles.length) {
if (item.Chapters && item.Chapters.length) { vjs_subtitles[0] = [];
// Put together the videojs source arrays for each available chapter vjs_subtitles[0].push({Name: "Off", index: ''});
$.each(item.Chapters, function (i, chapter) { _V_.SubtitleSelectorButton = _V_.SubtitleSelector.extend({
buttonText: vjs_subtitles[defaultSubtitleIndex][0].Name,
Subtitles: vjs_subtitles
});
vjs_chapters[i] = []; // Add the subtitle selector button.
_V_.merge(_V_.ControlBar.prototype.options.components, { SubtitleSelectorButton: {} });
}
vjs_chapter = {};
vjs_chapter.Name = chapter.Name + " (" + ticks_to_human(chapter.StartPositionTicks) + ")";
vjs_chapter.StartPositionTicks = chapter.StartPositionTicks;
vjs_chapters[i].push(vjs_chapter);
});
_V_.SubtitleSelectorButton = _V_.SubtitleSelector.extend({
buttonText: '',
Chapters: vjs_chapters
});
// Add the chapter selector button.
_V_.merge(_V_.ControlBar.prototype.options.components, { SubtitleSelectorButton: {} });
} }
} }
@ -292,6 +306,7 @@ _V_.ResolutionMenuItem = _V_.MenuItem.extend({
this.play(); this.play();
}); });
} else { } else {
newSrc += "&StartTimeTicks=0";
this.player.src(newSrc).one('loadedmetadata', function () { this.player.src(newSrc).one('loadedmetadata', function () {
this.currentTime(current_time); this.currentTime(current_time);
this.play(); this.play();
@ -548,6 +563,9 @@ _V_.SubtitleSelector = _V_.Button.extend({
this._super(player, options); this._super(player, options);
// Save the starting subtitle track as a property of the player object
player.options.currentSubtitle = this.buttonText;
this.menu = this.createMenu(); this.menu = this.createMenu();
if (this.items.length === 0) { if (this.items.length === 0) {
@ -598,11 +616,12 @@ _V_.SubtitleSelector = _V_.Button.extend({
var items = []; var items = [];
this.each(this.Subtitles, function (subtitle) { this.each(this.Subtitles, function (subtitle) {
if (subtitle && subtitle.length) {
items.push(new _V_.SubtitleMenuItem(this.player, { items.push(new _V_.SubtitleMenuItem(this.player, {
label: subtitle[0].Name, label: subtitle[0].Name,
src: subtitle src: subtitle
})); }));
}
}); });
return items; return items;
@ -654,7 +673,7 @@ _V_.SubtitleMenuItem = _V_.MenuItem.extend({
init: function (player, options) { init: function (player, options) {
// Modify options for parent MenuItem class's init. // Modify options for parent MenuItem class's init.
//options.selected = ( options.label === player.options.currentResolution ); options.selected = ( options.label === player.options.currentSubtitle );
this._super(player, options); this._super(player, options);
this.player.addEvent('changeSubtitle', _V_.proxy(this, this.update)); this.player.addEvent('changeSubtitle', _V_.proxy(this, this.update));
@ -668,17 +687,17 @@ _V_.SubtitleMenuItem = _V_.MenuItem.extend({
var current_time = this.player.currentTime(); var current_time = this.player.currentTime();
// Set the button text to the newly chosen quality // Set the button text to the newly chosen subtitle
jQuery(this.player.controlBar.el).find('.vjs-quality-text').html(this.options.label); jQuery(this.player.controlBar.el).find('.vjs-quality-text').html(this.options.label);
// Change the source and make sure we don't start the video over // Change the source and make sure we don't start the video over
var currentSrc = this.player.tag.src; var currentSrc = this.player.tag.src;
var src = parse_src_url(currentSrc); var src = parse_src_url(currentSrc);
var newSrc = "/mediabrowser/" + src.Type + "/" + src.item_id + "/stream." + src.stream + "?audioChannels=" + src.audioChannels + "&audioBitrate=" + src.audioBitrate + var newSrc = "/mediabrowser/" + src.Type + "/" + src.item_id + "/stream." + src.stream + "?audioChannels=" + src.audioChannels + "&audioBitrate=" + src.audioBitrate +
"&videoBitrate=" + src.videoBitrate + "&maxWidth=" + src.maxWidth + "&maxHeight=" + src.maxHeight + "&videoBitrate=" + src.videoBitrate + "&maxWidth=" + src.maxWidth + "&maxHeight=" + src.maxHeight +
"&videoCodec=" + src.videoCodec + "&audioCodec=" + src.audioCodec; "&videoCodec=" + src.videoCodec + "&audioCodec=" + src.audioCodec +
"&AudioStreamIndex=" + src.AudioStreamIndex + "&SubtitleStreamIndex=" + this.options.src[0].index;
if (this.player.duration() == "Infinity") { if (this.player.duration() == "Infinity") {
if (currentSrc.indexOf("StartTimeTicks") >= 0) { if (currentSrc.indexOf("StartTimeTicks") >= 0) {
@ -694,6 +713,7 @@ _V_.SubtitleMenuItem = _V_.MenuItem.extend({
this.play(); this.play();
}); });
} else { } else {
newSrc += "&StartTimeTicks=0";
this.player.src(newSrc).one('loadedmetadata', function () { this.player.src(newSrc).one('loadedmetadata', function () {
this.currentTime(current_time); this.currentTime(current_time);
this.play(); this.play();
@ -733,6 +753,9 @@ _V_.LanguageSelector = _V_.Button.extend({
this._super(player, options); this._super(player, options);
// Save the starting language as a property of the player object
player.options.currentLanguage = this.buttonText;
this.menu = this.createMenu(); this.menu = this.createMenu();
if (this.items.length === 0) { if (this.items.length === 0) {
@ -783,11 +806,12 @@ _V_.LanguageSelector = _V_.Button.extend({
var items = []; var items = [];
this.each(this.Languages, function (language) { this.each(this.Languages, function (language) {
if (language && language.length) {
items.push(new _V_.LanguageMenuItem(this.player, { items.push(new _V_.LanguageMenuItem(this.player, {
label: language[0].Name, label: language[0].Name,
src: language src: language
})); }));
}
}); });
return items; return items;
@ -839,20 +863,26 @@ _V_.LanguageMenuItem = _V_.MenuItem.extend({
init: function (player, options) { init: function (player, options) {
// Modify options for parent MenuItem class's init. // Modify options for parent MenuItem class's init.
//options.selected = ( options.label === player.options.currentResolution ); options.selected = ( options.label === player.options.currentLanguage );
this._super(player, options); this._super(player, options);
this.player.addEvent('changeLanguage', _V_.proxy(this, this.update)); this.player.addEvent('changeLanguage', _V_.proxy(this, this.update));
}, },
onClick: function () { onClick: function () {
// Check that we are changing to a new subtitle (not the one we are already on)
// Check that we are changing to a new language (not the one we are already on)
if (this.options.label === this.player.options.currentLanguage) if (this.options.label === this.player.options.currentLanguage)
return; return;
// Change the source and make sure we don't start the video over
var currentSrc = this.player.tag.src;
var src = parse_src_url(currentSrc);
var newSrc = "/mediabrowser/" + src.Type + "/" + src.item_id + "/stream." + src.stream + "?audioChannels=" + src.audioChannels + "&audioBitrate=" + src.audioBitrate + var newSrc = "/mediabrowser/" + src.Type + "/" + src.item_id + "/stream." + src.stream + "?audioChannels=" + src.audioChannels + "&audioBitrate=" + src.audioBitrate +
"&videoBitrate=" + src.videoBitrate + "&maxWidth=" + src.maxWidth + "&maxHeight=" + src.maxHeight + "&videoBitrate=" + src.videoBitrate + "&maxWidth=" + src.maxWidth + "&maxHeight=" + src.maxHeight +
"&videoCodec=" + src.videoCodec + "&audioCodec=" + src.audioCodec; "&videoCodec=" + src.videoCodec + "&audioCodec=" + src.audioCodec +
"&AudioStreamIndex=" + this.options.src[0].index + "&SubtitleStreamIndex=" + src.SubtitleStreamIndex;
if (this.player.duration() == "Infinity") { if (this.player.duration() == "Infinity") {
if (currentSrc.indexOf("StartTimeTicks") >= 0) { if (currentSrc.indexOf("StartTimeTicks") >= 0) {
@ -868,6 +898,7 @@ _V_.LanguageMenuItem = _V_.MenuItem.extend({
this.play(); this.play();
}); });
} else { } else {
newSrc += "&StartTimeTicks=0";
this.player.src(newSrc).one('loadedmetadata', function () { this.player.src(newSrc).one('loadedmetadata', function () {
this.currentTime(current_time); this.currentTime(current_time);
this.play(); this.play();