mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
fixed switching of audio/subtitle streams
This commit is contained in:
parent
4c4c131147
commit
f0bf153290
2 changed files with 91 additions and 98 deletions
|
@ -2482,7 +2482,7 @@
|
||||||
var name = LibraryBrowser.getPosterViewDisplayName(item, true);
|
var name = LibraryBrowser.getPosterViewDisplayName(item, true);
|
||||||
|
|
||||||
html += '<div style="font-weight:bold;margin-bottom:1em;">';
|
html += '<div style="font-weight:bold;margin-bottom:1em;">';
|
||||||
var logoHeight = isSmallItem ? 20 : 24;
|
var logoHeight = isSmallItem ? 20 : 26;
|
||||||
var maxLogoWidth = isPortrait ? 100 : 200;
|
var maxLogoWidth = isPortrait ? 100 : 200;
|
||||||
var imgUrl;
|
var imgUrl;
|
||||||
|
|
||||||
|
@ -2556,7 +2556,7 @@
|
||||||
buttonCount++;
|
buttonCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUser.Configuration.IsAdministrator && item.Type != "Recording") {
|
if (currentUser.Configuration.IsAdministrator && item.Type != "Recording" && item.Type != "Program") {
|
||||||
html += '<button type="button" data-mini="true" data-inline="true" data-icon="edit" data-iconpos="notext" title="Edit" onclick="Dashboard.navigate(\'edititemmetadata.html?id=' + item.Id + '\');return false;" style="' + buttonMargin + '">Edit</button>';
|
html += '<button type="button" data-mini="true" data-inline="true" data-icon="edit" data-iconpos="notext" title="Edit" onclick="Dashboard.navigate(\'edititemmetadata.html?id=' + item.Id + '\');return false;" style="' + buttonMargin + '">Edit</button>';
|
||||||
buttonCount++;
|
buttonCount++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var testableAudioElement = document.createElement('audio');
|
|
||||||
var testableVideoElement = document.createElement('video');
|
var testableVideoElement = document.createElement('video');
|
||||||
var currentMediaElement;
|
var currentMediaElement;
|
||||||
var currentProgressInterval;
|
var currentProgressInterval;
|
||||||
|
@ -221,31 +220,28 @@
|
||||||
if (params.SubtitleStreamIndex != null) {
|
if (params.SubtitleStreamIndex != null) {
|
||||||
currentSrc = replaceQueryString(currentSrc, 'SubtitleStreamIndex', params.SubtitleStreamIndex);
|
currentSrc = replaceQueryString(currentSrc, 'SubtitleStreamIndex', params.SubtitleStreamIndex);
|
||||||
}
|
}
|
||||||
if (params.MaxWidth != null) {
|
|
||||||
currentSrc = replaceQueryString(currentSrc, 'MaxWidth', params.MaxWidth);
|
|
||||||
}
|
|
||||||
if (params.VideoBitrate != null) {
|
|
||||||
currentSrc = replaceQueryString(currentSrc, 'VideoBitrate', params.VideoBitrate);
|
|
||||||
}
|
|
||||||
if (params.AudioBitrate != null) {
|
|
||||||
currentSrc = replaceQueryString(currentSrc, 'AudioBitrate', params.AudioBitrate);
|
|
||||||
}
|
|
||||||
if (params.AudioCodec) {
|
|
||||||
currentSrc = replaceQueryString(currentSrc, 'AudioCodec', params.AudioCodec);
|
|
||||||
}
|
|
||||||
if (params.VideoCodec) {
|
|
||||||
currentSrc = replaceQueryString(currentSrc, 'VideoCodec', params.VideoCodec);
|
|
||||||
}
|
|
||||||
if (params.Static != null) {
|
|
||||||
|
|
||||||
currentSrc = replaceQueryString(currentSrc, 'Static', params.Static);
|
var maxWidth = params.MaxWidth || getParameterByName('MaxWidth', currentSrc);
|
||||||
|
var audioStreamIndex = params.AudioStreamIndex == null ? getParameterByName('AudioStreamIndex', currentSrc) : params.AudioStreamIndex;
|
||||||
|
var subtitleStreamIndex = params.SubtitleStreamIndex == null ? getParameterByName('SubtitleStreamIndex', currentSrc) : params.SubtitleStreamIndex;
|
||||||
|
var videoBitrate = parseInt(getParameterByName('VideoBitrate', currentSrc) || '0');
|
||||||
|
var audioBitrate = parseInt(getParameterByName('AudioBitrate', currentSrc) || '0');
|
||||||
|
var bitrate = params.Bitrate || (videoBitrate + audioBitrate);
|
||||||
|
|
||||||
if (params.Static == 'true') {
|
var transcodingExtension = getTranscodingExtension();
|
||||||
|
|
||||||
|
var finalParams = getFinalVideoParams(currentItem, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension);
|
||||||
|
currentSrc = replaceQueryString(currentSrc, 'MaxWidth', finalParams.maxWidth);
|
||||||
|
currentSrc = replaceQueryString(currentSrc, 'VideoBitrate', finalParams.videoBitrate);
|
||||||
|
currentSrc = replaceQueryString(currentSrc, 'AudioBitrate', finalParams.audioBitrate);
|
||||||
|
|
||||||
|
if (finalParams.isStatic) {
|
||||||
currentSrc = currentSrc.replace('.webm', '.mp4').replace('.m3u8', '.mp4');
|
currentSrc = currentSrc.replace('.webm', '.mp4').replace('.m3u8', '.mp4');
|
||||||
} else {
|
} else {
|
||||||
currentSrc = currentSrc.replace('.mp4', getTranscodingExtension());
|
currentSrc = currentSrc.replace('.mp4', getTranscodingExtension());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
currentSrc = replaceQueryString(currentSrc, 'Static', finalParams.isStatic);
|
||||||
|
|
||||||
clearProgressInterval();
|
clearProgressInterval();
|
||||||
|
|
||||||
|
@ -314,7 +310,7 @@
|
||||||
if (!$(this).hasClass('selectedMediaFlyoutOption')) {
|
if (!$(this).hasClass('selectedMediaFlyoutOption')) {
|
||||||
var index = parseInt(this.getAttribute('data-index'));
|
var index = parseInt(this.getAttribute('data-index'));
|
||||||
|
|
||||||
changeStream(getCurrentTicks(), { AudioStreamIndex: index, Static: false });
|
changeStream(getCurrentTicks(), { AudioStreamIndex: index });
|
||||||
}
|
}
|
||||||
|
|
||||||
hideFlyout($('#audioTracksFlyout'));
|
hideFlyout($('#audioTracksFlyout'));
|
||||||
|
@ -325,7 +321,7 @@
|
||||||
if (!$(this).hasClass('selectedMediaFlyoutOption')) {
|
if (!$(this).hasClass('selectedMediaFlyoutOption')) {
|
||||||
var index = parseInt(this.getAttribute('data-index'));
|
var index = parseInt(this.getAttribute('data-index'));
|
||||||
|
|
||||||
changeStream(getCurrentTicks(), { SubtitleStreamIndex: index, Static: false });
|
changeStream(getCurrentTicks(), { SubtitleStreamIndex: index });
|
||||||
}
|
}
|
||||||
|
|
||||||
hideFlyout($('#subtitleFlyout'));
|
hideFlyout($('#subtitleFlyout'));
|
||||||
|
@ -336,23 +332,14 @@
|
||||||
if (!$(this).hasClass('selectedMediaFlyoutOption')) {
|
if (!$(this).hasClass('selectedMediaFlyoutOption')) {
|
||||||
|
|
||||||
var maxWidth = parseInt(this.getAttribute('data-maxwidth'));
|
var maxWidth = parseInt(this.getAttribute('data-maxwidth'));
|
||||||
var videoBitrate = parseInt(this.getAttribute('data-videobitrate'));
|
var bitrate = parseInt(this.getAttribute('data-bitrate'));
|
||||||
var audioBitrate = parseInt(this.getAttribute('data-audiobitrate'));
|
|
||||||
|
|
||||||
var audioCodec = this.getAttribute('data-audiocodec');
|
localStorage.setItem('preferredVideoBitrate', bitrate);
|
||||||
var videoCodec = this.getAttribute('data-videocodec');
|
|
||||||
var isStatic = this.getAttribute('data-static');
|
|
||||||
|
|
||||||
localStorage.setItem('preferredVideoBitrate', videoBitrate + audioBitrate);
|
|
||||||
|
|
||||||
changeStream(getCurrentTicks(), {
|
changeStream(getCurrentTicks(), {
|
||||||
|
|
||||||
MaxWidth: maxWidth,
|
MaxWidth: maxWidth,
|
||||||
VideoBitrate: videoBitrate,
|
Bitrate: bitrate
|
||||||
AudioBitrate: audioBitrate,
|
|
||||||
Static: isStatic,
|
|
||||||
AudioCodec: audioCodec,
|
|
||||||
VideoCodec: videoCodec
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,20 +529,38 @@
|
||||||
return audioElement[0];
|
return audioElement[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
function canPlayVideoDirect(item, videoStream) {
|
function canPlayVideoDirect(item, videoStream, audioStream, subtitleStream, maxWidth, bitrate) {
|
||||||
|
|
||||||
if (item.VideoType != "VideoFile" || item.LocationType != "FileSystem") {
|
if (item.VideoType != "VideoFile" || item.LocationType != "FileSystem") {
|
||||||
|
console.log('Transcoding because the content is not a video file');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((videoStream.Codec || '').toLowerCase().indexOf('h264') == -1) {
|
if ((videoStream.Codec || '').toLowerCase().indexOf('h264') == -1) {
|
||||||
|
console.log('Transcoding because the content is not h264');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var audioStreams = (item.MediaStreams || []).filter(function (stream) {
|
if (audioStream && !canPlayAudioStreamDirect(audioStream)) {
|
||||||
return stream.Type == "Audio";
|
console.log('Transcoding because the audio cant be played directly.');
|
||||||
});
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (audioStreams.length && !audioStreams.filter(canPlayAudioStreamDirect).length) {
|
if (subtitleStream) {
|
||||||
|
console.log('Transcoding because subtitles are required');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!videoStream.Width || videoStream.Width > maxWidth) {
|
||||||
|
console.log('Transcoding because resolution is too high');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var videoBitrate = videoStream.BitRate || 0;
|
||||||
|
var audioBitrate = audioStream ? audioStream.BitRate || 0 : null;
|
||||||
|
|
||||||
|
if ((videoBitrate + audioBitrate) > bitrate) {
|
||||||
|
console.log('Transcoding because bitrate is too high');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,9 +576,11 @@
|
||||||
function canPlayAudioStreamDirect(audioStream) {
|
function canPlayAudioStreamDirect(audioStream) {
|
||||||
|
|
||||||
var audioCodec = (audioStream.Codec || '').toLowerCase().replace('-', '');
|
var audioCodec = (audioStream.Codec || '').toLowerCase().replace('-', '');
|
||||||
|
|
||||||
if (audioCodec.indexOf('aac') == -1 &&
|
if (audioCodec.indexOf('aac') == -1 &&
|
||||||
audioCodec.indexOf('mp3') == -1 &&
|
audioCodec.indexOf('mp3') == -1 &&
|
||||||
audioCodec.indexOf('mpeg') == -1) {
|
audioCodec.indexOf('mpeg') == -1) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,19 +596,12 @@
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVideoQualityOptions(item, audioStreamIndex, transcodeExtension) {
|
function getVideoQualityOptions(item) {
|
||||||
|
|
||||||
var videoStream = (item.MediaStreams || []).filter(function (stream) {
|
var videoStream = (item.MediaStreams || []).filter(function (stream) {
|
||||||
return stream.Type == "Video";
|
return stream.Type == "Video";
|
||||||
})[0];
|
})[0];
|
||||||
|
|
||||||
var audioStreams = (item.MediaStreams || []).filter(function (stream) {
|
|
||||||
return stream.Type == "Audio";
|
|
||||||
});
|
|
||||||
|
|
||||||
var audioStream = audioStreamIndex == null ? null : audioStreams[audioStreamIndex];
|
|
||||||
|
|
||||||
var canPlayDirect = canPlayVideoDirect(item, videoStream, audioStream);
|
|
||||||
var bitrateSetting = parseInt(localStorage.getItem('preferredVideoBitrate') || '') || 1500000;
|
var bitrateSetting = parseInt(localStorage.getItem('preferredVideoBitrate') || '') || 1500000;
|
||||||
|
|
||||||
var maxAllowedWidth = Math.max(screen.height, screen.width);
|
var maxAllowedWidth = Math.max(screen.height, screen.width);
|
||||||
|
@ -614,13 +614,6 @@
|
||||||
maxAllowedWidth = videoStream.Width;
|
maxAllowedWidth = videoStream.Width;
|
||||||
}
|
}
|
||||||
|
|
||||||
var canPlayVideoCodecDirect = (videoStream ? videoStream.Codec : '').toLowerCase().indexOf('h264') != -1;
|
|
||||||
var canPlayAudioDirect = audioStream ? canPlayAudioStreamDirect(audioStream) : false;
|
|
||||||
|
|
||||||
var videoBitrate = videoStream ? videoStream.BitRate : null;
|
|
||||||
var audioBitrate = audioStream ? audioStream.BitRate : null;
|
|
||||||
var totalBitrate = (videoBitrate || 0) + (audioBitrate || 0);
|
|
||||||
|
|
||||||
// Some 1080- videos are reported as 1912?
|
// Some 1080- videos are reported as 1912?
|
||||||
if (maxAllowedWidth >= 1910) {
|
if (maxAllowedWidth >= 1910) {
|
||||||
options.push({ name: '1080p - 10Mbps', maxWidth: 1920, bitrate: 10000000 });
|
options.push({ name: '1080p - 10Mbps', maxWidth: 1920, bitrate: 10000000 });
|
||||||
|
@ -651,8 +644,6 @@
|
||||||
options.push({ name: '360p', maxWidth: 640, bitrate: 400000 });
|
options.push({ name: '360p', maxWidth: 640, bitrate: 400000 });
|
||||||
options.push({ name: '240p', maxWidth: 426, bitrate: 320000 });
|
options.push({ name: '240p', maxWidth: 426, bitrate: 320000 });
|
||||||
|
|
||||||
var videoWidth = videoStream ? videoStream.Width : null;
|
|
||||||
|
|
||||||
var i, length, option;
|
var i, length, option;
|
||||||
var selectedIndex = -1;
|
var selectedIndex = -1;
|
||||||
for (i = 0, length = options.length; i < length; i++) {
|
for (i = 0, length = options.length; i < length; i++) {
|
||||||
|
@ -662,32 +653,6 @@
|
||||||
if (selectedIndex == -1 && option.bitrate <= bitrateSetting) {
|
if (selectedIndex == -1 && option.bitrate <= bitrateSetting) {
|
||||||
selectedIndex = i;
|
selectedIndex = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
option.audioBitrate = option.bitrate >= 700000 ? 128000 : 64000;
|
|
||||||
|
|
||||||
if (canPlayVideoCodecDirect &&
|
|
||||||
totalBitrate &&
|
|
||||||
option.bitrate >= totalBitrate &&
|
|
||||||
videoWidth &&
|
|
||||||
option.maxWidth >= videoWidth) {
|
|
||||||
|
|
||||||
if (canPlayDirect) {
|
|
||||||
|
|
||||||
option.isStatic = true;
|
|
||||||
option.videoCodec = 'copy';
|
|
||||||
option.audioCodec = 'copy';
|
|
||||||
}
|
|
||||||
//else if (canPlayVideoCodecDirect && transcodeExtension == '.m3u8') {
|
|
||||||
// option.videoCodec = 'copy';
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
option.isStatic = option.isStatic || false;
|
|
||||||
|
|
||||||
option.videoCodec = option.videoCodec || (transcodeExtension == '.webm' ? 'vpx' : 'h264');
|
|
||||||
option.audioCodec = option.audioCodec || (transcodeExtension == '.webm' ? 'Vorbis' : 'aac');
|
|
||||||
|
|
||||||
option.videoBitrate = option.bitrate - option.audioBitrate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedIndex == -1) {
|
if (selectedIndex == -1) {
|
||||||
|
@ -697,13 +662,38 @@
|
||||||
|
|
||||||
options[selectedIndex].selected = true;
|
options[selectedIndex].selected = true;
|
||||||
|
|
||||||
var firstOption = options[0];
|
return options;
|
||||||
|
|
||||||
if (firstOption.isStatic) {
|
|
||||||
firstOption.name = 'Direct';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return options;
|
function getFinalVideoParams(item, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension) {
|
||||||
|
|
||||||
|
var videoStream = (item.MediaStreams || []).filter(function (stream) {
|
||||||
|
return stream.Type === "Video";
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
var audioStream = (item.MediaStreams || []).filter(function (stream) {
|
||||||
|
return stream.Index === audioStreamIndex;
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
var subtitleStream = (item.MediaStreams || []).filter(function (stream) {
|
||||||
|
return stream.Index === subtitleStreamIndex ;
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
var canPlayDirect = canPlayVideoDirect(item, videoStream, audioStream, subtitleStream, maxWidth, bitrate);
|
||||||
|
|
||||||
|
var audioBitrate = bitrate >= 700000 ? 128000 : 64000;
|
||||||
|
|
||||||
|
var videoBitrate = bitrate - audioBitrate;
|
||||||
|
|
||||||
|
return {
|
||||||
|
|
||||||
|
isStatic: canPlayDirect,
|
||||||
|
maxWidth: maxWidth,
|
||||||
|
audioCodec: transcodingExtension == '.webm' ? 'vorbis' : 'aac',
|
||||||
|
videoCodec: transcodingExtension == '.webm' ? 'vpx' : 'h264',
|
||||||
|
audioBitrate: audioBitrate,
|
||||||
|
videoBitrate: videoBitrate
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function playVideo(item, startPosition, user) {
|
function playVideo(item, startPosition, user) {
|
||||||
|
@ -720,17 +710,20 @@
|
||||||
Static: false
|
Static: false
|
||||||
};
|
};
|
||||||
|
|
||||||
var mp4Quality = getVideoQualityOptions(item, baseParams.AudioStreamIndex, '.mp4').filter(function (opt) {
|
var mp4Quality = getVideoQualityOptions(item).filter(function (opt) {
|
||||||
return opt.selected;
|
return opt.selected;
|
||||||
})[0];
|
})[0];
|
||||||
|
mp4Quality = $.extend(mp4Quality, getFinalVideoParams(item, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4'));
|
||||||
|
|
||||||
var webmQuality = getVideoQualityOptions(item, baseParams.AudioStreamIndex, '.webm').filter(function (opt) {
|
var webmQuality = getVideoQualityOptions(item).filter(function (opt) {
|
||||||
return opt.selected;
|
return opt.selected;
|
||||||
})[0];
|
})[0];
|
||||||
|
webmQuality = $.extend(webmQuality, getFinalVideoParams(item, webmQuality.maxWidth, webmQuality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.webm'));
|
||||||
|
|
||||||
var m3U8Quality = getVideoQualityOptions(item, baseParams.AudioStreamIndex, '.m3u8').filter(function (opt) {
|
var m3U8Quality = getVideoQualityOptions(item).filter(function (opt) {
|
||||||
return opt.selected;
|
return opt.selected;
|
||||||
})[0];
|
})[0];
|
||||||
|
m3U8Quality = $.extend(m3U8Quality, getFinalVideoParams(item, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4'));
|
||||||
|
|
||||||
// Webm must be ahead of mp4 due to the issue of mp4 playing too fast in chrome
|
// Webm must be ahead of mp4 due to the issue of mp4 playing too fast in chrome
|
||||||
var prioritizeWebmOverH264 = $.browser.chrome || $.browser.msie;
|
var prioritizeWebmOverH264 = $.browser.chrome || $.browser.msie;
|
||||||
|
@ -1863,7 +1856,7 @@
|
||||||
cssClass += " selectedMediaFlyoutOption";
|
cssClass += " selectedMediaFlyoutOption";
|
||||||
}
|
}
|
||||||
|
|
||||||
html += '<div data-static="' + option.isStatic + '" data-videocodec="' + option.videoCodec + '" data-audiocodec="' + option.audioCodec + '" data-maxwidth="' + option.maxWidth + '" data-videobitrate="' + option.videoBitrate + '" data-audiobitrate="' + option.audioBitrate + '" class="' + cssClass + '">';
|
html += '<div data-maxwidth="' + option.maxWidth + '" data-bitrate="' + option.bitrate + '" class="' + cssClass + '">';
|
||||||
|
|
||||||
html += '<div class="mediaFlyoutOptionContent">';
|
html += '<div class="mediaFlyoutOptionContent">';
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue