jellyfin-web/src/scripts/browserdeviceprofile.js

901 lines
30 KiB
JavaScript
Raw Normal View History

define(['browser'], function (browser) {
'use strict';
function canPlayH264(videoTestElement) {
return !!(videoTestElement.canPlayType && videoTestElement.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, ''));
}
function canPlayH265(videoTestElement, options) {
if (browser.tizen || browser.orsay || browser.xboxOne || browser.web0s || options.supportsHevc) {
return true;
}
var userAgent = navigator.userAgent.toLowerCase();
if (browser.chromecast) {
var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
if (isChromecastUltra) {
return true;
}
}
if (browser.ps4) {
return false;
}
return !!videoTestElement.canPlayType &&
(videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.L120"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="hev1.1.L120"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.0.L120"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="hev1.1.0.L120"').replace(/no/, ''));
}
var _supportsTextTracks;
function supportsTextTracks() {
if (browser.tizen || browser.orsay) {
return true;
}
if (_supportsTextTracks == null) {
_supportsTextTracks = document.createElement('video').textTracks != null;
}
// For now, until ready
return _supportsTextTracks;
}
var _canPlayHls;
function canPlayHls() {
if (_canPlayHls == null) {
_canPlayHls = canPlayNativeHls() || canPlayHlsWithMSE();
}
return _canPlayHls;
}
function canPlayNativeHls() {
if (browser.tizen || browser.orsay) {
return true;
}
var media = document.createElement('video');
if (media.canPlayType('application/x-mpegURL').replace(/no/, '') ||
media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, '')) {
return true;
}
return false;
}
function canPlayHlsWithMSE() {
// text tracks dont work with this in firefox
return window.MediaSource != null;
}
function supportsAc3(videoTestElement) {
if (browser.edgeUwp || browser.tizen || browser.orsay || browser.web0s) {
return true;
}
return videoTestElement.canPlayType('audio/mp4; codecs="ac-3"').replace(/no/, '');
}
function supportsEac3(videoTestElement) {
if (browser.tizen || browser.orsay || browser.web0s) {
return true;
}
return videoTestElement.canPlayType('audio/mp4; codecs="ec-3"').replace(/no/, '');
}
function supportsAc3InHls(videoTestElement) {
if (browser.tizen || browser.orsay || browser.web0s) {
return true;
}
if (videoTestElement.canPlayType) {
return videoTestElement.canPlayType('application/x-mpegurl; codecs="avc1.42E01E, ac-3"').replace(/no/, '') ||
videoTestElement.canPlayType('application/vnd.apple.mpegURL; codecs="avc1.42E01E, ac-3"').replace(/no/, '');
}
return false;
}
function canPlayAudioFormat(format) {
var typeString;
if (format === 'flac') {
if (browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp) {
return true;
}
} else if (format === 'wma') {
if (browser.tizen || browser.orsay || browser.edgeUwp) {
return true;
}
} else if (format === 'asf') {
if (browser.tizen || browser.web0s || browser.edgeUwp) {
return true;
}
} else if (format === 'opus') {
if (!browser.web0s) {
typeString = 'audio/ogg; codecs="opus"';
return !!document.createElement('audio').canPlayType(typeString).replace(/no/, '');
}
return false;
} else if (format === 'alac') {
if (browser.iOS || browser.osx) {
return true;
}
} else if (format === 'mp2') {
// For now
return false;
}
if (format === 'webma') {
typeString = 'audio/webm';
} else if (format === 'mp2') {
typeString = 'audio/mpeg';
} else {
typeString = 'audio/' + format;
}
return !!document.createElement('audio').canPlayType(typeString).replace(/no/, '');
}
function testCanPlayMkv(videoTestElement) {
if (browser.tizen || browser.orsay || browser.web0s) {
return true;
}
if (videoTestElement.canPlayType('video/x-matroska').replace(/no/, '') ||
videoTestElement.canPlayType('video/mkv').replace(/no/, '')) {
return true;
}
// Unfortunately there's no real way to detect mkv support
if (browser.chrome) {
// Not supported on opera tv
if (browser.operaTv) {
return false;
}
var userAgent = navigator.userAgent.toLowerCase();
// Filter out browsers based on chromium that don't support mkv
if (userAgent.indexOf('vivaldi') !== -1 || userAgent.indexOf('opera') !== -1) {
return false;
}
return true;
}
if (browser.edgeUwp) {
return true;
}
return false;
}
function testCanPlayTs() {
return browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
}
function supportsMpeg2Video() {
return browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
}
function supportsVc1() {
return browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
}
function getFlvMseDirectPlayProfile() {
var videoAudioCodecs = ['aac'];
if (!browser.edge && !browser.msie) {
videoAudioCodecs.push('mp3');
}
return {
Container: 'flv',
Type: 'Video',
VideoCodec: 'h264',
AudioCodec: videoAudioCodecs.join(',')
};
}
function getDirectPlayProfileForVideoContainer(container, videoAudioCodecs, videoTestElement, options) {
var supported = false;
var profileContainer = container;
var videoCodecs = [];
switch (container) {
case 'asf':
supported = browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
videoAudioCodecs = [];
break;
case 'avi':
supported = browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
// New Samsung TV don't support XviD/DivX
// Explicitly add supported codecs to make other codecs be transcoded
if (browser.tizenVersion >= 4) {
videoCodecs.push('h264');
if (canPlayH265(videoTestElement, options)) {
videoCodecs.push('h265');
videoCodecs.push('hevc');
}
}
break;
case 'mpg':
case 'mpeg':
supported = browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
break;
case 'flv':
supported = browser.tizen || browser.orsay;
//if (!supported && window.MediaSource != null && window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"')) {
// return getFlvMseDirectPlayProfile();
//}
break;
case '3gp':
case 'mts':
case 'trp':
case 'vob':
case 'vro':
supported = browser.tizen || browser.orsay;
break;
case 'mov':
supported = browser.tizen || browser.orsay || browser.web0s || browser.chrome || browser.edgeUwp;
videoCodecs.push('h264');
break;
case 'm2ts':
supported = browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
videoCodecs.push('h264');
if (supportsVc1()) {
videoCodecs.push('vc1');
}
if (supportsMpeg2Video()) {
videoCodecs.push('mpeg2video');
}
break;
case 'wmv':
supported = browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
videoAudioCodecs = [];
break;
case 'ts':
supported = testCanPlayTs();
videoCodecs.push('h264');
if (canPlayH265(videoTestElement, options)) {
videoCodecs.push('h265');
videoCodecs.push('hevc');
}
if (supportsVc1()) {
videoCodecs.push('vc1');
}
if (supportsMpeg2Video()) {
videoCodecs.push('mpeg2video');
}
profileContainer = 'ts,mpegts';
break;
default:
break;
}
return supported ? {
Container: profileContainer,
Type: 'Video',
VideoCodec: videoCodecs.join(','),
AudioCodec: videoAudioCodecs.join(',')
} : null;
}
function getMaxBitrate() {
return 120000000;
}
function getGlobalMaxVideoBitrate() {
var userAgent = navigator.userAgent.toLowerCase();
if (browser.chromecast) {
var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
if (isChromecastUltra) {
return null;
}
// This is a hack to try and detect chromecast on vizio
if (self.screen && self.screen.width >= 3800) {
return null;
}
return 30000000;
}
var isTizenFhd = false;
if (browser.tizen) {
try {
var isTizenUhd = webapis.productinfo.isUdPanelSupported();
isTizenFhd = !isTizenUhd;
console.debug("isTizenFhd = " + isTizenFhd);
} catch (error) {
console.error("isUdPanelSupported() error code = " + error.code);
}
}
return browser.ps4 ? 8000000 :
(browser.xboxOne ? 12000000 :
(browser.edgeUwp ? null :
(browser.tizen && isTizenFhd ? 20000000 : null)));
}
return function (options) {
options = options || {};
var physicalAudioChannels = options.audioChannels || (browser.tv || browser.ps4 || browser.xboxOne ? 6 : 2);
var bitrateSetting = getMaxBitrate();
var videoTestElement = document.createElement('video');
var canPlayVp8 = videoTestElement.canPlayType('video/webm; codecs="vp8"').replace(/no/, '');
var canPlayVp9 = videoTestElement.canPlayType('video/webm; codecs="vp9"').replace(/no/, '');
var webmAudioCodecs = ['vorbis'];
var canPlayMkv = testCanPlayMkv(videoTestElement);
var profile = {};
profile.MaxStreamingBitrate = bitrateSetting;
profile.MaxStaticBitrate = 100000000;
profile.MusicStreamingTranscodingBitrate = Math.min(bitrateSetting, 192000);
profile.DirectPlayProfiles = [];
var videoAudioCodecs = [];
var hlsVideoAudioCodecs = [];
var supportsMp3VideoAudio = videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.69"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.6B"').replace(/no/, '');
// Not sure how to test for this
var supportsMp2VideoAudio = browser.edgeUwp || browser.tizen || browser.orsay || browser.web0s;
var maxVideoWidth = browser.xboxOne ?
(self.screen ? self.screen.width : null) :
null;
if (options.maxVideoWidth) {
maxVideoWidth = options.maxVideoWidth;
}
var canPlayAacVideoAudio = videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"').replace(/no/, '');
if (canPlayAacVideoAudio && browser.chromecast && physicalAudioChannels <= 2) {
// prioritize this first
videoAudioCodecs.push('aac');
}
// Only put mp3 first if mkv support is there
// Otherwise with HLS and mp3 audio we're seeing some browsers
// safari is lying
if (supportsAc3(videoTestElement)) {
videoAudioCodecs.push('ac3');
var eAc3 = supportsEac3(videoTestElement);
if (eAc3) {
videoAudioCodecs.push('eac3');
}
// This works in edge desktop, but not mobile
// TODO: Retest this on mobile
if (supportsAc3InHls(videoTestElement)) {
hlsVideoAudioCodecs.push('ac3');
if (eAc3) {
hlsVideoAudioCodecs.push('eac3');
}
}
}
if (canPlayAacVideoAudio && browser.chromecast && videoAudioCodecs.indexOf('aac') === -1) {
// prioritize this first
videoAudioCodecs.push('aac');
}
if (supportsMp3VideoAudio) {
videoAudioCodecs.push('mp3');
// PS4 fails to load HLS with mp3 audio
if (!browser.ps4) {
// mp3 encoder only supports 2 channels, so only make that preferred if we're only requesting 2 channels
// Also apply it for chromecast because it no longer supports AAC 5.1
if (physicalAudioChannels <= 2) {
hlsVideoAudioCodecs.push('mp3');
}
}
}
if (canPlayAacVideoAudio) {
if (videoAudioCodecs.indexOf('aac') === -1) {
videoAudioCodecs.push('aac');
}
hlsVideoAudioCodecs.push('aac');
}
if (supportsMp3VideoAudio) {
// PS4 fails to load HLS with mp3 audio
if (!browser.ps4) {
if (hlsVideoAudioCodecs.indexOf('mp3') === -1) {
hlsVideoAudioCodecs.push('mp3');
}
}
}
if (supportsMp2VideoAudio) {
videoAudioCodecs.push('mp2');
}
var supportsDts = browser.tizen || browser.orsay || browser.web0s || options.supportsDts;
// DTS audio not supported in 2018 models (Tizen 4.0)
if (browser.tizenVersion >= 4) {
supportsDts = false;
}
if (supportsDts) {
videoAudioCodecs.push('dca');
videoAudioCodecs.push('dts');
}
if (browser.tizen || browser.orsay || browser.web0s) {
videoAudioCodecs.push('pcm_s16le');
videoAudioCodecs.push('pcm_s24le');
}
if (options.supportsTrueHd) {
videoAudioCodecs.push('truehd');
}
if (browser.tizen || browser.orsay) {
videoAudioCodecs.push('aac_latm');
}
if (canPlayAudioFormat('opus')) {
videoAudioCodecs.push('opus');
hlsVideoAudioCodecs.push('opus');
webmAudioCodecs.push('opus');
}
if (canPlayAudioFormat('flac')) {
videoAudioCodecs.push('flac');
}
videoAudioCodecs = videoAudioCodecs.filter(function (c) {
return (options.disableVideoAudioCodecs || []).indexOf(c) === -1;
});
hlsVideoAudioCodecs = hlsVideoAudioCodecs.filter(function (c) {
return (options.disableHlsVideoAudioCodecs || []).indexOf(c) === -1;
});
var mp4VideoCodecs = [];
var hlsVideoCodecs = [];
if (canPlayH264(videoTestElement)) {
mp4VideoCodecs.push('h264');
hlsVideoCodecs.push('h264');
}
if (canPlayH265(videoTestElement, options)) {
mp4VideoCodecs.push('h265');
mp4VideoCodecs.push('hevc');
if (browser.tizen || browser.web0s) {
hlsVideoCodecs.push('h265');
hlsVideoCodecs.push('hevc');
}
}
if (supportsMpeg2Video()) {
mp4VideoCodecs.push('mpeg2video');
}
if (supportsVc1()) {
mp4VideoCodecs.push('vc1');
}
if (browser.tizen || browser.orsay) {
mp4VideoCodecs.push('msmpeg4v2');
}
if (canPlayVp8) {
mp4VideoCodecs.push('vp8');
}
if (canPlayVp9) {
mp4VideoCodecs.push('vp9');
}
if (canPlayVp8 || browser.tizen || browser.orsay) {
videoAudioCodecs.push('vorbis');
}
if (mp4VideoCodecs.length) {
profile.DirectPlayProfiles.push({
Container: 'mp4,m4v',
Type: 'Video',
VideoCodec: mp4VideoCodecs.join(','),
AudioCodec: videoAudioCodecs.join(',')
});
}
if (canPlayMkv && mp4VideoCodecs.length) {
profile.DirectPlayProfiles.push({
Container: 'mkv',
Type: 'Video',
VideoCodec: mp4VideoCodecs.join(','),
AudioCodec: videoAudioCodecs.join(',')
});
}
// These are formats we can't test for but some devices will support
['m2ts', 'wmv', 'ts', 'asf', 'avi', 'mpg', 'mpeg', 'flv', '3gp', 'mts', 'trp', 'vob', 'vro', 'mov'].map(function (container) {
return getDirectPlayProfileForVideoContainer(container, videoAudioCodecs, videoTestElement, options);
}).filter(function (i) {
return i != null;
}).forEach(function (i) {
profile.DirectPlayProfiles.push(i);
});
['opus', 'mp3', 'mp2', 'aac', 'flac', 'alac', 'webma', 'wma', 'wav', 'ogg', 'oga'].filter(canPlayAudioFormat).forEach(function (audioFormat) {
if (audioFormat === 'mp2') {
profile.DirectPlayProfiles.push({
Container: 'mp2,mp3',
Type: 'Audio',
AudioCodec: audioFormat
});
} else if (audioFormat === 'mp3') {
profile.DirectPlayProfiles.push({
Container: audioFormat,
Type: 'Audio',
AudioCodec: audioFormat
});
} else {
profile.DirectPlayProfiles.push({
Container: audioFormat === 'webma' ? 'webma,webm' : audioFormat,
Type: 'Audio'
});
}
// aac also appears in the m4a and m4b container
if (audioFormat === 'aac' || audioFormat === 'alac') {
profile.DirectPlayProfiles.push({
Container: 'm4a,m4b',
AudioCodec: audioFormat,
Type: 'Audio'
});
}
});
if (canPlayVp8) {
profile.DirectPlayProfiles.push({
Container: 'webm',
Type: 'Video',
AudioCodec: webmAudioCodecs.join(','),
VideoCodec: 'VP8'
});
}
if (canPlayVp9) {
profile.DirectPlayProfiles.push({
Container: 'webm',
Type: 'Video',
AudioCodec: webmAudioCodecs.join(','),
VideoCodec: 'VP9'
});
}
profile.TranscodingProfiles = [];
var hlsBreakOnNonKeyFrames = browser.iOS || browser.osx || browser.edge || !canPlayNativeHls() ? true : false;
if (canPlayHls() && browser.enableHlsAudio !== false) {
profile.TranscodingProfiles.push({
// hlsjs, edge, and android all seem to require ts container
Container: !canPlayNativeHls() || browser.edge || browser.android ? 'ts' : 'aac',
Type: 'Audio',
AudioCodec: 'aac',
Context: 'Streaming',
Protocol: 'hls',
MaxAudioChannels: physicalAudioChannels.toString(),
MinSegments: browser.iOS || browser.osx ? '2' : '1',
BreakOnNonKeyFrames: hlsBreakOnNonKeyFrames
});
}
// For streaming, prioritize opus transcoding after mp3/aac. It is too problematic with random failures
// But for static (offline sync), it will be just fine.
// Prioritize aac higher because the encoder can accept more channels than mp3
['aac', 'mp3', 'opus', 'wav'].filter(canPlayAudioFormat).forEach(function (audioFormat) {
profile.TranscodingProfiles.push({
Container: audioFormat,
Type: 'Audio',
AudioCodec: audioFormat,
Context: 'Streaming',
Protocol: 'http',
MaxAudioChannels: physicalAudioChannels.toString()
});
});
['opus', 'mp3', 'aac', 'wav'].filter(canPlayAudioFormat).forEach(function (audioFormat) {
profile.TranscodingProfiles.push({
Container: audioFormat,
Type: 'Audio',
AudioCodec: audioFormat,
Context: 'Static',
Protocol: 'http',
MaxAudioChannels: physicalAudioChannels.toString()
});
});
if (canPlayMkv && !browser.tizen && !browser.orsay && options.enableMkvProgressive !== false) {
profile.TranscodingProfiles.push({
Container: 'mkv',
Type: 'Video',
AudioCodec: videoAudioCodecs.join(','),
VideoCodec: mp4VideoCodecs.join(','),
Context: 'Streaming',
MaxAudioChannels: physicalAudioChannels.toString(),
CopyTimestamps: true
});
}
if (canPlayMkv) {
profile.TranscodingProfiles.push({
Container: 'mkv',
Type: 'Video',
AudioCodec: videoAudioCodecs.join(','),
VideoCodec: mp4VideoCodecs.join(','),
Context: 'Static',
MaxAudioChannels: physicalAudioChannels.toString(),
CopyTimestamps: true
});
}
if (canPlayHls() && hlsVideoAudioCodecs.length && options.enableHls !== false) {
profile.TranscodingProfiles.push({
Container: 'ts',
Type: 'Video',
AudioCodec: hlsVideoAudioCodecs.join(','),
VideoCodec: hlsVideoCodecs.join(','),
Context: 'Streaming',
Protocol: 'hls',
MaxAudioChannels: physicalAudioChannels.toString(),
MinSegments: browser.iOS || browser.osx ? '2' : '1',
BreakOnNonKeyFrames: hlsBreakOnNonKeyFrames
});
}
if (canPlayVp8) {
profile.TranscodingProfiles.push({
Container: 'webm',
Type: 'Video',
AudioCodec: 'vorbis',
VideoCodec: 'vpx',
Context: 'Streaming',
Protocol: 'http',
// If audio transcoding is needed, limit channels to number of physical audio channels
// Trying to transcode to 5 channels when there are only 2 speakers generally does not sound good
MaxAudioChannels: physicalAudioChannels.toString()
});
}
profile.TranscodingProfiles.push({
Container: 'mp4',
Type: 'Video',
AudioCodec: videoAudioCodecs.join(','),
VideoCodec: 'h264',
Context: 'Static',
Protocol: 'http'
});
profile.ContainerProfiles = [];
profile.CodecProfiles = [];
var supportsSecondaryAudio = browser.tizen || browser.orsay || videoTestElement.audioTracks;
var aacCodecProfileConditions = [];
// Handle he-aac not supported
if (!videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.5"').replace(/no/, '')) {
// TODO: This needs to become part of the stream url in order to prevent stream copy
aacCodecProfileConditions.push({
Condition: 'NotEquals',
Property: 'AudioProfile',
Value: 'HE-AAC'
});
}
if (!supportsSecondaryAudio) {
aacCodecProfileConditions.push({
Condition: 'Equals',
Property: 'IsSecondaryAudio',
Value: 'false',
IsRequired: false
});
}
if (browser.chromecast) {
aacCodecProfileConditions.push({
Condition: 'LessThanEqual',
Property: 'AudioChannels',
Value: '2',
IsRequired: true
});
}
if (aacCodecProfileConditions.length) {
profile.CodecProfiles.push({
Type: 'VideoAudio',
Codec: 'aac',
Conditions: aacCodecProfileConditions
});
}
if (!supportsSecondaryAudio) {
profile.CodecProfiles.push({
Type: 'VideoAudio',
Conditions: [
{
Condition: 'Equals',
Property: 'IsSecondaryAudio',
Value: 'false',
IsRequired: false
}
]
});
}
var maxH264Level = 42;
var h264Profiles = 'high|main|baseline|constrained baseline';
if (browser.tizen || browser.orsay || browser.web0s ||
videoTestElement.canPlayType('video/mp4; codecs="avc1.640833"').replace(/no/, '')) {
maxH264Level = 51;
}
// Support H264 Level 52 (Tizen 5.0) - app only
if (browser.tizenVersion >= 5 && window.NativeShell) {
maxH264Level = 52;
}
if (browser.tizen || browser.orsay ||
videoTestElement.canPlayType('video/mp4; codecs="avc1.6e0033"').replace(/no/, '')) {
// These tests are passing in safari, but playback is failing
if (!browser.safari && !browser.iOS && !browser.web0s && !browser.edge && !browser.mobile) {
h264Profiles += '|high 10';
}
}
profile.CodecProfiles.push({
Type: 'Video',
Codec: 'h264',
Conditions: [
{
Condition: 'NotEquals',
Property: 'IsAnamorphic',
Value: 'true',
IsRequired: false
},
{
Condition: 'EqualsAny',
Property: 'VideoProfile',
Value: h264Profiles,
IsRequired: false
},
{
Condition: 'LessThanEqual',
Property: 'VideoLevel',
Value: maxH264Level.toString(),
IsRequired: false
}
]
});
if (!browser.edgeUwp && !browser.tizen && !browser.orsay && !browser.web0s) {
//profile.CodecProfiles[profile.CodecProfiles.length - 1].Conditions.push({
// Condition: 'NotEquals',
// Property: 'IsAVC',
// Value: 'false',
// IsRequired: false
//});
//profile.CodecProfiles[profile.CodecProfiles.length - 1].Conditions.push({
// Condition: 'NotEquals',
// Property: 'IsInterlaced',
// Value: 'true',
// IsRequired: false
//});
}
if (maxVideoWidth) {
profile.CodecProfiles[profile.CodecProfiles.length - 1].Conditions.push({
Condition: 'LessThanEqual',
Property: 'Width',
Value: maxVideoWidth.toString(),
IsRequired: false
});
}
var globalMaxVideoBitrate = (getGlobalMaxVideoBitrate() || '').toString();
var h264MaxVideoBitrate = globalMaxVideoBitrate;
if (h264MaxVideoBitrate) {
profile.CodecProfiles[profile.CodecProfiles.length - 1].Conditions.push({
Condition: 'LessThanEqual',
Property: 'VideoBitrate',
Value: h264MaxVideoBitrate,
IsRequired: true
});
}
var globalVideoConditions = [];
if (globalMaxVideoBitrate) {
globalVideoConditions.push({
Condition: 'LessThanEqual',
Property: 'VideoBitrate',
Value: globalMaxVideoBitrate
});
}
if (maxVideoWidth) {
globalVideoConditions.push({
Condition: 'LessThanEqual',
Property: 'Width',
Value: maxVideoWidth.toString(),
IsRequired: false
});
}
if (globalVideoConditions.length) {
profile.CodecProfiles.push({
Type: 'Video',
Conditions: globalVideoConditions
});
}
if (browser.chromecast) {
profile.CodecProfiles.push({
Type: 'Audio',
Codec: 'flac',
Conditions: [
{
Condition: 'LessThanEqual',
Property: 'AudioSampleRate',
Value: '96000'
}]
});
}
// Subtitle profiles
// External vtt or burn in
profile.SubtitleProfiles = [];
if (supportsTextTracks()) {
profile.SubtitleProfiles.push({
Format: 'vtt',
Method: 'External'
});
}
profile.ResponseProfiles = [];
profile.ResponseProfiles.push({
Type: 'Video',
Container: 'm4v',
MimeType: 'video/mp4'
});
return profile;
};
});