2020-11-20 12:30:16 +08:00
import appSettings from './settings/appSettings' ;
import * as userSettings from './settings/userSettings' ;
2020-08-16 20:24:45 +02:00
import browser from './browser' ;
/* eslint-disable indent */
2020-08-02 15:25:20 +03:00
2020-03-30 17:02:16 +08:00
function canPlayH264 ( videoTestElement ) {
return ! ! ( videoTestElement . canPlayType && videoTestElement . canPlayType ( 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"' ) . replace ( /no/ , '' ) ) ;
}
2020-11-12 20:03:38 +08:00
function canPlayHevc ( videoTestElement , options ) {
2020-06-06 19:16:48 +02:00
if ( browser . tizen || browser . xboxOne || browser . web0s || options . supportsHevc ) {
2020-03-30 17:02:16 +08:00
return true ;
}
if ( browser . ps4 ) {
return false ;
}
2020-11-12 20:03:38 +08:00
// hevc main level 4.0
2020-03-30 17:02:16 +08:00
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/ , '' ) ) ;
}
2020-10-07 21:12:14 +09:00
let _supportsTextTracks ;
2020-03-30 17:02:16 +08:00
function supportsTextTracks ( ) {
2020-06-06 19:16:48 +02:00
if ( browser . tizen ) {
2020-03-30 17:02:16 +08:00
return true ;
}
if ( _supportsTextTracks == null ) {
_supportsTextTracks = document . createElement ( 'video' ) . textTracks != null ;
}
// For now, until ready
return _supportsTextTracks ;
}
2020-10-07 21:12:14 +09:00
let _canPlayHls ;
2020-03-30 17:02:16 +08:00
function canPlayHls ( ) {
if ( _canPlayHls == null ) {
_canPlayHls = canPlayNativeHls ( ) || canPlayHlsWithMSE ( ) ;
}
return _canPlayHls ;
}
function canPlayNativeHls ( ) {
2020-06-06 19:16:48 +02:00
if ( browser . tizen ) {
2020-03-30 17:02:16 +08:00
return true ;
}
2020-10-07 21:12:14 +09:00
const media = document . createElement ( 'video' ) ;
2022-10-06 01:13:06 -04:00
return ! ! ( media . canPlayType ( 'application/x-mpegURL' ) . replace ( /no/ , '' ) ||
media . canPlayType ( 'application/vnd.apple.mpegURL' ) . replace ( /no/ , '' ) ) ;
2020-03-30 17:02:16 +08:00
}
function canPlayHlsWithMSE ( ) {
// text tracks don’ t work with this in firefox
2020-07-05 12:54:25 +02:00
return window . MediaSource != null ; /* eslint-disable-line compat/compat */
2020-03-30 17:02:16 +08:00
}
function supportsAc3 ( videoTestElement ) {
2020-06-06 19:16:48 +02:00
if ( browser . edgeUwp || browser . tizen || browser . web0s ) {
2020-03-30 17:02:16 +08:00
return true ;
}
2020-09-01 13:20:26 -04:00
// iPhones 5c and older and old model iPads do not support AC-3/E-AC-3
// These models can only run iOS 10.x or lower
if ( browser . iOS && browser . iOSVersion < 11 ) {
return false ;
}
2020-03-30 17:02:16 +08:00
return videoTestElement . canPlayType ( 'audio/mp4; codecs="ac-3"' ) . replace ( /no/ , '' ) ;
}
function supportsEac3 ( videoTestElement ) {
2020-06-06 19:16:48 +02:00
if ( browser . tizen || browser . web0s ) {
2020-03-30 17:02:16 +08:00
return true ;
}
2020-09-01 13:20:26 -04:00
// iPhones 5c and older and old model iPads do not support AC-3/E-AC-3
// These models can only run iOS 10.x or lower
if ( browser . iOS && browser . iOSVersion < 11 ) {
return false ;
}
2020-03-30 17:02:16 +08:00
return videoTestElement . canPlayType ( 'audio/mp4; codecs="ec-3"' ) . replace ( /no/ , '' ) ;
}
function supportsAc3InHls ( videoTestElement ) {
2020-06-06 19:16:48 +02:00
if ( browser . tizen || browser . web0s ) {
2020-03-30 17:02:16 +08:00
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 ) {
2020-10-07 21:12:14 +09:00
let typeString ;
2020-03-30 17:02:16 +08:00
2022-10-04 17:31:48 -04:00
if ( format === 'flac' || format === 'asf' ) {
2020-06-06 19:16:48 +02:00
if ( browser . tizen || browser . web0s || browser . edgeUwp ) {
2020-03-30 17:02:16 +08:00
return true ;
}
} else if ( format === 'wma' ) {
2020-06-06 19:16:48 +02:00
if ( browser . tizen || browser . edgeUwp ) {
2020-03-30 17:02:16 +08:00
return true ;
}
} else if ( format === 'opus' ) {
2022-03-17 22:40:36 +03:00
if ( browser . web0s ) {
// canPlayType lies about OPUS support
return browser . web0sVersion >= 3.5 ;
}
2022-02-15 18:45:01 +03:00
typeString = 'audio/ogg; codecs="opus"' ;
2020-03-30 17:02:16 +08:00
} 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' ;
2022-02-15 18:45:01 +03:00
} else if ( ! typeString ) {
2020-03-30 17:02:16 +08:00
typeString = 'audio/' + format ;
}
return ! ! document . createElement ( 'audio' ) . canPlayType ( typeString ) . replace ( /no/ , '' ) ;
}
function testCanPlayMkv ( videoTestElement ) {
2020-06-06 19:16:48 +02:00
if ( browser . tizen || browser . web0s ) {
2020-03-30 17:02:16 +08:00
return true ;
}
if ( videoTestElement . canPlayType ( 'video/x-matroska' ) . replace ( /no/ , '' ) ||
videoTestElement . canPlayType ( 'video/mkv' ) . replace ( /no/ , '' ) ) {
return true ;
}
2020-07-27 21:11:12 +08:00
if ( browser . edgeChromium && browser . windows ) {
return true ;
}
2022-10-06 01:13:06 -04:00
return ! ! browser . edgeUwp ;
2020-03-30 17:02:16 +08:00
}
2020-06-03 12:26:25 -04:00
function testCanPlayAv1 ( videoTestElement ) {
2022-10-04 17:31:48 -04:00
if ( browser . tizenVersion >= 5.5 || browser . web0sVersion >= 5 ) {
2020-06-03 12:26:25 -04:00
return true ;
}
return videoTestElement . canPlayType ( 'video/webm; codecs="av01.0.15M.10"' ) . replace ( /no/ , '' ) ;
}
2020-03-30 17:02:16 +08:00
function testCanPlayTs ( ) {
2020-06-06 19:16:48 +02:00
return browser . tizen || browser . web0s || browser . edgeUwp ;
2020-03-30 17:02:16 +08:00
}
function supportsMpeg2Video ( ) {
2020-06-06 19:16:48 +02:00
return browser . tizen || browser . web0s || browser . edgeUwp ;
2020-03-30 17:02:16 +08:00
}
2020-06-09 21:50:12 +02:00
function supportsVc1 ( videoTestElement ) {
return browser . tizen || browser . web0s || browser . edgeUwp || videoTestElement . canPlayType ( 'video/mp4; codecs="vc-1"' ) . replace ( /no/ , '' ) ;
2020-03-30 17:02:16 +08:00
}
function getDirectPlayProfileForVideoContainer ( container , videoAudioCodecs , videoTestElement , options ) {
2020-10-07 21:12:14 +09:00
let supported = false ;
let profileContainer = container ;
const videoCodecs = [ ] ;
2020-03-30 17:02:16 +08:00
switch ( container ) {
case 'asf' :
2022-10-04 17:31:48 -04:00
case 'wmv' :
2020-06-06 19:16:48 +02:00
supported = browser . tizen || browser . web0s || browser . edgeUwp ;
2020-03-30 17:02:16 +08:00
videoAudioCodecs = [ ] ;
break ;
case 'avi' :
2020-06-06 19:16:48 +02:00
supported = browser . tizen || browser . web0s || browser . edgeUwp ;
2020-03-30 17:02:16 +08:00
// 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' ) ;
2020-11-12 20:03:38 +08:00
if ( canPlayHevc ( videoTestElement , options ) ) {
2020-03-30 17:02:16 +08:00
videoCodecs . push ( 'hevc' ) ;
}
}
break ;
case 'mpg' :
case 'mpeg' :
2020-06-06 19:16:48 +02:00
supported = browser . tizen || browser . web0s || browser . edgeUwp ;
2020-03-30 17:02:16 +08:00
break ;
case 'flv' :
2020-06-06 19:16:48 +02:00
supported = browser . tizen ;
2020-03-30 17:02:16 +08:00
break ;
case '3gp' :
case 'mts' :
case 'trp' :
case 'vob' :
case 'vro' :
2020-06-06 19:16:48 +02:00
supported = browser . tizen ;
2020-03-30 17:02:16 +08:00
break ;
case 'mov' :
2021-05-03 10:34:21 -04:00
supported = browser . safari || browser . tizen || browser . web0s || browser . chrome || browser . edgeChromium || browser . edgeUwp ;
2020-03-30 17:02:16 +08:00
videoCodecs . push ( 'h264' ) ;
break ;
case 'm2ts' :
2020-06-06 19:16:48 +02:00
supported = browser . tizen || browser . web0s || browser . edgeUwp ;
2020-03-30 17:02:16 +08:00
videoCodecs . push ( 'h264' ) ;
2020-06-09 21:50:12 +02:00
if ( supportsVc1 ( videoTestElement ) ) {
2020-03-30 17:02:16 +08:00
videoCodecs . push ( 'vc1' ) ;
}
if ( supportsMpeg2Video ( ) ) {
videoCodecs . push ( 'mpeg2video' ) ;
}
break ;
case 'ts' :
supported = testCanPlayTs ( ) ;
videoCodecs . push ( 'h264' ) ;
2020-11-12 20:03:38 +08:00
// safari doesn't support hevc in TS-HLS
if ( ( browser . tizen || browser . web0s ) && canPlayHevc ( videoTestElement , options ) ) {
2020-03-30 17:02:16 +08:00
videoCodecs . push ( 'hevc' ) ;
}
2020-06-09 21:50:12 +02:00
if ( supportsVc1 ( videoTestElement ) ) {
2020-03-30 17:02:16 +08:00
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 ( ) {
2020-10-07 21:12:14 +09:00
let isTizenFhd = false ;
2020-03-30 17:02:16 +08:00
if ( browser . tizen ) {
try {
2020-10-07 21:12:14 +09:00
const isTizenUhd = webapis . productinfo . isUdPanelSupported ( ) ;
2020-03-30 17:02:16 +08:00
isTizenFhd = ! isTizenUhd ;
2020-05-04 12:44:12 +02:00
console . debug ( 'isTizenFhd = ' + isTizenFhd ) ;
2020-03-30 17:02:16 +08:00
} catch ( error ) {
2020-05-04 12:44:12 +02:00
console . error ( 'isUdPanelSupported() error code = ' + error . code ) ;
2020-03-30 17:02:16 +08:00
}
}
2022-04-27 15:45:56 -07:00
let bitrate = null ;
if ( browser . ps4 ) {
bitrate = 8000000 ;
} else if ( browser . xboxOne ) {
bitrate = 12000000 ;
} else if ( browser . tizen && isTizenFhd ) {
bitrate = 20000000 ;
}
return bitrate ;
2020-03-30 17:02:16 +08:00
}
2022-01-17 00:08:33 +01:00
function getSpeakerCount ( ) {
const AudioContext = window . AudioContext || window . webkitAudioContext || false ; /* eslint-disable-line compat/compat */
if ( AudioContext ) {
const audioCtx = new AudioContext ( ) ;
return audioCtx . destination . maxChannelCount ;
}
return - 1 ;
}
2022-06-26 20:53:47 -04:00
function getPhysicalAudioChannels ( options , videoTestElement ) {
2022-01-17 00:08:33 +01:00
const allowedAudioChannels = parseInt ( userSettings . allowedAudioChannels ( ) , 10 ) ;
if ( allowedAudioChannels > 0 ) {
return allowedAudioChannels ;
}
if ( options . audioChannels ) {
return options . audioChannels ;
}
const isSurroundSoundSupportedBrowser = browser . safari || browser . chrome || browser . edgeChromium || browser . firefox || browser . tv || browser . ps4 || browser . xboxOne ;
2022-06-26 20:53:47 -04:00
const isAc3Eac3Supported = supportsAc3 ( videoTestElement ) || supportsEac3 ( videoTestElement ) ;
2022-01-17 00:08:33 +01:00
const speakerCount = getSpeakerCount ( ) ;
2022-06-26 20:53:47 -04:00
// AC3/EAC3 hinted that device is able to play dolby surround sound.
if ( isAc3Eac3Supported && isSurroundSoundSupportedBrowser ) {
return speakerCount > 6 ? speakerCount : 6 ;
}
2022-01-17 00:08:33 +01:00
if ( speakerCount > 2 ) {
if ( isSurroundSoundSupportedBrowser ) {
return speakerCount ;
}
return 2 ;
}
if ( speakerCount > 0 ) {
return speakerCount ;
}
if ( isSurroundSoundSupportedBrowser ) {
return 6 ;
}
return 2 ;
}
2023-01-22 14:08:02 -05:00
/ * *
* Checks if the web engine supports secondary audio .
* @ param { HTMLVideoElement } videoTestElement The video test element
* @ returns { boolean } _true _ if the web engine supports secondary audio .
* /
export function canPlaySecondaryAudio ( videoTestElement ) {
// We rely on HTMLMediaElement.audioTracks
// It works in Chrome 79+ with "Experimental Web Platform features" enabled
return ! ! videoTestElement . audioTracks
// It doesn't work in Firefox 108 even with "media.track.enabled" enabled (it only sees the first audio track)
&& ! browser . firefox
// It seems to work on Tizen 5.5+ (2020, Chrome 69+). See https://developer.tizen.org/forums/web-application-development/video-tag-not-work-audiotracks
&& ( browser . tizenVersion >= 5.5 || ! browser . tizen )
// Assume webOS 5+ (2020, Chrome 68+) supports secondary audio like Tizen 5.5+
&& ( browser . web0sVersion >= 5.0 || ! browser . web0sVersion ) ;
}
2020-08-16 20:24:45 +02:00
export default function ( options ) {
2020-03-30 17:02:16 +08:00
options = options || { } ;
2020-10-07 21:12:14 +09:00
const bitrateSetting = getMaxBitrate ( ) ;
2020-03-30 17:02:16 +08:00
2020-10-07 21:12:14 +09:00
const videoTestElement = document . createElement ( 'video' ) ;
2020-03-30 17:02:16 +08:00
2022-06-26 20:53:47 -04:00
const physicalAudioChannels = getPhysicalAudioChannels ( options , videoTestElement ) ;
2020-10-07 21:12:14 +09:00
const canPlayVp8 = videoTestElement . canPlayType ( 'video/webm; codecs="vp8"' ) . replace ( /no/ , '' ) ;
const canPlayVp9 = videoTestElement . canPlayType ( 'video/webm; codecs="vp9"' ) . replace ( /no/ , '' ) ;
const webmAudioCodecs = [ 'vorbis' ] ;
2020-03-30 17:02:16 +08:00
2020-10-07 21:12:14 +09:00
const canPlayMkv = testCanPlayMkv ( videoTestElement ) ;
2020-03-30 17:02:16 +08:00
2022-10-12 14:44:10 -04:00
const profile = {
MaxStreamingBitrate : bitrateSetting ,
MaxStaticBitrate : 100000000 ,
MusicStreamingTranscodingBitrate : Math . min ( bitrateSetting , 384000 ) ,
DirectPlayProfiles : [ ]
} ;
2020-03-30 17:02:16 +08:00
2020-10-07 21:12:14 +09:00
let videoAudioCodecs = [ ] ;
2020-11-12 20:03:38 +08:00
let hlsInTsVideoAudioCodecs = [ ] ;
let hlsInFmp4VideoAudioCodecs = [ ] ;
2020-03-30 17:02:16 +08:00
2020-10-07 21:12:14 +09:00
const supportsMp3VideoAudio = videoTestElement . canPlayType ( 'video/mp4; codecs="avc1.640029, mp4a.69"' ) . replace ( /no/ , '' )
2020-06-06 18:53:05 +02:00
|| videoTestElement . canPlayType ( 'video/mp4; codecs="avc1.640029, mp4a.6B"' ) . replace ( /no/ , '' )
|| videoTestElement . canPlayType ( 'video/mp4; codecs="avc1.640029, mp3"' ) . replace ( /no/ , '' ) ;
2020-03-30 17:02:16 +08:00
2022-04-21 00:34:38 +02:00
let supportsMp2VideoAudio = options . supportsMp2VideoAudio ;
if ( supportsMp2VideoAudio == null ) {
supportsMp2VideoAudio = browser . edgeUwp || browser . tizen || browser . web0s ;
// If the browser supports MP3, it presumably supports MP2 as well
if ( supportsMp3VideoAudio && ( browser . chrome || browser . edgeChromium || ( browser . firefox && browser . versionMajor >= 83 ) ) ) {
supportsMp2VideoAudio = true ;
}
2022-08-27 08:22:59 +02:00
if ( browser . android ) {
supportsMp2VideoAudio = false ;
}
2022-04-21 00:34:38 +02:00
}
2020-03-30 17:02:16 +08:00
2020-08-25 10:12:35 +09:00
/* eslint-disable compat/compat */
2022-05-16 12:23:22 -07:00
let maxVideoWidth = browser . xboxOne ? window . screen ? . width : null ;
2020-03-30 17:02:16 +08:00
2020-08-25 10:12:35 +09:00
/* eslint-enable compat/compat */
2020-03-30 17:02:16 +08:00
if ( options . maxVideoWidth ) {
maxVideoWidth = options . maxVideoWidth ;
}
2020-10-07 21:12:14 +09:00
const canPlayAacVideoAudio = videoTestElement . canPlayType ( 'video/mp4; codecs="avc1.640029, mp4a.40.2"' ) . replace ( /no/ , '' ) ;
2020-10-31 21:20:20 +08:00
const canPlayAc3VideoAudio = supportsAc3 ( videoTestElement ) ;
const canPlayEac3VideoAudio = supportsEac3 ( videoTestElement ) ;
const canPlayAc3VideoAudioInHls = supportsAc3InHls ( videoTestElement ) ;
2020-03-30 17:02:16 +08:00
2020-11-29 15:31:14 +08:00
// Transcoding codec is the first in hlsVideoAudioCodecs.
// Prefer AAC, MP3 to other codecs when audio transcoding.
2020-10-31 21:20:20 +08:00
if ( canPlayAacVideoAudio ) {
videoAudioCodecs . push ( 'aac' ) ;
2020-11-12 20:03:38 +08:00
hlsInTsVideoAudioCodecs . push ( 'aac' ) ;
hlsInFmp4VideoAudioCodecs . push ( 'aac' ) ;
2020-10-31 21:20:20 +08:00
}
2020-03-30 17:02:16 +08:00
if ( supportsMp3VideoAudio ) {
videoAudioCodecs . push ( 'mp3' ) ;
// PS4 fails to load HLS with mp3 audio
if ( ! browser . ps4 ) {
2020-11-12 20:03:38 +08:00
hlsInTsVideoAudioCodecs . push ( 'mp3' ) ;
2020-03-30 17:02:16 +08:00
}
2020-11-12 20:03:38 +08:00
hlsInFmp4VideoAudioCodecs . push ( 'mp3' ) ;
2020-03-30 17:02:16 +08:00
}
2020-11-29 15:31:14 +08:00
// For AC3/EAC3 remuxing.
// Do not use AC3 for audio transcoding unless AAC and MP3 are not supported.
2020-10-31 21:20:20 +08:00
if ( canPlayAc3VideoAudio ) {
2020-11-29 15:31:14 +08:00
videoAudioCodecs . push ( 'ac3' ) ;
if ( canPlayEac3VideoAudio ) {
videoAudioCodecs . push ( 'eac3' ) ;
}
2020-11-12 20:03:38 +08:00
2020-11-29 15:31:14 +08:00
if ( canPlayAc3VideoAudioInHls ) {
hlsInTsVideoAudioCodecs . push ( 'ac3' ) ;
hlsInFmp4VideoAudioCodecs . push ( 'ac3' ) ;
2020-11-12 20:03:38 +08:00
if ( canPlayEac3VideoAudio ) {
2020-11-29 15:31:14 +08:00
hlsInTsVideoAudioCodecs . push ( 'eac3' ) ;
hlsInFmp4VideoAudioCodecs . push ( 'eac3' ) ;
2020-03-30 17:02:16 +08:00
}
}
}
if ( supportsMp2VideoAudio ) {
videoAudioCodecs . push ( 'mp2' ) ;
2022-04-21 00:34:38 +02:00
hlsInTsVideoAudioCodecs . push ( 'mp2' ) ;
hlsInFmp4VideoAudioCodecs . push ( 'mp2' ) ;
2020-03-30 17:02:16 +08:00
}
2021-09-25 13:50:47 +03:00
let supportsDts = options . supportsDts ;
if ( supportsDts == null ) {
supportsDts = browser . tizen || browser . web0sVersion || videoTestElement . canPlayType ( 'video/mp4; codecs="dts-"' ) . replace ( /no/ , '' ) || videoTestElement . canPlayType ( 'video/mp4; codecs="dts+"' ) . replace ( /no/ , '' ) ;
2020-03-30 17:02:16 +08:00
2021-09-25 13:50:47 +03:00
// DTS audio is not supported by Samsung TV 2018+ (Tizen 4.0+) and LG TV 2020+ (webOS 5.0+) models
if ( browser . tizenVersion >= 4 || browser . web0sVersion >= 5 ) {
supportsDts = false ;
}
2020-03-30 17:02:16 +08:00
}
if ( supportsDts ) {
videoAudioCodecs . push ( 'dca' ) ;
videoAudioCodecs . push ( 'dts' ) ;
}
2020-06-06 19:16:48 +02:00
if ( browser . tizen || browser . web0s ) {
2020-03-30 17:02:16 +08:00
videoAudioCodecs . push ( 'pcm_s16le' ) ;
videoAudioCodecs . push ( 'pcm_s24le' ) ;
}
if ( options . supportsTrueHd ) {
videoAudioCodecs . push ( 'truehd' ) ;
}
2020-06-06 19:16:48 +02:00
if ( browser . tizen ) {
2020-03-30 17:02:16 +08:00
videoAudioCodecs . push ( 'aac_latm' ) ;
}
if ( canPlayAudioFormat ( 'opus' ) ) {
videoAudioCodecs . push ( 'opus' ) ;
webmAudioCodecs . push ( 'opus' ) ;
2021-05-19 21:07:36 +08:00
if ( browser . tizen ) {
hlsInTsVideoAudioCodecs . push ( 'opus' ) ;
}
2020-03-30 17:02:16 +08:00
}
if ( canPlayAudioFormat ( 'flac' ) ) {
videoAudioCodecs . push ( 'flac' ) ;
2020-11-12 20:03:38 +08:00
hlsInFmp4VideoAudioCodecs . push ( 'flac' ) ;
}
if ( canPlayAudioFormat ( 'alac' ) ) {
videoAudioCodecs . push ( 'alac' ) ;
hlsInFmp4VideoAudioCodecs . push ( 'alac' ) ;
2020-03-30 17:02:16 +08:00
}
videoAudioCodecs = videoAudioCodecs . filter ( function ( c ) {
return ( options . disableVideoAudioCodecs || [ ] ) . indexOf ( c ) === - 1 ;
} ) ;
2020-11-12 20:03:38 +08:00
hlsInTsVideoAudioCodecs = hlsInTsVideoAudioCodecs . filter ( function ( c ) {
return ( options . disableHlsVideoAudioCodecs || [ ] ) . indexOf ( c ) === - 1 ;
} ) ;
hlsInFmp4VideoAudioCodecs = hlsInFmp4VideoAudioCodecs . filter ( function ( c ) {
2020-03-30 17:02:16 +08:00
return ( options . disableHlsVideoAudioCodecs || [ ] ) . indexOf ( c ) === - 1 ;
} ) ;
2020-10-07 21:12:14 +09:00
const mp4VideoCodecs = [ ] ;
const webmVideoCodecs = [ ] ;
2020-11-12 20:03:38 +08:00
const hlsInTsVideoCodecs = [ ] ;
const hlsInFmp4VideoCodecs = [ ] ;
2020-11-20 17:33:35 +08:00
if ( ( browser . safari || browser . tizen || browser . web0s ) && canPlayHevc ( videoTestElement , options ) ) {
2020-11-12 20:03:38 +08:00
hlsInFmp4VideoCodecs . push ( 'hevc' ) ;
}
2020-03-30 17:02:16 +08:00
if ( canPlayH264 ( videoTestElement ) ) {
mp4VideoCodecs . push ( 'h264' ) ;
2020-11-12 20:03:38 +08:00
hlsInTsVideoCodecs . push ( 'h264' ) ;
2020-03-30 17:02:16 +08:00
2020-11-12 20:03:38 +08:00
if ( browser . safari || browser . tizen || browser . web0s ) {
hlsInFmp4VideoCodecs . push ( 'h264' ) ;
}
}
2020-03-30 17:02:16 +08:00
2020-11-12 20:03:38 +08:00
if ( canPlayHevc ( videoTestElement , options ) ) {
// safari is lying on HDR and 60fps videos, use fMP4 instead
if ( ! browser . safari ) {
mp4VideoCodecs . push ( 'hevc' ) ;
2020-03-30 17:02:16 +08:00
}
2021-03-20 11:56:51 +03:00
if ( browser . tizen || browser . web0s ) {
hlsInTsVideoCodecs . push ( 'hevc' ) ;
}
2020-03-30 17:02:16 +08:00
}
if ( supportsMpeg2Video ( ) ) {
mp4VideoCodecs . push ( 'mpeg2video' ) ;
}
2020-06-09 21:50:12 +02:00
if ( supportsVc1 ( videoTestElement ) ) {
2020-03-30 17:02:16 +08:00
mp4VideoCodecs . push ( 'vc1' ) ;
}
2020-06-06 19:16:48 +02:00
if ( browser . tizen ) {
2020-03-30 17:02:16 +08:00
mp4VideoCodecs . push ( 'msmpeg4v2' ) ;
}
if ( canPlayVp8 ) {
2020-06-03 12:26:25 -04:00
webmVideoCodecs . push ( 'vp8' ) ;
2020-03-30 17:02:16 +08:00
}
if ( canPlayVp9 ) {
mp4VideoCodecs . push ( 'vp9' ) ;
2020-06-03 12:26:25 -04:00
webmVideoCodecs . push ( 'vp9' ) ;
}
if ( testCanPlayAv1 ( videoTestElement ) ) {
mp4VideoCodecs . push ( 'av1' ) ;
webmVideoCodecs . push ( 'av1' ) ;
2020-03-30 17:02:16 +08:00
}
2020-06-06 19:16:48 +02:00
if ( canPlayVp8 || browser . tizen ) {
2020-03-30 17:02:16 +08:00
videoAudioCodecs . push ( 'vorbis' ) ;
}
2020-06-03 12:26:25 -04:00
if ( webmVideoCodecs . length ) {
profile . DirectPlayProfiles . push ( {
Container : 'webm' ,
Type : 'Video' ,
VideoCodec : webmVideoCodecs . join ( ',' ) ,
AudioCodec : webmAudioCodecs . join ( ',' )
} ) ;
}
2020-03-30 17:02:16 +08:00
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 ) {
2020-11-01 04:15:46 +08:00
profile . DirectPlayProfiles . push ( {
Container : audioFormat ,
Type : 'Audio'
} ) ;
2020-11-30 15:20:32 +08:00
// https://www.webmproject.org/about/faq/
if ( audioFormat === 'opus' || audioFormat === 'webma' ) {
2020-03-30 17:02:16 +08:00
profile . DirectPlayProfiles . push ( {
2020-11-01 04:15:46 +08:00
Container : 'webm' ,
2020-11-30 15:20:32 +08:00
AudioCodec : audioFormat ,
2020-03-30 17:02:16 +08:00
Type : 'Audio'
} ) ;
}
// aac also appears in the m4a and m4b container
2020-11-30 15:20:32 +08:00
// m4a/alac only works when using safari
2020-03-30 17:02:16 +08:00
if ( audioFormat === 'aac' || audioFormat === 'alac' ) {
profile . DirectPlayProfiles . push ( {
2020-11-30 15:20:32 +08:00
Container : 'm4a' ,
AudioCodec : audioFormat ,
Type : 'Audio'
} ) ;
profile . DirectPlayProfiles . push ( {
Container : 'm4b' ,
AudioCodec : audioFormat ,
2020-03-30 17:02:16 +08:00
Type : 'Audio'
} ) ;
}
} ) ;
profile . TranscodingProfiles = [ ] ;
2020-10-07 21:12:14 +09:00
const hlsBreakOnNonKeyFrames = browser . iOS || browser . osx || browser . edge || ! canPlayNativeHls ( ) ? true : false ;
2020-03-30 17:02:16 +08:00
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 ( )
} ) ;
} ) ;
2020-06-06 19:16:48 +02:00
if ( canPlayMkv && ! browser . tizen && options . enableMkvProgressive !== false ) {
2020-03-30 17:02:16 +08:00
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
} ) ;
}
2020-11-12 20:03:38 +08:00
if ( canPlayHls ( ) && options . enableHls !== false ) {
if ( hlsInFmp4VideoCodecs . length && hlsInFmp4VideoAudioCodecs . length && userSettings . preferFmp4HlsContainer ( ) && ( browser . safari || browser . tizen || browser . web0s ) ) {
profile . TranscodingProfiles . push ( {
Container : 'mp4' ,
Type : 'Video' ,
AudioCodec : hlsInFmp4VideoAudioCodecs . join ( ',' ) ,
VideoCodec : hlsInFmp4VideoCodecs . join ( ',' ) ,
Context : 'Streaming' ,
Protocol : 'hls' ,
MaxAudioChannels : physicalAudioChannels . toString ( ) ,
MinSegments : browser . iOS || browser . osx ? '2' : '1' ,
BreakOnNonKeyFrames : hlsBreakOnNonKeyFrames
} ) ;
}
if ( hlsInTsVideoCodecs . length && hlsInTsVideoAudioCodecs . length ) {
profile . TranscodingProfiles . push ( {
Container : 'ts' ,
Type : 'Video' ,
AudioCodec : hlsInTsVideoAudioCodecs . join ( ',' ) ,
VideoCodec : hlsInTsVideoCodecs . join ( ',' ) ,
Context : 'Streaming' ,
Protocol : 'hls' ,
MaxAudioChannels : physicalAudioChannels . toString ( ) ,
MinSegments : browser . iOS || browser . osx ? '2' : '1' ,
BreakOnNonKeyFrames : hlsBreakOnNonKeyFrames
} ) ;
}
2020-03-30 17:02:16 +08:00
}
2023-01-22 14:07:07 -05:00
// Progressive mp4 transcoding
if ( mp4VideoCodecs . length && videoAudioCodecs . length ) {
2021-08-20 17:48:14 -04:00
profile . TranscodingProfiles . push ( {
2023-01-22 14:07:07 -05:00
Container : 'mp4' ,
2021-08-20 17:48:14 -04:00
Type : 'Video' ,
2023-01-22 14:07:07 -05:00
AudioCodec : videoAudioCodecs . join ( ',' ) ,
VideoCodec : mp4VideoCodecs . join ( ',' ) ,
2021-08-20 17:48:14 -04:00
Context : 'Streaming' ,
Protocol : 'http' ,
MaxAudioChannels : physicalAudioChannels . toString ( )
} ) ;
2020-03-30 17:02:16 +08:00
}
profile . TranscodingProfiles . push ( {
Container : 'mp4' ,
Type : 'Video' ,
AudioCodec : videoAudioCodecs . join ( ',' ) ,
VideoCodec : 'h264' ,
Context : 'Static' ,
Protocol : 'http'
} ) ;
profile . ContainerProfiles = [ ] ;
profile . CodecProfiles = [ ] ;
2023-01-22 14:08:02 -05:00
const supportsSecondaryAudio = canPlaySecondaryAudio ( videoTestElement ) ;
2020-03-30 17:02:16 +08:00
2020-10-07 21:12:14 +09:00
const aacCodecProfileConditions = [ ] ;
2020-03-30 17:02:16 +08:00
// 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 ( 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
}
]
} ) ;
}
2020-10-07 21:12:14 +09:00
let maxH264Level = 42 ;
let h264Profiles = 'high|main|baseline|constrained baseline' ;
2020-03-30 17:02:16 +08:00
2020-06-06 19:16:48 +02:00
if ( browser . tizen || browser . web0s ||
2020-03-30 17:02:16 +08:00
videoTestElement . canPlayType ( 'video/mp4; codecs="avc1.640833"' ) . replace ( /no/ , '' ) ) {
maxH264Level = 51 ;
}
// Support H264 Level 52 (Tizen 5.0) - app only
2021-10-26 20:40:51 +02:00
if ( ( browser . tizenVersion >= 5 && window . NativeShell ) ||
videoTestElement . canPlayType ( 'video/mp4; codecs="avc1.640834"' ) . replace ( /no/ , '' ) ) {
2020-03-30 17:02:16 +08:00
maxH264Level = 52 ;
}
2022-10-03 14:22:02 -04:00
if ( ( browser . tizen ||
videoTestElement . canPlayType ( 'video/mp4; codecs="avc1.6e0033"' ) . replace ( /no/ , '' ) )
2020-03-30 17:02:16 +08:00
// These tests are passing in safari, but playback is failing
2022-10-03 14:22:02 -04:00
&& ! browser . safari && ! browser . iOS && ! browser . web0s && ! browser . edge && ! browser . mobile
) {
h264Profiles += '|high 10' ;
2020-03-30 17:02:16 +08:00
}
2020-11-12 20:03:38 +08:00
let maxHevcLevel = 120 ;
let hevcProfiles = 'main' ;
// hevc main level 4.1
if ( videoTestElement . canPlayType ( 'video/mp4; codecs="hvc1.1.4.L123"' ) . replace ( /no/ , '' ) ||
videoTestElement . canPlayType ( 'video/mp4; codecs="hev1.1.4.L123"' ) . replace ( /no/ , '' ) ) {
maxHevcLevel = 123 ;
}
// hevc main10 level 4.1
if ( videoTestElement . canPlayType ( 'video/mp4; codecs="hvc1.2.4.L123"' ) . replace ( /no/ , '' ) ||
videoTestElement . canPlayType ( 'video/mp4; codecs="hev1.2.4.L123"' ) . replace ( /no/ , '' ) ) {
maxHevcLevel = 123 ;
hevcProfiles = 'main|main 10' ;
}
// hevc main10 level 5.1
if ( videoTestElement . canPlayType ( 'video/mp4; codecs="hvc1.2.4.L153"' ) . replace ( /no/ , '' ) ||
videoTestElement . canPlayType ( 'video/mp4; codecs="hev1.2.4.L153"' ) . replace ( /no/ , '' ) ) {
maxHevcLevel = 153 ;
hevcProfiles = 'main|main 10' ;
}
// hevc main10 level 6.1
if ( videoTestElement . canPlayType ( 'video/mp4; codecs="hvc1.2.4.L183"' ) . replace ( /no/ , '' ) ||
2020-11-12 20:35:56 +08:00
videoTestElement . canPlayType ( 'video/mp4; codecs="hev1.2.4.L183"' ) . replace ( /no/ , '' ) ) {
2020-11-12 20:03:38 +08:00
maxHevcLevel = 183 ;
hevcProfiles = 'main|main 10' ;
}
2022-06-17 13:10:36 -04:00
const h264VideoRangeTypes = 'SDR' ;
let hevcVideoRangeTypes = 'SDR' ;
let vp9VideoRangeTypes = 'SDR' ;
let av1VideoRangeTypes = 'SDR' ;
if ( browser . safari && ( ( browser . iOS && browser . iOSVersion >= 11 ) || browser . osx ) ) {
hevcVideoRangeTypes += '|HDR10|HLG' ;
if ( ( browser . iOS && browser . iOSVersion >= 13 ) || browser . osx ) {
hevcVideoRangeTypes += '|DOVI' ;
}
}
if ( browser . tizen || browser . web0s ) {
hevcVideoRangeTypes += '|HDR10|HLG|DOVI' ;
vp9VideoRangeTypes += '|HDR10|HLG' ;
av1VideoRangeTypes += '|HDR10|HLG' ;
}
if ( browser . edgeChromium || browser . chrome || browser . firefox ) {
vp9VideoRangeTypes += '|HDR10|HLG' ;
av1VideoRangeTypes += '|HDR10|HLG' ;
}
2020-07-27 20:06:08 +03:00
const h264CodecProfileConditions = [
{
Condition : 'NotEquals' ,
Property : 'IsAnamorphic' ,
Value : 'true' ,
IsRequired : false
} ,
{
Condition : 'EqualsAny' ,
Property : 'VideoProfile' ,
Value : h264Profiles ,
IsRequired : false
} ,
2022-06-17 13:10:36 -04:00
{
Condition : 'EqualsAny' ,
Property : 'VideoRangeType' ,
Value : h264VideoRangeTypes ,
IsRequired : false
} ,
2020-07-27 20:06:08 +03:00
{
Condition : 'LessThanEqual' ,
Property : 'VideoLevel' ,
Value : maxH264Level . toString ( ) ,
IsRequired : false
}
] ;
2020-03-30 17:02:16 +08:00
2020-11-12 20:03:38 +08:00
const hevcCodecProfileConditions = [
{
Condition : 'NotEquals' ,
Property : 'IsAnamorphic' ,
Value : 'true' ,
IsRequired : false
} ,
{
Condition : 'EqualsAny' ,
Property : 'VideoProfile' ,
Value : hevcProfiles ,
IsRequired : false
} ,
2022-06-17 13:10:36 -04:00
{
Condition : 'EqualsAny' ,
Property : 'VideoRangeType' ,
Value : hevcVideoRangeTypes ,
IsRequired : false
} ,
2020-11-12 20:03:38 +08:00
{
Condition : 'LessThanEqual' ,
Property : 'VideoLevel' ,
Value : maxHevcLevel . toString ( ) ,
IsRequired : false
}
] ;
2022-06-17 13:10:36 -04:00
const vp9CodecProfileConditions = [
{
Condition : 'EqualsAny' ,
Property : 'VideoRangeType' ,
Value : vp9VideoRangeTypes ,
IsRequired : false
}
] ;
const av1CodecProfileConditions = [
{
Condition : 'EqualsAny' ,
Property : 'VideoRangeType' ,
Value : av1VideoRangeTypes ,
IsRequired : false
}
] ;
2020-06-06 19:16:48 +02:00
if ( ! browser . edgeUwp && ! browser . tizen && ! browser . web0s ) {
2020-07-27 20:06:08 +03:00
h264CodecProfileConditions . push ( {
2020-06-06 19:16:48 +02:00
Condition : 'NotEquals' ,
Property : 'IsInterlaced' ,
Value : 'true' ,
IsRequired : false
} ) ;
2020-11-12 20:03:38 +08:00
hevcCodecProfileConditions . push ( {
Condition : 'NotEquals' ,
Property : 'IsInterlaced' ,
Value : 'true' ,
IsRequired : false
} ) ;
2020-03-30 17:02:16 +08:00
}
if ( maxVideoWidth ) {
2020-07-27 20:06:08 +03:00
h264CodecProfileConditions . push ( {
2020-03-30 17:02:16 +08:00
Condition : 'LessThanEqual' ,
Property : 'Width' ,
Value : maxVideoWidth . toString ( ) ,
IsRequired : false
} ) ;
2020-11-12 20:03:38 +08:00
hevcCodecProfileConditions . push ( {
Condition : 'LessThanEqual' ,
Property : 'Width' ,
Value : maxVideoWidth . toString ( ) ,
IsRequired : false
} ) ;
2020-03-30 17:02:16 +08:00
}
2020-10-07 21:12:14 +09:00
const globalMaxVideoBitrate = ( getGlobalMaxVideoBitrate ( ) || '' ) . toString ( ) ;
2020-03-30 17:02:16 +08:00
2020-10-07 21:12:14 +09:00
const h264MaxVideoBitrate = globalMaxVideoBitrate ;
2020-03-30 17:02:16 +08:00
2020-11-12 20:03:38 +08:00
const hevcMaxVideoBitrate = globalMaxVideoBitrate ;
2020-03-30 17:02:16 +08:00
if ( h264MaxVideoBitrate ) {
2020-07-27 20:06:08 +03:00
h264CodecProfileConditions . push ( {
2020-03-30 17:02:16 +08:00
Condition : 'LessThanEqual' ,
Property : 'VideoBitrate' ,
Value : h264MaxVideoBitrate ,
IsRequired : true
} ) ;
}
2020-11-12 20:03:38 +08:00
if ( hevcMaxVideoBitrate ) {
hevcCodecProfileConditions . push ( {
Condition : 'LessThanEqual' ,
Property : 'VideoBitrate' ,
Value : hevcMaxVideoBitrate ,
IsRequired : true
} ) ;
}
2020-07-27 20:06:08 +03:00
// On iOS 12.x, for TS container max h264 level is 4.2
if ( browser . iOS && browser . iOSVersion < 13 ) {
const codecProfile = {
Type : 'Video' ,
Codec : 'h264' ,
Container : 'ts' ,
Conditions : h264CodecProfileConditions . filter ( ( condition ) => {
return condition . Property !== 'VideoLevel' ;
} )
} ;
codecProfile . Conditions . push ( {
Condition : 'LessThanEqual' ,
Property : 'VideoLevel' ,
Value : '42' ,
IsRequired : false
} ) ;
profile . CodecProfiles . push ( codecProfile ) ;
}
profile . CodecProfiles . push ( {
Type : 'Video' ,
Codec : 'h264' ,
Conditions : h264CodecProfileConditions
} ) ;
2020-11-12 20:03:38 +08:00
profile . CodecProfiles . push ( {
Type : 'Video' ,
Codec : 'hevc' ,
Conditions : hevcCodecProfileConditions
} ) ;
2022-06-17 13:10:36 -04:00
profile . CodecProfiles . push ( {
Type : 'Video' ,
Codec : 'vp9' ,
Conditions : vp9CodecProfileConditions
} ) ;
profile . CodecProfiles . push ( {
Type : 'Video' ,
Codec : 'av1' ,
Conditions : av1CodecProfileConditions
} ) ;
2020-10-07 21:12:14 +09:00
const globalVideoConditions = [ ] ;
2020-03-30 17:02:16 +08:00
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
} ) ;
}
// Subtitle profiles
// External vtt or burn in
profile . SubtitleProfiles = [ ] ;
2021-04-26 20:35:17 -04:00
const subtitleBurninSetting = appSettings . get ( 'subtitleburnin' ) ;
2021-05-01 16:56:37 -04:00
if ( subtitleBurninSetting !== 'all' ) {
2021-04-25 20:31:19 -04:00
if ( supportsTextTracks ( ) ) {
profile . SubtitleProfiles . push ( {
Format : 'vtt' ,
Method : 'External'
} ) ;
}
2021-05-01 16:56:37 -04:00
if ( options . enableSsaRender !== false && ! options . isRetry && subtitleBurninSetting !== 'allcomplexformats' ) {
2021-04-25 20:31:19 -04:00
profile . SubtitleProfiles . push ( {
Format : 'ass' ,
Method : 'External'
} ) ;
profile . SubtitleProfiles . push ( {
Format : 'ssa' ,
Method : 'External'
} ) ;
}
2020-04-27 23:09:59 +03:00
}
2020-03-30 17:02:16 +08:00
profile . ResponseProfiles = [ ] ;
profile . ResponseProfiles . push ( {
Type : 'Video' ,
Container : 'm4v' ,
MimeType : 'video/mp4'
} ) ;
return profile ;
2020-10-17 20:04:52 +01:00
}
2020-08-16 20:24:45 +02:00
/* eslint-enable indent */