mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
use shared device profile
This commit is contained in:
parent
120e92760d
commit
294ad10bc2
1 changed files with 169 additions and 411 deletions
|
@ -44,72 +44,15 @@
|
||||||
return targets;
|
return targets;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.getDeviceProfile = function (maxHeight) {
|
function updateDeviceProfileForAndroid(profile) {
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
// Just here as an easy escape out, if ever needed
|
||||||
|
var enableVlcVideo = true;
|
||||||
|
var enableVlcAudio = true;
|
||||||
|
|
||||||
require(['qualityoptions'], function (qualityoptions) {
|
profile.CodecProfiles = [];
|
||||||
|
|
||||||
var bitrateSetting = AppSettings.maxStreamingBitrate();
|
if (enableVlcVideo) {
|
||||||
|
|
||||||
if (!maxHeight) {
|
|
||||||
maxHeight = qualityoptions.getVideoQualityOptions(bitrateSetting).filter(function (q) {
|
|
||||||
return q.selected;
|
|
||||||
})[0].maxHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
var isVlc = AppInfo.isNativeApp && browserInfo.android;
|
|
||||||
|
|
||||||
var supportedFormats = getSupportedFormats();
|
|
||||||
|
|
||||||
var canPlayWebm = supportedFormats.indexOf('webm') != -1;
|
|
||||||
var canPlayAc3 = supportedFormats.indexOf('ac3') != -1;
|
|
||||||
var canPlayAac = supportedFormats.indexOf('aac') != -1;
|
|
||||||
var canPlayMp3 = supportedFormats.indexOf('mp3') != -1;
|
|
||||||
var canPlayMkv = supportedFormats.indexOf('mkv') != -1;
|
|
||||||
|
|
||||||
var profile = {};
|
|
||||||
|
|
||||||
profile.MaxStreamingBitrate = bitrateSetting;
|
|
||||||
profile.MaxStaticBitrate = 8000000;
|
|
||||||
profile.MusicStreamingTranscodingBitrate = Math.min(bitrateSetting, 192000);
|
|
||||||
|
|
||||||
profile.DirectPlayProfiles = [];
|
|
||||||
|
|
||||||
var videoAudioCodecs = [];
|
|
||||||
// Only put mp3 first if mkv support is there
|
|
||||||
// Otherwise with HLS and mp3 audio we're seeing firefox and chrome not play it with HLS
|
|
||||||
if (canPlayMkv) {
|
|
||||||
if (canPlayMp3) {
|
|
||||||
videoAudioCodecs.push('mp3');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (canPlayAac) {
|
|
||||||
videoAudioCodecs.push('aac');
|
|
||||||
}
|
|
||||||
if (!canPlayMkv) {
|
|
||||||
if (canPlayMp3) {
|
|
||||||
videoAudioCodecs.push('mp3');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (supportedFormats.indexOf('h264') != -1) {
|
|
||||||
profile.DirectPlayProfiles.push({
|
|
||||||
Container: 'mp4,m4v',
|
|
||||||
Type: 'Video',
|
|
||||||
VideoCodec: 'h264',
|
|
||||||
AudioCodec: videoAudioCodecs.join(',')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canPlayMkv) {
|
|
||||||
profile.DirectPlayProfiles.push({
|
|
||||||
Container: 'mkv,mov',
|
|
||||||
Type: 'Video',
|
|
||||||
VideoCodec: 'h264',
|
|
||||||
AudioCodec: videoAudioCodecs.join(',')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var directPlayVideoContainers = AppInfo.directPlayVideoContainers;
|
var directPlayVideoContainers = AppInfo.directPlayVideoContainers;
|
||||||
|
|
||||||
|
@ -120,278 +63,7 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
['opus', 'mp3', 'aac', 'webma'].forEach(function (audioFormat) {
|
|
||||||
|
|
||||||
if (supportedFormats.indexOf(audioFormat) != -1) {
|
|
||||||
profile.DirectPlayProfiles.push({
|
|
||||||
Container: audioFormat == 'webma' ? 'webma,webm' : audioFormat,
|
|
||||||
Type: 'Audio'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var directPlayAudioContainers = AppInfo.directPlayAudioContainers;
|
|
||||||
|
|
||||||
if (directPlayAudioContainers && directPlayAudioContainers.length) {
|
|
||||||
profile.DirectPlayProfiles.push({
|
|
||||||
Container: directPlayAudioContainers.join(','),
|
|
||||||
Type: 'Audio'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canPlayWebm) {
|
|
||||||
profile.DirectPlayProfiles.push({
|
|
||||||
Container: 'webm',
|
|
||||||
Type: 'Video'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
profile.TranscodingProfiles = [];
|
|
||||||
|
|
||||||
// Can't use mkv on mobile because we have to use the native player controls and they won't be able to seek it
|
|
||||||
if (canPlayMkv && !isVlc && !browserInfo.mobile) {
|
|
||||||
profile.TranscodingProfiles.push({
|
|
||||||
Container: 'mkv',
|
|
||||||
Type: 'Video',
|
|
||||||
AudioCodec: videoAudioCodecs.join(','),
|
|
||||||
VideoCodec: 'h264',
|
|
||||||
Context: 'Streaming'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.canPlayHls()) {
|
|
||||||
profile.TranscodingProfiles.push({
|
|
||||||
Container: 'ts',
|
|
||||||
Type: 'Video',
|
|
||||||
AudioCodec: videoAudioCodecs.join(','),
|
|
||||||
VideoCodec: 'h264',
|
|
||||||
Context: 'Streaming',
|
|
||||||
Protocol: 'hls'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (canPlayAac && browserInfo.safari && !AppInfo.isNativeApp) {
|
|
||||||
profile.TranscodingProfiles.push({
|
|
||||||
Container: 'ts',
|
|
||||||
Type: 'Audio',
|
|
||||||
AudioCodec: 'aac',
|
|
||||||
Context: 'Streaming',
|
|
||||||
Protocol: 'hls'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canPlayWebm) {
|
|
||||||
|
|
||||||
profile.TranscodingProfiles.push({
|
|
||||||
Container: 'webm',
|
|
||||||
Type: 'Video',
|
|
||||||
AudioCodec: 'vorbis',
|
|
||||||
VideoCodec: 'vpx',
|
|
||||||
Context: 'Streaming',
|
|
||||||
Protocol: 'http'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
profile.TranscodingProfiles.push({
|
|
||||||
Container: 'mp4',
|
|
||||||
Type: 'Video',
|
|
||||||
AudioCodec: videoAudioCodecs.join(','),
|
|
||||||
VideoCodec: 'h264',
|
|
||||||
Context: 'Streaming',
|
|
||||||
Protocol: 'http'
|
|
||||||
});
|
|
||||||
|
|
||||||
profile.TranscodingProfiles.push({
|
|
||||||
Container: 'mp4',
|
|
||||||
Type: 'Video',
|
|
||||||
AudioCodec: videoAudioCodecs.join(','),
|
|
||||||
VideoCodec: 'h264',
|
|
||||||
Context: 'Static',
|
|
||||||
Protocol: 'http'
|
|
||||||
});
|
|
||||||
|
|
||||||
['opus', 'mp3', 'aac'].forEach(function (audioFormat) {
|
|
||||||
|
|
||||||
if (supportedFormats.indexOf(audioFormat) != -1) {
|
|
||||||
profile.TranscodingProfiles.push({
|
|
||||||
Container: audioFormat,
|
|
||||||
Type: 'Audio',
|
|
||||||
AudioCodec: audioFormat,
|
|
||||||
Context: 'Streaming',
|
|
||||||
Protocol: 'http'
|
|
||||||
});
|
|
||||||
profile.TranscodingProfiles.push({
|
|
||||||
Container: audioFormat,
|
|
||||||
Type: 'Audio',
|
|
||||||
AudioCodec: audioFormat,
|
|
||||||
Context: 'Static',
|
|
||||||
Protocol: 'http'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
profile.ContainerProfiles = [];
|
|
||||||
|
|
||||||
profile.CodecProfiles = [];
|
|
||||||
profile.CodecProfiles.push({
|
|
||||||
Type: 'Audio',
|
|
||||||
Conditions: [{
|
|
||||||
Condition: 'LessThanEqual',
|
|
||||||
Property: 'AudioChannels',
|
|
||||||
Value: '2'
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
|
|
||||||
// These don't play very well
|
|
||||||
if (isVlc) {
|
|
||||||
profile.CodecProfiles.push({
|
|
||||||
Type: 'VideoAudio',
|
|
||||||
Codec: 'dca',
|
|
||||||
Conditions: [
|
|
||||||
{
|
|
||||||
Condition: 'LessThanEqual',
|
|
||||||
Property: 'AudioChannels',
|
|
||||||
Value: 6
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
profile.CodecProfiles.push({
|
|
||||||
Type: 'VideoAudio',
|
|
||||||
Codec: 'aac,mp3',
|
|
||||||
Conditions: [
|
|
||||||
{
|
|
||||||
Condition: 'LessThanEqual',
|
|
||||||
Property: 'AudioChannels',
|
|
||||||
Value: '6'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
var videoAudioChannels = '6';
|
|
||||||
|
|
||||||
profile.CodecProfiles.push({
|
|
||||||
Type: 'VideoAudio',
|
|
||||||
Codec: 'aac',
|
|
||||||
Container: 'mkv,mov',
|
|
||||||
Conditions: [
|
|
||||||
{
|
|
||||||
Condition: 'NotEquals',
|
|
||||||
Property: 'AudioProfile',
|
|
||||||
Value: 'HE-AAC'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: 'Equals',
|
|
||||||
Property: 'IsSecondaryAudio',
|
|
||||||
Value: 'false',
|
|
||||||
IsRequired: 'false'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: 'LessThanEqual',
|
|
||||||
Property: 'AudioChannels',
|
|
||||||
Value: videoAudioChannels
|
|
||||||
}
|
|
||||||
// Disabling this is going to require us to learn why it was disabled in the first place
|
|
||||||
//,
|
|
||||||
//{
|
|
||||||
// Condition: 'NotEquals',
|
|
||||||
// Property: 'AudioProfile',
|
|
||||||
// Value: 'LC'
|
|
||||||
//}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
profile.CodecProfiles.push({
|
|
||||||
Type: 'VideoAudio',
|
|
||||||
Conditions: [
|
|
||||||
{
|
|
||||||
Condition: 'Equals',
|
|
||||||
Property: 'IsSecondaryAudio',
|
|
||||||
Value: 'false',
|
|
||||||
IsRequired: 'false'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: 'LessThanEqual',
|
|
||||||
Property: 'AudioChannels',
|
|
||||||
Value: videoAudioChannels
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isVlc) {
|
|
||||||
profile.CodecProfiles.push({
|
|
||||||
Type: 'Video',
|
|
||||||
Codec: 'h264',
|
|
||||||
Conditions: [
|
|
||||||
{
|
|
||||||
Condition: 'EqualsAny',
|
|
||||||
Property: 'VideoProfile',
|
|
||||||
Value: 'high|main|baseline|constrained baseline'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: 'LessThanEqual',
|
|
||||||
Property: 'VideoLevel',
|
|
||||||
Value: '41'
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
profile.CodecProfiles.push({
|
|
||||||
Type: 'Video',
|
|
||||||
Codec: 'h264',
|
|
||||||
Conditions: [
|
|
||||||
{
|
|
||||||
Condition: 'NotEquals',
|
|
||||||
Property: 'IsAnamorphic',
|
|
||||||
Value: 'true',
|
|
||||||
IsRequired: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: 'EqualsAny',
|
|
||||||
Property: 'VideoProfile',
|
|
||||||
Value: 'high|main|baseline|constrained baseline'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: 'LessThanEqual',
|
|
||||||
Property: 'VideoLevel',
|
|
||||||
Value: '41'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: 'LessThanEqual',
|
|
||||||
Property: 'Height',
|
|
||||||
Value: maxHeight
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isVlc) {
|
|
||||||
profile.CodecProfiles.push({
|
|
||||||
Type: 'Video',
|
|
||||||
Codec: 'vpx',
|
|
||||||
Conditions: [
|
|
||||||
{
|
|
||||||
Condition: 'NotEquals',
|
|
||||||
Property: 'IsAnamorphic',
|
|
||||||
Value: 'true',
|
|
||||||
IsRequired: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: 'LessThanEqual',
|
|
||||||
Property: 'Height',
|
|
||||||
Value: maxHeight
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subtitle profiles
|
|
||||||
// External vtt or burn in
|
|
||||||
profile.SubtitleProfiles = [];
|
profile.SubtitleProfiles = [];
|
||||||
if (self.supportsTextTracks()) {
|
|
||||||
|
|
||||||
if (isVlc) {
|
|
||||||
profile.SubtitleProfiles.push({
|
profile.SubtitleProfiles.push({
|
||||||
Format: 'srt',
|
Format: 'srt',
|
||||||
Method: 'External'
|
Method: 'External'
|
||||||
|
@ -440,28 +112,114 @@
|
||||||
Format: 'smi',
|
Format: 'smi',
|
||||||
Method: 'Embed'
|
Method: 'Embed'
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
profile.SubtitleProfiles.push({
|
// These don't play very well
|
||||||
Format: 'vtt',
|
profile.CodecProfiles.push({
|
||||||
Method: 'External'
|
Type: 'VideoAudio',
|
||||||
|
Codec: 'dca',
|
||||||
|
Conditions: [
|
||||||
|
{
|
||||||
|
Condition: 'LessThanEqual',
|
||||||
|
Property: 'AudioChannels',
|
||||||
|
Value: 6
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
profile.CodecProfiles.push({
|
||||||
|
Type: 'VideoAudio',
|
||||||
|
Codec: 'aac,mp3',
|
||||||
|
Conditions: [
|
||||||
|
{
|
||||||
|
Condition: 'LessThanEqual',
|
||||||
|
Property: 'AudioChannels',
|
||||||
|
Value: '6'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
profile.CodecProfiles.push({
|
||||||
|
Type: 'Video',
|
||||||
|
Codec: 'h264',
|
||||||
|
Conditions: [
|
||||||
|
{
|
||||||
|
Condition: 'EqualsAny',
|
||||||
|
Property: 'VideoProfile',
|
||||||
|
Value: 'high|main|baseline|constrained baseline'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Condition: 'LessThanEqual',
|
||||||
|
Property: 'VideoLevel',
|
||||||
|
Value: '41'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableVlcAudio) {
|
||||||
|
|
||||||
|
var directPlayAudioContainers = AppInfo.directPlayAudioContainers;
|
||||||
|
|
||||||
|
if (directPlayAudioContainers && directPlayAudioContainers.length) {
|
||||||
|
profile.DirectPlayProfiles.push({
|
||||||
|
Container: directPlayAudioContainers.join(','),
|
||||||
|
Type: 'Audio'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.CodecProfiles.push({
|
||||||
|
Type: 'Audio',
|
||||||
|
Conditions: [{
|
||||||
|
Condition: 'LessThanEqual',
|
||||||
|
Property: 'AudioChannels',
|
||||||
|
Value: '2'
|
||||||
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
profile.ResponseProfiles = [];
|
function updateDeviceProfileForIOS(profile) {
|
||||||
|
|
||||||
profile.ResponseProfiles.push({
|
var directPlayVideoContainers = AppInfo.directPlayVideoContainers;
|
||||||
Type: 'Video',
|
|
||||||
Container: 'm4v',
|
if (directPlayVideoContainers && directPlayVideoContainers.length) {
|
||||||
MimeType: 'video/mp4'
|
profile.DirectPlayProfiles.push({
|
||||||
|
Container: directPlayVideoContainers.join(','),
|
||||||
|
Type: 'Video'
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
profile.ResponseProfiles.push({
|
var directPlayAudioContainers = AppInfo.directPlayAudioContainers;
|
||||||
Type: 'Video',
|
|
||||||
Container: 'mov',
|
if (directPlayAudioContainers && directPlayAudioContainers.length) {
|
||||||
MimeType: 'video/webm'
|
profile.DirectPlayProfiles.push({
|
||||||
|
Container: directPlayAudioContainers.join(','),
|
||||||
|
Type: 'Audio'
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (browserInfo.safari && !AppInfo.isNativeApp) {
|
||||||
|
profile.TranscodingProfiles.unshift({
|
||||||
|
Container: 'ts',
|
||||||
|
Type: 'Audio',
|
||||||
|
AudioCodec: 'aac',
|
||||||
|
Context: 'Streaming',
|
||||||
|
Protocol: 'hls'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getDeviceProfile = function (maxHeight) {
|
||||||
|
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
|
||||||
|
require(['browserdeviceprofile'], function (profile) {
|
||||||
|
|
||||||
|
if (AppInfo.isNativeApp && browserInfo.android) {
|
||||||
|
updateDeviceProfileForAndroid(profile);
|
||||||
|
}
|
||||||
|
else if (AppInfo.isNativeApp && browserInfo.safari) {
|
||||||
|
updateDeviceProfileForIOS(profile);
|
||||||
|
}
|
||||||
resolve(profile);
|
resolve(profile);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue