mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
use server to build initial stream url's
This commit is contained in:
parent
c64474f046
commit
1fc390dc50
3 changed files with 375 additions and 295 deletions
|
@ -428,14 +428,12 @@
|
|||
|
||||
if (!$(this).hasClass('selectedMediaPopupOption')) {
|
||||
|
||||
var maxWidth = parseInt(this.getAttribute('data-maxwidth'));
|
||||
var bitrate = parseInt(this.getAttribute('data-bitrate'));
|
||||
|
||||
AppSettings.maxStreamingBitrate(bitrate);
|
||||
|
||||
self.changeStream(self.getCurrentTicks(), {
|
||||
|
||||
MaxWidth: maxWidth,
|
||||
Bitrate: bitrate
|
||||
});
|
||||
}
|
||||
|
@ -796,7 +794,12 @@
|
|||
var currentSrc = self.getCurrentSrc(self.currentMediaElement).toLowerCase();
|
||||
var isStatic = currentSrc.indexOf('static=true') != -1;
|
||||
|
||||
var options = getVideoQualityOptions(self.currentMediaSource.MediaStreams);
|
||||
var videoStream = self.currentMediaSource.MediaStreams.filter(function (stream) {
|
||||
return stream.Type == "Video";
|
||||
})[0];
|
||||
var videoWidth = videoStream ? videoStream.Width : null;
|
||||
|
||||
var options = self.getVideoQualityOptions(videoWidth);
|
||||
|
||||
if (isStatic) {
|
||||
options[0].name = "Direct";
|
||||
|
@ -819,7 +822,7 @@
|
|||
cssClass += ' selectedMediaPopupOption';
|
||||
}
|
||||
|
||||
var optionHtml = '<li><a data-maxwidth="' + option.maxWidth + '" data-bitrate="' + option.bitrate + '" class="' + cssClass + '" href="#">';
|
||||
var optionHtml = '<li><a data-bitrate="' + option.bitrate + '" class="' + cssClass + '" href="#">';
|
||||
|
||||
optionHtml += '<p style="margin:0;">';
|
||||
|
||||
|
@ -845,85 +848,6 @@
|
|||
return html;
|
||||
}
|
||||
|
||||
function getVideoQualityOptions(mediaStreams) {
|
||||
|
||||
var videoStream = mediaStreams.filter(function (stream) {
|
||||
return stream.Type == "Video";
|
||||
})[0];
|
||||
|
||||
var bitrateSetting = AppSettings.maxStreamingBitrate();
|
||||
|
||||
var maxAllowedWidth = self.getMaxPlayableWidth();
|
||||
|
||||
var options = [];
|
||||
|
||||
// We have media info
|
||||
if (videoStream && videoStream.Width) {
|
||||
|
||||
maxAllowedWidth = videoStream.Width;
|
||||
}
|
||||
|
||||
// Some 1080- videos are reported as 1912?
|
||||
if (maxAllowedWidth >= 1900) {
|
||||
options.push({ name: '1080p - 30Mbps', maxWidth: 1920, bitrate: 30000000 });
|
||||
options.push({ name: '1080p - 25Mbps', maxWidth: 1920, bitrate: 25000000 });
|
||||
options.push({ name: '1080p - 20Mbps', maxWidth: 1920, bitrate: 20000000 });
|
||||
options.push({ name: '1080p - 15Mbps', maxWidth: 1920, bitrate: 15000000 });
|
||||
options.push({ name: '1080p - 10Mbps', maxWidth: 1920, bitrate: 10000000 });
|
||||
options.push({ name: '1080p - 8Mbps', maxWidth: 1920, bitrate: 8000000 });
|
||||
options.push({ name: '1080p - 6Mbps', maxWidth: 1920, bitrate: 6000000 });
|
||||
options.push({ name: '1080p - 5Mbps', maxWidth: 1920, bitrate: 5000000 });
|
||||
}
|
||||
else if (maxAllowedWidth >= 1260) {
|
||||
options.push({ name: '720p - 10Mbps', maxWidth: 1280, bitrate: 10000000 });
|
||||
options.push({ name: '720p - 8Mbps', maxWidth: 1280, bitrate: 8000000 });
|
||||
options.push({ name: '720p - 6Mbps', maxWidth: 1280, bitrate: 6000000 });
|
||||
options.push({ name: '720p - 5Mbps', maxWidth: 1280, bitrate: 5000000 });
|
||||
}
|
||||
else if (maxAllowedWidth >= 460) {
|
||||
options.push({ name: '480p - 4Mbps', maxWidth: 720, bitrate: 4000000 });
|
||||
options.push({ name: '480p - 3Mbps', maxWidth: 720, bitrate: 3000000 });
|
||||
options.push({ name: '480p - 2.5Mbps', maxWidth: 720, bitrate: 2500000 });
|
||||
options.push({ name: '480p - 2Mbps', maxWidth: 720, bitrate: 2000000 });
|
||||
options.push({ name: '480p - 1.5Mbps', maxWidth: 720, bitrate: 1500000 });
|
||||
}
|
||||
|
||||
if (maxAllowedWidth >= 1260) {
|
||||
options.push({ name: '720p - 4Mbps', maxWidth: 1280, bitrate: 4000000 });
|
||||
options.push({ name: '720p - 3Mbps', maxWidth: 1280, bitrate: 3000000 });
|
||||
options.push({ name: '720p - 2Mbps', maxWidth: 1280, bitrate: 2000000 });
|
||||
|
||||
// The extra 1 is because they're keyed off the bitrate value
|
||||
options.push({ name: '720p - 1Mbps', maxWidth: 1280, bitrate: 1000001 });
|
||||
}
|
||||
|
||||
options.push({ name: '480p - 1.0Mbps', maxWidth: 720, bitrate: 1000000 });
|
||||
options.push({ name: '480p - 720kbps', maxWidth: 720, bitrate: 720000 });
|
||||
options.push({ name: '480p - 420kbps', maxWidth: 720, bitrate: 420000 });
|
||||
options.push({ name: '360p', maxWidth: 640, bitrate: 400000 });
|
||||
options.push({ name: '240p', maxWidth: 426, bitrate: 320000 });
|
||||
|
||||
var i, length, option;
|
||||
var selectedIndex = -1;
|
||||
for (i = 0, length = options.length; i < length; i++) {
|
||||
|
||||
option = options[i];
|
||||
|
||||
if (selectedIndex == -1 && option.bitrate <= bitrateSetting) {
|
||||
selectedIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedIndex == -1) {
|
||||
|
||||
selectedIndex = options.length - 1;
|
||||
}
|
||||
|
||||
options[selectedIndex].selected = true;
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
function bindEventsForPlayback() {
|
||||
|
||||
var hideElementsOnIdle = !$.browser.mobile;
|
||||
|
@ -1007,101 +931,71 @@
|
|||
}
|
||||
};
|
||||
|
||||
self.playVideo = function (playbackInfo, item, mediaSource, startPosition) {
|
||||
self.playVideo = function (deviceProfile, playbackInfo, item, mediaSource, startPosition) {
|
||||
|
||||
var videoUrl;
|
||||
var contentType;
|
||||
|
||||
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 = {
|
||||
audioChannels: 2,
|
||||
StartTimeTicks: startPosition,
|
||||
AudioStreamIndex: mediaSource.DefaultAudioStreamIndex,
|
||||
deviceId: ApiClient.deviceId(),
|
||||
Static: false,
|
||||
mediaSourceId: mediaSource.Id,
|
||||
api_key: ApiClient.accessToken(),
|
||||
StreamId: playbackInfo.StreamId
|
||||
};
|
||||
|
||||
if (selectedSubtitleStream && (!self.supportsSubtitleStreamExternally(selectedSubtitleStream) || !self.supportsTextTracks())) {
|
||||
baseParams.SubtitleStreamIndex = mediaSource.DefaultSubtitleStreamIndex;
|
||||
}
|
||||
|
||||
var mp4Quality = getVideoQualityOptions(mediaStreams).filter(function (opt) {
|
||||
return opt.selected;
|
||||
})[0];
|
||||
mp4Quality = $.extend(mp4Quality, self.getFinalVideoParams(mediaSource, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4'));
|
||||
|
||||
var webmQuality = getVideoQualityOptions(mediaStreams).filter(function (opt) {
|
||||
return opt.selected;
|
||||
})[0];
|
||||
webmQuality = $.extend(webmQuality, self.getFinalVideoParams(mediaSource, webmQuality.maxWidth, webmQuality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.webm'));
|
||||
|
||||
var m3U8Quality = getVideoQualityOptions(mediaStreams).filter(function (opt) {
|
||||
return opt.selected;
|
||||
})[0];
|
||||
m3U8Quality = $.extend(m3U8Quality, self.getFinalVideoParams(mediaSource, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4'));
|
||||
|
||||
var isStatic = mp4Quality.isStatic;
|
||||
|
||||
self.startTimeTicksOffset = isStatic ? 0 : startPosition || 0;
|
||||
|
||||
var startPositionInSeekParam = startPosition ? (startPosition / 10000000) : 0;
|
||||
var seekParam = startPositionInSeekParam ? '#t=' + startPositionInSeekParam : '';
|
||||
|
||||
var mp4VideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.mp4', $.extend({}, baseParams, {
|
||||
Static: isStatic,
|
||||
maxWidth: mp4Quality.maxWidth,
|
||||
videoBitrate: mp4Quality.videoBitrate,
|
||||
audioBitrate: mp4Quality.audioBitrate,
|
||||
VideoCodec: mp4Quality.videoCodec,
|
||||
AudioCodec: mp4Quality.audioCodec,
|
||||
profile: 'high',
|
||||
//EnableAutoStreamCopy: false,
|
||||
level: '41'
|
||||
}));
|
||||
|
||||
if (isStatic && mediaSource.Protocol == 'Http' && !mediaSource.RequiredHttpHeaders.length) {
|
||||
mp4VideoUrl = mediaSource.Path;
|
||||
}
|
||||
|
||||
if (isStatic) {
|
||||
mp4VideoUrl += seekParam;
|
||||
if (mediaSource.enableDirectPlay) {
|
||||
videoUrl = mediaSource.Path;
|
||||
self.startTimeTicksOffset = 0;
|
||||
contentType = 'video/' + mediaSource.Container;
|
||||
} else {
|
||||
mp4VideoUrl += "&StreamId=" + new Date().getTime();
|
||||
|
||||
var selectedSubtitleStream = subtitleStreams.filter(function (s) {
|
||||
return s.Index == mediaSource.DefaultSubtitleStreamIndex;
|
||||
|
||||
})[0];
|
||||
|
||||
var transcodingParams = {
|
||||
audioChannels: 2,
|
||||
StartTimeTicks: startPosition,
|
||||
AudioStreamIndex: mediaSource.DefaultAudioStreamIndex,
|
||||
deviceId: ApiClient.deviceId(),
|
||||
mediaSourceId: mediaSource.Id,
|
||||
api_key: ApiClient.accessToken(),
|
||||
StreamId: playbackInfo.StreamId,
|
||||
ClientTime: new Date().getTime()
|
||||
};
|
||||
|
||||
if (selectedSubtitleStream && (!self.supportsSubtitleStreamExternally(selectedSubtitleStream) || !self.supportsTextTracks())) {
|
||||
transcodingParams.SubtitleStreamIndex = mediaSource.DefaultSubtitleStreamIndex;
|
||||
}
|
||||
|
||||
self.startTimeTicksOffset = mediaSource.SupportsDirectStream ? 0 : startPosition || 0;
|
||||
var startPositionInSeekParam = startPosition ? (startPosition / 10000000) : 0;
|
||||
var seekParam = startPositionInSeekParam ? '#t=' + startPositionInSeekParam : '';
|
||||
|
||||
if (mediaSource.SupportsDirectStream) {
|
||||
|
||||
videoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.' + mediaSource.Container, {
|
||||
Static: true,
|
||||
mediaSourceId: mediaSource.Id,
|
||||
api_key: ApiClient.accessToken()
|
||||
});
|
||||
videoUrl += seekParam;
|
||||
contentType = 'video/' + mediaSource.Container;
|
||||
|
||||
} else {
|
||||
videoUrl = ApiClient.getUrl(mediaSource.TranscodingUrl);
|
||||
|
||||
if (mediaSource.TranscodingSubProtocol == 'hls') {
|
||||
|
||||
videoUrl += seekParam;
|
||||
contentType = 'application/x-mpegURL';
|
||||
}
|
||||
else {
|
||||
|
||||
contentType = 'video/' + mediaSource.TranscodingContainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var webmVideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.webm', $.extend({}, baseParams, {
|
||||
VideoCodec: 'vpx',
|
||||
AudioCodec: 'Vorbis',
|
||||
maxWidth: webmQuality.maxWidth,
|
||||
videoBitrate: webmQuality.videoBitrate,
|
||||
audioBitrate: webmQuality.audioBitrate,
|
||||
EnableAutoStreamCopy: false,
|
||||
StreamId: new Date().getTime()
|
||||
}));
|
||||
|
||||
var hlsVideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/master.m3u8', $.extend({}, baseParams, {
|
||||
maxWidth: m3U8Quality.maxWidth,
|
||||
videoBitrate: m3U8Quality.videoBitrate,
|
||||
audioBitrate: m3U8Quality.audioBitrate,
|
||||
VideoCodec: m3U8Quality.videoCodec,
|
||||
AudioCodec: m3U8Quality.audioCodec,
|
||||
profile: 'high',
|
||||
level: '41',
|
||||
StartTimeTicks: 0,
|
||||
StreamId: new Date().getTime()
|
||||
|
||||
})) + seekParam;
|
||||
|
||||
//======================================================================================>
|
||||
|
||||
// Create video player
|
||||
|
@ -1118,27 +1012,7 @@
|
|||
html += '<video class="itemVideo" id="itemVideo" preload="metadata" autoplay>';
|
||||
}
|
||||
|
||||
if (!isStatic) {
|
||||
// HLS must be at the top for safari
|
||||
html += '<source type="application/x-mpegURL" src="' + hlsVideoUrl + '" />';
|
||||
}
|
||||
|
||||
var mp4BeforeWebm = self.getVideoTranscodingExtension() != '.webm';
|
||||
|
||||
if (mp4BeforeWebm) {
|
||||
html += '<source type="video/mp4" src="' + mp4VideoUrl + '" />';
|
||||
}
|
||||
|
||||
// Have to put webm ahead of mp4 because it will play in fast forward in chrome
|
||||
// And firefox doesn't like fragmented mp4
|
||||
if (!isStatic) {
|
||||
|
||||
html += '<source type="video/webm" src="' + webmVideoUrl + '" />';
|
||||
}
|
||||
|
||||
if (!mp4BeforeWebm) {
|
||||
html += '<source type="video/mp4" src="' + mp4VideoUrl + '" />';
|
||||
}
|
||||
html += '<source type="' + contentType + '" src="' + videoUrl + '" />';
|
||||
|
||||
if (self.supportsTextTracks()) {
|
||||
var textStreams = subtitleStreams.filter(function (s) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue