Home Reference Source

src/config.ts

  1. import AbrController from './controller/abr-controller';
  2. import AudioStreamController from './controller/audio-stream-controller';
  3. import AudioTrackController from './controller/audio-track-controller';
  4. import { SubtitleStreamController } from './controller/subtitle-stream-controller';
  5. import SubtitleTrackController from './controller/subtitle-track-controller';
  6. import BufferController from './controller/buffer-controller';
  7. import { TimelineController } from './controller/timeline-controller';
  8. import CapLevelController from './controller/cap-level-controller';
  9. import FPSController from './controller/fps-controller';
  10. import EMEController from './controller/eme-controller';
  11. import XhrLoader from './utils/xhr-loader';
  12. import FetchLoader, { fetchSupported } from './utils/fetch-loader';
  13. import Cues from './utils/cues';
  14. import { requestMediaKeySystemAccess } from './utils/mediakeys-helper';
  15. import { logger } from './utils/logger';
  16.  
  17. import type { CuesInterface } from './utils/cues';
  18. import type { MediaKeyFunc } from './utils/mediakeys-helper';
  19. import type {
  20. FragmentLoaderContext,
  21. Loader,
  22. LoaderContext,
  23. PlaylistLoaderContext,
  24. } from './types/loader';
  25.  
  26. export type ABRControllerConfig = {
  27. abrEwmaFastLive: number;
  28. abrEwmaSlowLive: number;
  29. abrEwmaFastVoD: number;
  30. abrEwmaSlowVoD: number;
  31. abrEwmaDefaultEstimate: number;
  32. abrBandWidthFactor: number;
  33. abrBandWidthUpFactor: number;
  34. abrMaxWithRealBitrate: boolean;
  35. maxStarvationDelay: number;
  36. maxLoadingDelay: number;
  37. };
  38.  
  39. export type BufferControllerConfig = {
  40. appendErrorMaxRetry: number;
  41. backBufferLength: number;
  42. liveDurationInfinity: boolean;
  43. liveBackBufferLength: number | null;
  44. };
  45.  
  46. export type CapLevelControllerConfig = {
  47. capLevelToPlayerSize: boolean;
  48. };
  49.  
  50. export type DRMSystemOptions = {
  51. audioRobustness?: string;
  52. videoRobustness?: string;
  53. };
  54.  
  55. export type EMEControllerConfig = {
  56. licenseXhrSetup?: (xhr: XMLHttpRequest, url: string) => void;
  57. licenseResponseCallback?: (xhr: XMLHttpRequest, url: string) => ArrayBuffer;
  58. emeEnabled: boolean;
  59. widevineLicenseUrl?: string;
  60. drmSystemOptions: DRMSystemOptions;
  61. requestMediaKeySystemAccessFunc: MediaKeyFunc | null;
  62. };
  63.  
  64. export type FragmentLoaderConfig = {
  65. fLoader?: { new (confg: HlsConfig): Loader<FragmentLoaderContext> };
  66.  
  67. fragLoadingTimeOut: number;
  68. fragLoadingMaxRetry: number;
  69. fragLoadingRetryDelay: number;
  70. fragLoadingMaxRetryTimeout: number;
  71. };
  72.  
  73. export type FPSControllerConfig = {
  74. capLevelOnFPSDrop: boolean;
  75. fpsDroppedMonitoringPeriod: number;
  76. fpsDroppedMonitoringThreshold: number;
  77. };
  78.  
  79. export type LevelControllerConfig = {
  80. startLevel?: number;
  81. };
  82.  
  83. export type MP4RemuxerConfig = {
  84. stretchShortVideoTrack: boolean;
  85. maxAudioFramesDrift: number;
  86. };
  87.  
  88. export type PlaylistLoaderConfig = {
  89. pLoader?: { new (confg: HlsConfig): Loader<PlaylistLoaderContext> };
  90.  
  91. manifestLoadingTimeOut: number;
  92. manifestLoadingMaxRetry: number;
  93. manifestLoadingRetryDelay: number;
  94. manifestLoadingMaxRetryTimeout: number;
  95.  
  96. levelLoadingTimeOut: number;
  97. levelLoadingMaxRetry: number;
  98. levelLoadingRetryDelay: number;
  99. levelLoadingMaxRetryTimeout: number;
  100. };
  101.  
  102. export type StreamControllerConfig = {
  103. autoStartLoad: boolean;
  104. startPosition: number;
  105. defaultAudioCodec?: string;
  106. initialLiveManifestSize: number;
  107. maxBufferLength: number;
  108. maxBufferSize: number;
  109. maxBufferHole: number;
  110. highBufferWatchdogPeriod: number;
  111. nudgeOffset: number;
  112. nudgeMaxRetry: number;
  113. maxFragLookUpTolerance: number;
  114. maxMaxBufferLength: number;
  115. startFragPrefetch: boolean;
  116. testBandwidth: boolean;
  117. };
  118.  
  119. export type LatencyControllerConfig = {
  120. liveSyncDurationCount: number;
  121. liveMaxLatencyDurationCount: number;
  122. liveSyncDuration?: number;
  123. liveMaxLatencyDuration?: number;
  124. maxLiveSyncPlaybackRate: number;
  125. };
  126.  
  127. export type TimelineControllerConfig = {
  128. cueHandler: CuesInterface;
  129. enableCEA708Captions: boolean;
  130. enableWebVTT: boolean;
  131. enableIMSC1: boolean;
  132. captionsTextTrack1Label: string;
  133. captionsTextTrack1LanguageCode: string;
  134. captionsTextTrack2Label: string;
  135. captionsTextTrack2LanguageCode: string;
  136. captionsTextTrack3Label: string;
  137. captionsTextTrack3LanguageCode: string;
  138. captionsTextTrack4Label: string;
  139. captionsTextTrack4LanguageCode: string;
  140. renderTextTracksNatively: boolean;
  141. };
  142.  
  143. export type TSDemuxerConfig = {
  144. forceKeyFrameOnDiscontinuity: boolean;
  145. };
  146.  
  147. export type HlsConfig = {
  148. debug: boolean;
  149. enableWorker: boolean;
  150. enableSoftwareAES: boolean;
  151. minAutoBitrate: number;
  152. loader: { new (confg: HlsConfig): Loader<LoaderContext> };
  153. xhrSetup?: (xhr: XMLHttpRequest, url: string) => void;
  154.  
  155. // Alt Audio
  156. audioStreamController?: typeof AudioStreamController;
  157. audioTrackController?: typeof AudioTrackController;
  158. // Subtitle
  159. subtitleStreamController?: typeof SubtitleStreamController;
  160. subtitleTrackController?: typeof SubtitleTrackController;
  161. timelineController?: typeof TimelineController;
  162. // EME
  163. emeController?: typeof EMEController;
  164.  
  165. abrController: typeof AbrController;
  166. bufferController: typeof BufferController;
  167. capLevelController: typeof CapLevelController;
  168. fpsController: typeof FPSController;
  169. progressive: boolean;
  170. lowLatencyMode: boolean;
  171. } & ABRControllerConfig &
  172. BufferControllerConfig &
  173. CapLevelControllerConfig &
  174. EMEControllerConfig &
  175. FPSControllerConfig &
  176. FragmentLoaderConfig &
  177. LevelControllerConfig &
  178. MP4RemuxerConfig &
  179. PlaylistLoaderConfig &
  180. StreamControllerConfig &
  181. LatencyControllerConfig &
  182. TimelineControllerConfig &
  183. TSDemuxerConfig;
  184.  
  185. // If possible, keep hlsDefaultConfig shallow
  186. // It is cloned whenever a new Hls instance is created, by keeping the config
  187. // shallow the properties are cloned, and we don't end up manipulating the default
  188. export const hlsDefaultConfig: HlsConfig = {
  189. autoStartLoad: true, // used by stream-controller
  190. startPosition: -1, // used by stream-controller
  191. defaultAudioCodec: undefined, // used by stream-controller
  192. debug: false, // used by logger
  193. capLevelOnFPSDrop: false, // used by fps-controller
  194. capLevelToPlayerSize: false, // used by cap-level-controller
  195. initialLiveManifestSize: 1, // used by stream-controller
  196. maxBufferLength: 30, // used by stream-controller
  197. backBufferLength: Infinity, // used by buffer-controller
  198. maxBufferSize: 60 * 1000 * 1000, // used by stream-controller
  199. maxBufferHole: 0.1, // used by stream-controller
  200. highBufferWatchdogPeriod: 2, // used by stream-controller
  201. nudgeOffset: 0.1, // used by stream-controller
  202. nudgeMaxRetry: 3, // used by stream-controller
  203. maxFragLookUpTolerance: 0.25, // used by stream-controller
  204. liveSyncDurationCount: 3, // used by latency-controller
  205. liveMaxLatencyDurationCount: Infinity, // used by latency-controller
  206. liveSyncDuration: undefined, // used by latency-controller
  207. liveMaxLatencyDuration: undefined, // used by latency-controller
  208. maxLiveSyncPlaybackRate: 1, // used by latency-controller
  209. liveDurationInfinity: false, // used by buffer-controller
  210. liveBackBufferLength: null, // used by buffer-controller
  211. maxMaxBufferLength: 600, // used by stream-controller
  212. enableWorker: true, // used by demuxer
  213. enableSoftwareAES: true, // used by decrypter
  214. manifestLoadingTimeOut: 10000, // used by playlist-loader
  215. manifestLoadingMaxRetry: 1, // used by playlist-loader
  216. manifestLoadingRetryDelay: 1000, // used by playlist-loader
  217. manifestLoadingMaxRetryTimeout: 64000, // used by playlist-loader
  218. startLevel: undefined, // used by level-controller
  219. levelLoadingTimeOut: 10000, // used by playlist-loader
  220. levelLoadingMaxRetry: 4, // used by playlist-loader
  221. levelLoadingRetryDelay: 1000, // used by playlist-loader
  222. levelLoadingMaxRetryTimeout: 64000, // used by playlist-loader
  223. fragLoadingTimeOut: 20000, // used by fragment-loader
  224. fragLoadingMaxRetry: 6, // used by fragment-loader
  225. fragLoadingRetryDelay: 1000, // used by fragment-loader
  226. fragLoadingMaxRetryTimeout: 64000, // used by fragment-loader
  227. startFragPrefetch: false, // used by stream-controller
  228. fpsDroppedMonitoringPeriod: 5000, // used by fps-controller
  229. fpsDroppedMonitoringThreshold: 0.2, // used by fps-controller
  230. appendErrorMaxRetry: 3, // used by buffer-controller
  231. loader: XhrLoader,
  232. // loader: FetchLoader,
  233. fLoader: undefined, // used by fragment-loader
  234. pLoader: undefined, // used by playlist-loader
  235. xhrSetup: undefined, // used by xhr-loader
  236. licenseXhrSetup: undefined, // used by eme-controller
  237. licenseResponseCallback: undefined, // used by eme-controller
  238. abrController: AbrController,
  239. bufferController: BufferController,
  240. capLevelController: CapLevelController,
  241. fpsController: FPSController,
  242. stretchShortVideoTrack: false, // used by mp4-remuxer
  243. maxAudioFramesDrift: 1, // used by mp4-remuxer
  244. forceKeyFrameOnDiscontinuity: true, // used by ts-demuxer
  245. abrEwmaFastLive: 3, // used by abr-controller
  246. abrEwmaSlowLive: 9, // used by abr-controller
  247. abrEwmaFastVoD: 3, // used by abr-controller
  248. abrEwmaSlowVoD: 9, // used by abr-controller
  249. abrEwmaDefaultEstimate: 5e5, // 500 kbps // used by abr-controller
  250. abrBandWidthFactor: 0.95, // used by abr-controller
  251. abrBandWidthUpFactor: 0.7, // used by abr-controller
  252. abrMaxWithRealBitrate: false, // used by abr-controller
  253. maxStarvationDelay: 4, // used by abr-controller
  254. maxLoadingDelay: 4, // used by abr-controller
  255. minAutoBitrate: 0, // used by hls
  256. emeEnabled: false, // used by eme-controller
  257. widevineLicenseUrl: undefined, // used by eme-controller
  258. drmSystemOptions: {}, // used by eme-controller
  259. requestMediaKeySystemAccessFunc: requestMediaKeySystemAccess, // used by eme-controller
  260. testBandwidth: true,
  261. progressive: false,
  262. lowLatencyMode: true,
  263.  
  264. // Dynamic Modules
  265. ...timelineConfig(),
  266. subtitleStreamController: __USE_SUBTITLES__
  267. ? SubtitleStreamController
  268. : undefined,
  269. subtitleTrackController: __USE_SUBTITLES__
  270. ? SubtitleTrackController
  271. : undefined,
  272. timelineController: __USE_SUBTITLES__ ? TimelineController : undefined,
  273. audioStreamController: __USE_ALT_AUDIO__ ? AudioStreamController : undefined,
  274. audioTrackController: __USE_ALT_AUDIO__ ? AudioTrackController : undefined,
  275. emeController: __USE_EME_DRM__ ? EMEController : undefined,
  276. };
  277.  
  278. function timelineConfig(): TimelineControllerConfig {
  279. return {
  280. cueHandler: Cues, // used by timeline-controller
  281. enableCEA708Captions: __USE_SUBTITLES__, // used by timeline-controller
  282. enableWebVTT: __USE_SUBTITLES__, // used by timeline-controller
  283. enableIMSC1: __USE_SUBTITLES__, // used by timeline-controller
  284. captionsTextTrack1Label: 'English', // used by timeline-controller
  285. captionsTextTrack1LanguageCode: 'en', // used by timeline-controller
  286. captionsTextTrack2Label: 'Spanish', // used by timeline-controller
  287. captionsTextTrack2LanguageCode: 'es', // used by timeline-controller
  288. captionsTextTrack3Label: 'Unknown CC', // used by timeline-controller
  289. captionsTextTrack3LanguageCode: '', // used by timeline-controller
  290. captionsTextTrack4Label: 'Unknown CC', // used by timeline-controller
  291. captionsTextTrack4LanguageCode: '', // used by timeline-controller
  292. renderTextTracksNatively: true,
  293. };
  294. }
  295.  
  296. export function mergeConfig(
  297. defaultConfig: HlsConfig,
  298. userConfig: Partial<HlsConfig>
  299. ): HlsConfig {
  300. if (
  301. (userConfig.liveSyncDurationCount ||
  302. userConfig.liveMaxLatencyDurationCount) &&
  303. (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)
  304. ) {
  305. throw new Error(
  306. "Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration"
  307. );
  308. }
  309.  
  310. if (
  311. userConfig.liveMaxLatencyDurationCount !== undefined &&
  312. (userConfig.liveSyncDurationCount === undefined ||
  313. userConfig.liveMaxLatencyDurationCount <=
  314. userConfig.liveSyncDurationCount)
  315. ) {
  316. throw new Error(
  317. 'Illegal hls.js config: "liveMaxLatencyDurationCount" must be greater than "liveSyncDurationCount"'
  318. );
  319. }
  320.  
  321. if (
  322. userConfig.liveMaxLatencyDuration !== undefined &&
  323. (userConfig.liveSyncDuration === undefined ||
  324. userConfig.liveMaxLatencyDuration <= userConfig.liveSyncDuration)
  325. ) {
  326. throw new Error(
  327. 'Illegal hls.js config: "liveMaxLatencyDuration" must be greater than "liveSyncDuration"'
  328. );
  329. }
  330.  
  331. return Object.assign({}, defaultConfig, userConfig);
  332. }
  333.  
  334. export function enableStreamingMode(config) {
  335. const currentLoader = config.loader;
  336. if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
  337. // If a developer has configured their own loader, respect that choice
  338. logger.log(
  339. '[config]: Custom loader detected, cannot enable progressive streaming'
  340. );
  341. config.progressive = false;
  342. } else {
  343. const canStreamProgressively = fetchSupported();
  344. if (canStreamProgressively) {
  345. config.loader = FetchLoader;
  346. config.progressive = true;
  347. config.enableSoftwareAES = true;
  348. logger.log('[config]: Progressive streaming enabled, using FetchLoader');
  349. }
  350. }
  351. }