{
  "version": 3,
  "sources": ["../src/index.ts", "../src/hls.ts", "../src/errors.ts", "../src/types.ts", "../lang/en.json", "../src/util.ts", "../src/autoplay.ts", "../src/preload.ts", "../src/min-preload.ts", "../src/media-tracks.ts", "../src/text-tracks.ts", "../src/pdt.ts", "../src/request-errors.ts", "../src/min-cap-level-controller.ts", "../src/webkit-fairplay.ts", "../src/eme-fairplay.ts"],
  "sourcesContent": ["import type { ValueOf, PlaybackCore, MuxMediaProps, MuxMediaPropsInternal, MuxMediaPropTypes } from './types';\nimport mux, { ErrorEvent } from 'mux-embed';\nimport Hls from './hls';\nimport type { HlsInterface } from './hls';\nimport { CapLevelController, ErrorData, HlsConfig } from 'hls.js';\nimport { MediaError, MuxErrorCategory, MuxErrorCode, errorCategoryToTokenNameOrPrefix } from './errors';\nimport { setupAutoplay } from './autoplay';\nimport { setupPreload } from './preload';\nimport { setupMinPreload, setupInitialEstimate } from './min-preload';\nimport { setupMediaTracks } from './media-tracks';\nimport {\n  setupTextTracks,\n  addTextTrack,\n  removeTextTrack,\n  getTextTrack,\n  addCuePoints,\n  getCuePoints,\n  getActiveCuePoint,\n  setupCuePoints,\n  addChapters,\n  getChapters,\n  getActiveChapter,\n  setupChapters,\n} from './text-tracks';\nimport { getStartDate, getCurrentPdt } from './pdt';\nimport {\n  inSeekableRange,\n  toPlaybackIdParts,\n  getType,\n  toStreamTypeFromPlaylistType,\n  toTargetLiveWindowFromPlaylistType,\n  addEventListenerWithTeardown,\n  i18n,\n  parseJwt,\n  isRelativeUrl,\n  getFirstMediaPlaylistUrl,\n  toAbsoluteUrl,\n} from './util';\nimport { StreamTypes, PlaybackTypes, ExtensionMimeTypeMap, CmcdTypes, HlsPlaylistTypes, MediaTypes } from './types';\nimport { getErrorFromResponse, MuxJWTAud } from './request-errors';\nimport MinCapLevelController from './min-cap-level-controller';\nimport { setupWebkitNativeFairplayDRM } from './webkit-fairplay';\nimport { setupEmeNativeFairplayDRM } from './eme-fairplay';\n\nexport {\n  mux,\n  Hls,\n  MediaError,\n  MuxErrorCategory,\n  MuxErrorCode,\n  errorCategoryToTokenNameOrPrefix,\n  MuxJWTAud,\n  addTextTrack,\n  removeTextTrack,\n  getTextTrack,\n  addCuePoints,\n  getCuePoints,\n  getActiveCuePoint,\n  setupCuePoints,\n  addChapters,\n  getChapters,\n  getActiveChapter,\n  setupChapters,\n  getStartDate,\n  getCurrentPdt,\n  toPlaybackIdParts,\n  i18n,\n  parseJwt,\n  MinCapLevelController,\n};\nexport * from './types';\n\nconst DRMType = {\n  FAIRPLAY: 'fairplay',\n  PLAYREADY: 'playready',\n  WIDEVINE: 'widevine',\n} as const;\n\ntype DRMTypeValue = (typeof DRMType)[keyof typeof DRMType];\nexport const toDRMTypeFromKeySystem = (keySystem: string): DRMTypeValue | undefined => {\n  if (keySystem.includes('fps')) return DRMType.FAIRPLAY;\n  if (keySystem.includes('playready')) return DRMType.PLAYREADY;\n  if (keySystem.includes('widevine')) return DRMType.WIDEVINE;\n  return undefined;\n};\n\n/**\n * Fetches the first media playlist from a multivariant (master) HLS playlist string.\n *\n * The first `#EXT-X-STREAM-INF` entry is selected. If its URL is relative, it is\n * resolved against `masterPlaylistUrl`; absolute URLs are used as-is.\n *\n * @param multivariantPlaylist - The raw text of the multivariant playlist.\n * @param masterPlaylistUrl - The URL the multivariant playlist was fetched from.\n *   Required when the media playlist URL in the manifest is relative. If this is\n *   itself a relative URL it is resolved against `window.location.href` first.\n * @returns A promise that resolves with the media playlist text.\n * @rejects {Error} If no `#EXT-X-STREAM-INF` entry is found in the playlist.\n * @rejects {Error} If the media playlist URL is relative and `masterPlaylistUrl` is not provided.\n * @rejects {Response} If the fetch response status is not 200.\n */\nexport const getMediaPlaylistFromMultivariantPlaylist = (\n  multivariantPlaylist: string,\n  masterPlaylistUrl?: string | URL\n) => {\n  const mediaPlaylistUrl = getFirstMediaPlaylistUrl(multivariantPlaylist);\n\n  if (!mediaPlaylistUrl) {\n    return Promise.reject(new Error('No media playlist URL found in multivariant playlist'));\n  }\n\n  if (isRelativeUrl(mediaPlaylistUrl) && !masterPlaylistUrl) {\n    return Promise.reject(new Error('masterPlaylistUrl is required to resolve relative media playlist URL'));\n  }\n\n  let fetchUrl: URL | string;\n  try {\n    fetchUrl = toAbsoluteUrl(mediaPlaylistUrl, masterPlaylistUrl);\n  } catch (e) {\n    return Promise.reject(e);\n  }\n\n  return fetch(fetchUrl).then((resp) => {\n    if (resp.status !== 200) {\n      return Promise.reject(resp);\n    }\n    return resp.text();\n  });\n};\n\nexport const getMultivariantPlaylistSessionData = (playlist: string) => {\n  // See https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-12#section-4.4.6.4\n  const sessionDataLines = playlist.split('\\n').filter((line) => line.startsWith('#EXT-X-SESSION-DATA'));\n  if (!sessionDataLines.length) return {};\n\n  const sessionData: Record<string, Record<string, string>> = {};\n\n  for (const line of sessionDataLines) {\n    const sessionDataAttrs = parseTagAttributes(line);\n    const dataId = sessionDataAttrs['DATA-ID'];\n    if (!dataId) continue;\n\n    sessionData[dataId] = { ...sessionDataAttrs };\n  }\n\n  return {\n    sessionData,\n  };\n};\n\n// matches all HLS attribute name=value pairs, with or without quotes, using per spec rules\n// for matching AttributeName (See: https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-17#section-4.2)\nconst ATTR_LIST_REGEX = /([A-Z0-9-]+)=\"?(.*?)\"?(?:,|$)/g;\nexport function parseTagAttributes(str: string) {\n  const matches = [...str.matchAll(ATTR_LIST_REGEX)];\n  return Object.fromEntries(matches.map(([, key, value]) => [key, value]));\n}\n\nexport const getStreamInfoFromPlaylist = (playlist: string) => {\n  const playlistLines = playlist.split('\\n');\n  const typeLine = playlistLines.find((line) => line.startsWith('#EXT-X-PLAYLIST-TYPE')) ?? '';\n  const playlistType = typeLine.split(':')[1]?.trim() as HlsPlaylistTypes;\n  const streamType = toStreamTypeFromPlaylistType(playlistType);\n  const targetLiveWindow = toTargetLiveWindowFromPlaylistType(playlistType);\n\n  // Computation of the live edge start offset per media-ui-extensions proposal. See: https://github.com/video-dev/media-ui-extensions/blob/main/proposals/0007-live-edge.md#recommended-computation-for-rfc8216bis12-aka-hls (CJP)\n  let liveEdgeStartOffset = undefined;\n\n  if (streamType === StreamTypes.LIVE) {\n    // Required if playlist contains one or more EXT-X-PART tags. See: https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-12#section-4.4.3.7 (CJP)\n    const partInfLine = playlistLines.find((line) => line.startsWith('#EXT-X-PART-INF'));\n    const lowLatency = !!partInfLine;\n\n    if (lowLatency) {\n      // The EXT-X-PART-INF only has one in-spec named attribute, PART-TARGET, which is required,\n      // so parsing & casting presumptuously here. See spec link above for more info. (CJP)\n      const partTarget = +partInfLine.split(':')[1].split('=')[1];\n      liveEdgeStartOffset = partTarget * 2;\n    } else {\n      // This is required for all media playlists. See: https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-12#section-4.4.3.1 (CJP)\n      const targetDurationLine = playlistLines.find((line) => line.startsWith('#EXT-X-TARGETDURATION')) as string;\n      // EXT-X-TARGETDURATION has exactly one unnamed attribute that represents the target duration value, which is required,\n      // so parsing and casting presumptuously here. See spec link above for more info. (CJP)\n      const targetDurationValue = targetDurationLine?.split(':')?.[1];\n      // NOTE: Defaulting here and using optional chaining above since some people are seeing RTEs on iPhones under edge cases.\n      // Identifying root cause would be ideal, but this will at least avoid the RTE. (CJP)\n      const targetDuration = +(targetDurationValue ?? 6);\n      liveEdgeStartOffset = targetDuration * 3;\n    }\n  }\n\n  return {\n    streamType,\n    targetLiveWindow,\n    liveEdgeStartOffset,\n  };\n};\n\nexport const getStreamInfoFromSrcAndType = async (src: string, type?: MediaTypes | '') => {\n  if (type === ExtensionMimeTypeMap.MP4) {\n    return {\n      streamType: StreamTypes.ON_DEMAND,\n      targetLiveWindow: Number.NaN,\n      liveEdgeStartOffset: undefined,\n      sessionData: undefined,\n    };\n  }\n\n  if (type === ExtensionMimeTypeMap.M3U8) {\n    const multivariantPlaylistResponse = await fetch(src);\n    if (!multivariantPlaylistResponse.ok) {\n      return Promise.reject(multivariantPlaylistResponse);\n    }\n    const multivariantPlaylist = await multivariantPlaylistResponse.text();\n    // Note: We use response.url instead of src because it considers redirects.\n    const mediaPlaylist = await getMediaPlaylistFromMultivariantPlaylist(\n      multivariantPlaylist,\n      multivariantPlaylistResponse.url\n    );\n    return {\n      ...getMultivariantPlaylistSessionData(multivariantPlaylist),\n      ...getStreamInfoFromPlaylist(mediaPlaylist),\n    };\n  }\n\n  // Unknown or undefined type.\n  console.error(`Media type ${type} is an unrecognized or unsupported type for src ${src}.`);\n  return {\n    streamType: undefined,\n    targetLiveWindow: undefined,\n    liveEdgeStartOffset: undefined,\n    sessionData: undefined,\n  };\n};\n\nexport const updateStreamInfoFromSrc = async (\n  src: string,\n  mediaEl: HTMLMediaElement,\n  type: MediaTypes | '' = getType({ src })\n) => {\n  const { streamType, targetLiveWindow, liveEdgeStartOffset, sessionData } = await getStreamInfoFromSrcAndType(\n    src,\n    type\n  );\n\n  const metadata = sessionData?.['com.apple.hls.chapters' as keyof typeof sessionData];\n  if (metadata?.URI || metadata?.VALUE.toLocaleLowerCase().startsWith('http')) {\n    // NOTE: data identified by DATA-ID 'com.apple.hls.chapters' is expected to provide its value\n    // via a remote JSON source identified by the URI attribute. Providing VALUE as a fallback.\n    // For more, see:\n    // https://developer.apple.com/documentation/http-live-streaming/providing-javascript-object-notation-json-chapters#Specify-a-main-playlist\n    fetchAndDispatchMuxMetadata(metadata.URI ?? metadata.VALUE, mediaEl);\n  }\n\n  (muxMediaState.get(mediaEl) ?? {}).liveEdgeStartOffset = liveEdgeStartOffset;\n\n  (muxMediaState.get(mediaEl) ?? {}).targetLiveWindow = targetLiveWindow;\n  mediaEl.dispatchEvent(new CustomEvent('targetlivewindowchange', { composed: true, bubbles: true }));\n\n  (muxMediaState.get(mediaEl) ?? {}).streamType = streamType;\n  mediaEl.dispatchEvent(new CustomEvent('streamtypechange', { composed: true, bubbles: true }));\n};\n\nexport const fetchAndDispatchMuxMetadata = async (metadataUrl: string, mediaEl: HTMLMediaElement) => {\n  try {\n    const resp = await fetch(metadataUrl);\n    if (!resp.ok) {\n      throw new Error(`Failed to fetch Mux metadata: ${resp.status} ${resp.statusText}`);\n    }\n\n    const json = await resp.json();\n    const metadata: Record<string, string> = {};\n\n    if (!json?.[0]?.metadata) return;\n\n    for (const item of json[0].metadata) {\n      if (item.key && item.value) {\n        metadata[item.key] = item.value;\n      }\n    }\n\n    (muxMediaState.get(mediaEl) ?? {}).metadata = metadata;\n\n    const eventUpdateMetadata = new CustomEvent('muxmetadata');\n    mediaEl.dispatchEvent(eventUpdateMetadata);\n  } catch (error) {\n    console.error(error);\n  }\n};\n\nexport const getStreamInfoFromHlsjsLevelDetails = (levelDetails: any) => {\n  const playlistType: HlsPlaylistTypes = levelDetails.type as HlsPlaylistTypes;\n\n  const streamType = toStreamTypeFromPlaylistType(playlistType);\n  const targetLiveWindow = toTargetLiveWindowFromPlaylistType(playlistType);\n  let liveEdgeStartOffset = undefined;\n  const lowLatency = !!levelDetails.partList?.length;\n  if (streamType === StreamTypes.LIVE) {\n    liveEdgeStartOffset = lowLatency ? levelDetails.partTarget * 2 : levelDetails.targetduration * 3;\n  }\n\n  return {\n    streamType,\n    targetLiveWindow,\n    liveEdgeStartOffset,\n    lowLatency,\n  };\n};\n\nexport const updateStreamInfoFromHlsjsLevelDetails = (\n  levelDetails: any,\n  mediaEl: HTMLMediaElement,\n  hls: Pick<Hls, 'config' | 'userConfig' | 'liveSyncPosition'>\n) => {\n  const { streamType, targetLiveWindow, liveEdgeStartOffset, lowLatency } =\n    getStreamInfoFromHlsjsLevelDetails(levelDetails);\n\n  if (streamType === StreamTypes.LIVE) {\n    // Update hls.js config for live/ll-live\n    if (lowLatency) {\n      hls.config.backBufferLength = hls.userConfig.backBufferLength ?? 4;\n      hls.config.maxFragLookUpTolerance = hls.userConfig.maxFragLookUpTolerance ?? 0.001;\n      // For ll-hls, ensure that up switches are weighted the same as down switches to mitigate\n      // cases of getting stuck at lower bitrates.\n      hls.config.abrBandWidthUpFactor = hls.userConfig.abrBandWidthUpFactor ?? hls.config.abrBandWidthFactor;\n    } else {\n      hls.config.backBufferLength = hls.userConfig.backBufferLength ?? 8;\n    }\n\n    // Proxy `seekable.end()` to constrain based on rules in\n    // https://github.com/video-dev/media-ui-extensions/blob/main/proposals/0007-live-edge.md#property-constraint-on-htmlmediaelementseekableend-to-model-seekable-live-edge\n    const seekable: TimeRanges = Object.freeze({\n      get length() {\n        return mediaEl.seekable.length;\n      },\n      start(index: number) {\n        return mediaEl.seekable.start(index);\n      },\n      end(index: number) {\n        // Defer to native seekable for:\n        // 1) \"out of range\" cases\n        // 2) \"finite duration\" media (whether live/\"DVR\" that has ended or on demand)\n        if (index > this.length || index < 0 || Number.isFinite(mediaEl.duration)) return mediaEl.seekable.end(index);\n        // Otherwise rely on the live sync position (but still fall back to native seekable when nullish)\n        return hls.liveSyncPosition ?? mediaEl.seekable.end(index);\n      },\n    });\n    (muxMediaState.get(mediaEl) ?? {}).seekable = seekable;\n  }\n\n  (muxMediaState.get(mediaEl) ?? {}).liveEdgeStartOffset = liveEdgeStartOffset;\n\n  (muxMediaState.get(mediaEl) ?? {}).targetLiveWindow = targetLiveWindow;\n  mediaEl.dispatchEvent(new CustomEvent('targetlivewindowchange', { composed: true, bubbles: true }));\n\n  (muxMediaState.get(mediaEl) ?? {}).streamType = streamType;\n  mediaEl.dispatchEvent(new CustomEvent('streamtypechange', { composed: true, bubbles: true }));\n};\n\ndeclare global {\n  interface NavigatorUAData {\n    platform: string;\n    mobile: boolean;\n    brands: Array<{ brand: string; version: string }>;\n  }\n\n  interface Navigator {\n    userAgentData?: NavigatorUAData;\n  }\n}\n\nconst userAgentStr = globalThis?.navigator?.userAgent ?? '';\nconst userAgentPlatform = globalThis?.navigator?.userAgentData?.platform ?? '';\n\n// NOTE: Our primary *goal* with this is to detect \"non-Apple-OS\" platforms which may also support\n// native HLS playback. Our primary concern with any check for this is \"false negatives\" where we\n// identify an \"Apple-OS\" as a \"non-Apple-OS\". As such, instead of having logic to attempt to identify\n// \"!isAppleOS\", we opt to target known platforms that can support both native playback and MSE/hls.js.\n// For now, these are \"Android or Android-like\" platforms. If we end up matching platforms other than\n// Android (or e.g. forks thereof), this is fine so long as it doesn't include Apple-OS platforms.\n// Below are two strategies:\n// 1. UA string parsing - here, we're extra cautious to only match if the UA string explicitly includes 'android'.\n//   This is prone to false negatives (aka \"Android or Android-like\" platforms that yield false), since\n//   detection using UA strings is intentionally and notoriously unreliable (See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent)\n//   and Google is even officially attempting to lock this down even more for security and privacy reasons\n//   (See: https://developers.google.com/privacy-sandbox/blog/user-agent-reduction-android-model-and-version)\n// 2. userAgentData.platform checking - here, we're matching either 'android' or 'x11', and could add more matches in the future\n//    While still prone to false negatives, we can be a bit more aggressive with matches here for a few reasons.\n//    First, navigator.userAgentData is still experimental, is only supported on a subset of Chromium browsers,\n//    and neither Mozilla nor Webkit have even established an official browser support position. In other words,\n//    Apple-OS Safari and even other Apple-OS browsers (including Chrome) will typically not even support this\n//    feature, and, if and when they do, the purpose of this new API is to avoid obfuscatory information, so\n//    we should be able to better trust userAgentData.platform to not result in erroneous matches.\nconst isAndroidLike =\n  userAgentStr.toLowerCase().includes('android') ||\n  ['x11', 'android'].some((platformStr) => userAgentPlatform.toLowerCase().includes(platformStr));\n\nconst isSafari = (mediaEl: Pick<HTMLMediaElement, 'canPlayType'>) =>\n  /^((?!chrome|android).)*safari/i.test(userAgentStr) && !!mediaEl.canPlayType('application/vnd.apple.mpegurl');\n\n// NOTE: Exporting for testing\nexport const muxMediaState: WeakMap<\n  HTMLMediaElement,\n  Partial<MuxMediaProps> & {\n    seekable?: TimeRanges;\n    liveEdgeStartOffset?: number;\n    retryCount?: number;\n    coreReference?: PlaybackCore;\n  }\n> = new WeakMap();\n\nconst MUX_VIDEO_DOMAIN = 'mux.com';\nconst MSE_SUPPORTED = Hls.isSupported?.();\n\n/* NOTE: This will include iOS WebViews\n *\n * This is intentional, ultimately we intend to rely less on native platforms\n * and more on our own engine. Also, we would prefer to avoid UA parsing.\n *\n * For an example see: https://github.com/muxinc/elements/issues/1227\n * For internal dicussion see: https://github.com/muxinc/devextravaganza/issues/207\n */\nconst shouldDefaultToMSE = (mediaEl: Pick<HTMLMediaElement, 'canPlayType'>) => isAndroidLike || !isSafari(mediaEl);\n\nexport const generatePlayerInitTime = () => {\n  // bail during SSR to avoid triggering prerender errors\n  // actual time will be generated during hydration\n  if (typeof window === 'undefined') return undefined;\n\n  return mux.utils.now();\n};\n\nexport const generateUUID = mux.utils.generateUUID;\n\ntype MuxVideoURLProps = Partial<\n  Pick<\n    MuxMediaPropTypes,\n    | 'playbackId'\n    | 'customDomain'\n    | 'maxResolution'\n    | 'minResolution'\n    | 'renditionOrder'\n    | 'programStartTime'\n    | 'programEndTime'\n    | 'assetStartTime'\n    | 'assetEndTime'\n    | 'tokens'\n    | 'playbackToken'\n    | 'extraSourceParams'\n  >\n>;\n\nexport const toMuxVideoURL = ({\n  playbackId: playbackIdWithParams,\n  customDomain: domain = MUX_VIDEO_DOMAIN,\n  maxResolution,\n  minResolution,\n  renditionOrder,\n  programStartTime,\n  programEndTime,\n  assetStartTime,\n  assetEndTime,\n  // Normalizes different ways of providing playback token\n  playbackToken,\n  tokens: { playback: token = playbackToken } = {},\n  extraSourceParams = {},\n}: MuxVideoURLProps = {}) => {\n  if (!playbackIdWithParams) return undefined;\n  // Normalizes different ways of providing playback id\n  const [playbackId, queryPart = ''] = toPlaybackIdParts(playbackIdWithParams);\n  const url = new URL(`https://stream.${domain}/${playbackId}.m3u8${queryPart}`);\n  /*\n   * All identified query params here can only be added to public\n   * playback IDs. In order to use these features with signed URLs\n   * the query param must be added to the signing token.\n   *\n   * */\n  if (token || url.searchParams.has('token')) {\n    url.searchParams.forEach((_, key) => {\n      if (key != 'token') url.searchParams.delete(key);\n    });\n    if (token) url.searchParams.set('token', token);\n  } else {\n    if (maxResolution) {\n      url.searchParams.set('max_resolution', maxResolution);\n    }\n    if (minResolution) {\n      url.searchParams.set('min_resolution', minResolution);\n      if (maxResolution && +maxResolution.slice(0, -1) < +minResolution.slice(0, -1)) {\n        console.error(\n          'minResolution must be <= maxResolution',\n          'minResolution',\n          minResolution,\n          'maxResolution',\n          maxResolution\n        );\n      }\n    }\n    if (renditionOrder) {\n      url.searchParams.set('rendition_order', renditionOrder);\n    }\n    if (programStartTime) {\n      url.searchParams.set('program_start_time', `${programStartTime}`);\n    }\n    if (programEndTime) {\n      url.searchParams.set('program_end_time', `${programEndTime}`);\n    }\n    if (assetStartTime) {\n      url.searchParams.set('asset_start_time', `${assetStartTime}`);\n    }\n    if (assetEndTime) {\n      url.searchParams.set('asset_end_time', `${assetEndTime}`);\n    }\n    Object.entries(extraSourceParams).forEach(([k, v]) => {\n      if (v == undefined) return;\n      url.searchParams.set(k, v);\n    });\n  }\n  return url.toString();\n};\n\nconst toPlaybackIdFromParameterized = (playbackIdWithParams: string | undefined) => {\n  if (!playbackIdWithParams) return undefined;\n  const [playbackId] = playbackIdWithParams.split('?');\n  // `|| undefined` is here to handle potential invalid cases\n  return playbackId || undefined;\n};\n\nexport const toPlaybackIdFromSrc = (src: string | undefined) => {\n  if (!src || !src.startsWith('https://stream.')) return undefined;\n  const [playbackId] = new URL(src).pathname.slice(1).split(/\\.m3u8|\\//);\n  // `|| undefined` is here to handle potential invalid cases\n  return playbackId || undefined;\n};\n\nconst toVideoId = (props: Partial<MuxMediaPropsInternal>) => {\n  if (props?.metadata?.video_id) return props.metadata.video_id;\n  if (!isMuxVideoSrc(props)) return props.src;\n  return toPlaybackIdFromParameterized(props.playbackId) ?? toPlaybackIdFromSrc(props.src) ?? props.src;\n};\n\nexport const getError = (mediaEl: HTMLMediaElement) => {\n  return muxMediaState.get(mediaEl)?.error;\n};\n\nexport const getMetadata = (mediaEl: HTMLMediaElement) => {\n  return muxMediaState.get(mediaEl)?.metadata;\n};\n\nexport const getStreamType = (mediaEl: HTMLMediaElement) => {\n  return muxMediaState.get(mediaEl)?.streamType ?? StreamTypes.UNKNOWN;\n};\n\nexport const getTargetLiveWindow = (mediaEl: HTMLMediaElement) => {\n  return muxMediaState.get(mediaEl)?.targetLiveWindow ?? Number.NaN;\n};\n\nexport const getSeekable = (mediaEl: HTMLMediaElement) => {\n  return muxMediaState.get(mediaEl)?.seekable ?? mediaEl.seekable;\n};\n\nexport const getLiveEdgeStart = (mediaEl: HTMLMediaElement) => {\n  const liveEdgeStartOffset = muxMediaState.get(mediaEl)?.liveEdgeStartOffset;\n  if (typeof liveEdgeStartOffset !== 'number') return Number.NaN;\n  const seekable = getSeekable(mediaEl);\n  // We aren't guaranteed that seekable is ready before invoking this, so handle that case.\n  if (!seekable.length) return Number.NaN;\n  return seekable.end(seekable.length - 1) - liveEdgeStartOffset;\n};\n\n// Core could get updated if we re-initialize, for example: on FairPlay DRM fallback\nexport const getCoreReference = (mediaEl: HTMLMediaElement) => {\n  return muxMediaState.get(mediaEl)?.coreReference;\n};\n\nconst DEFAULT_ENDED_MOE = 0.034;\n\nconst isApproximatelyEqual = (x: number, y: number, moe = DEFAULT_ENDED_MOE) => Math.abs(x - y) <= moe;\nconst isApproximatelyGTE = (x: number, y: number, moe = DEFAULT_ENDED_MOE) => x > y || isApproximatelyEqual(x, y, moe);\n\nexport const isPseudoEnded = (mediaEl: HTMLMediaElement, moe = DEFAULT_ENDED_MOE) => {\n  return mediaEl.paused && isApproximatelyGTE(mediaEl.currentTime, mediaEl.duration, moe);\n};\n\nexport const isStuckOnLastFragment = (\n  mediaEl: HTMLMediaElement,\n  hls?: Pick<\n    Hls,\n    /** Should we add audio fragments logic here, too? (CJP) */\n    // | 'audioTrack'\n    // | 'audioTracks'\n    'levels' | 'currentLevel'\n  >\n) => {\n  if (!hls || !mediaEl.buffered.length) return undefined;\n  if (mediaEl.readyState > 2) return false;\n  const videoLevelDetails =\n    hls.currentLevel >= 0\n      ? hls.levels?.[hls.currentLevel]?.details\n      : hls.levels.find((level) => !!level.details)?.details;\n\n  // Don't define for live streams (for now).\n  if (!videoLevelDetails || videoLevelDetails.live) return undefined;\n\n  const { fragments } = videoLevelDetails;\n\n  // Don't give a definitive true|false before we have no fragments (for now).\n  if (!fragments?.length) return undefined;\n\n  // Do a cheap check up front to see if we're close to the end.\n  // For more on TARGET_DURATION, see https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-14#section-4.4.3.1 (CJP)\n  if (mediaEl.currentTime < mediaEl.duration - (videoLevelDetails.targetduration + 0.5)) return false;\n\n  const lastFragment = fragments[fragments.length - 1];\n\n  // We're not yet playing the last fragment, so we can't be stuck on it.\n  if (mediaEl.currentTime <= lastFragment.start) return false;\n\n  const lastFragmentMidpoint = lastFragment.start + lastFragment.duration / 2;\n  const lastBufferedStart = mediaEl.buffered.start(mediaEl.buffered.length - 1);\n  const lastBufferedEnd = mediaEl.buffered.end(mediaEl.buffered.length - 1);\n\n  // True if we've already buffered (half of) the last fragment\n  const lastFragmentInBuffer = lastFragmentMidpoint > lastBufferedStart && lastFragmentMidpoint < lastBufferedEnd;\n  // If we haven't buffered half already, assume we're still waiting to fetch+buffer the fragment, otherwise,\n  // since we already checked the ready state, this means we're stuck on the last segment, and should pretend we're ended!\n  return lastFragmentInBuffer;\n};\n\nexport const getEnded = (\n  mediaEl: HTMLMediaElement,\n  hls?: Pick<\n    Hls,\n    /** Should we add audio fragments logic here, too? (CJP) */\n    // | 'audioTrack'\n    // | 'audioTracks'\n    'levels' | 'currentLevel'\n  >\n) => {\n  // Since looping media never truly ends, don't apply pseudo-ended logic\n  // Also, trust when the HTMLMediaElement says we have ended (only apply pseudo-ended logic when it reports false)\n  if (mediaEl.ended || mediaEl.loop) return mediaEl.ended;\n  // Externalize conversion to boolean for \"under-determined cases\" here (See isStuckOnLastFragment() for details)\n  if (hls && !!isStuckOnLastFragment(mediaEl, hls)) return true;\n  return isPseudoEnded(mediaEl);\n};\n\nexport const initialize = (props: Partial<MuxMediaPropsInternal>, mediaEl: HTMLMediaElement, core?: PlaybackCore) => {\n  // Automatically tear down previously initialized mux data & hls instance if it exists.\n  teardown(mediaEl, core, props);\n  // NOTE: metadata should never be nullish/nil. Adding here for type safety due to current type defs.\n  const { metadata = {} } = props;\n  const { view_session_id = generateUUID() } = metadata;\n  const video_id = toVideoId(props);\n  metadata.view_session_id = view_session_id;\n  metadata.video_id = video_id;\n  props.metadata = metadata;\n\n  // Used to signal DRM Type to Mux Data. See, e.g. `getDRMConfig()`\n  const drmTypeCb = (drmType?: string) => {\n    mediaEl.mux?.emit('hb', { view_drm_type: drmType });\n  };\n\n  props.drmTypeCb = drmTypeCb;\n  props.fallbackToWebkitFairplay = async () => {\n    const wasPlaying = !mediaEl.paused;\n    const currentTime = mediaEl.currentTime;\n\n    props.useWebkitFairplay = true;\n\n    // Prevent duplicate mux data\n    const muxDataKeepSession = props.muxDataKeepSession;\n    props.muxDataKeepSession = true;\n\n    const oldCore = muxMediaState.get(mediaEl)?.coreReference;\n    // This will tear oldCore down internally\n    initialize(props, mediaEl, oldCore);\n\n    props.muxDataKeepSession = muxDataKeepSession;\n    // Try again for other src\n    props.useWebkitFairplay = false;\n    if (wasPlaying) {\n      await mediaEl\n        .play()\n        .then(() => {\n          mediaEl.currentTime = currentTime;\n        })\n        .catch(() => {});\n    }\n    mediaEl.currentTime = currentTime;\n  };\n\n  muxMediaState.set(mediaEl as HTMLMediaElement, { retryCount: 0 });\n  const nextHlsInstance = setupHls(props, mediaEl);\n  const setPreload = setupPreload(props as Pick<MuxMediaProps, 'preload' | 'src'>, mediaEl, nextHlsInstance);\n\n  if (props?.muxDataKeepSession && mediaEl?.mux && !mediaEl.mux.deleted) {\n    if (nextHlsInstance) {\n      mediaEl.mux.addHLSJS({\n        hlsjs: nextHlsInstance as HlsInterface,\n        Hls: nextHlsInstance ? Hls : undefined,\n      });\n    }\n  } else {\n    setupMux(props, mediaEl, nextHlsInstance);\n  }\n\n  loadMedia(props, mediaEl, nextHlsInstance);\n  setupCuePoints(mediaEl);\n  setupChapters(mediaEl);\n  const setAutoplay = setupAutoplay(props as Pick<MuxMediaProps, 'autoplay'>, mediaEl, nextHlsInstance);\n  setupMinPreload(props as Pick<MuxMediaProps, 'minPreloadSegments'>, mediaEl, nextHlsInstance);\n  setupInitialEstimate(props as Pick<MuxMediaProps, 'initialEstimateSegments'>, mediaEl, nextHlsInstance);\n\n  const newCore = {\n    engine: nextHlsInstance,\n    setAutoplay,\n    setPreload,\n  };\n\n  const state = muxMediaState.get(mediaEl);\n  if (state) {\n    state.coreReference = newCore;\n  }\n\n  return newCore;\n};\n\nexport const teardown = (\n  mediaEl?: HTMLMediaElement | null,\n  core?: PlaybackCore,\n  props?: Partial<MuxMediaPropsInternal>\n) => {\n  const hls = core?.engine;\n\n  if (mediaEl?.mux && !mediaEl.mux.deleted) {\n    if (props?.muxDataKeepSession) {\n      if (hls) mediaEl.mux.removeHLSJS();\n    } else {\n      mediaEl.mux.destroy();\n      delete mediaEl.mux;\n    }\n  }\n\n  if (hls) {\n    hls.detachMedia();\n    hls.destroy();\n  }\n\n  if (mediaEl) {\n    if (mediaEl.hasAttribute('src')) {\n      mediaEl.removeAttribute('src');\n      mediaEl.load();\n    }\n    mediaEl.removeEventListener('error', handleNativeError);\n    mediaEl.removeEventListener('error', handleInternalError);\n    mediaEl.removeEventListener('durationchange', seekInSeekableRange);\n    muxMediaState.delete(mediaEl);\n    mediaEl.dispatchEvent(new Event('teardown'));\n  }\n};\n\n/**\n * Returns true if we should use native playback. e.g. progressive files (mp3, mp4, webm) or native HLS on Safari.\n * We should use native playback for hls media sources if we\n *\n *   a) can use native playback (excluding Android, it's MSE by default)\n *   b) not prefer to use MSE/hls.js if it's supported\n */\nfunction useNative(\n  props: Partial<Pick<MuxMediaProps, 'preferPlayback' | 'type'>>,\n  mediaEl: Pick<HTMLMediaElement, 'canPlayType'>\n) {\n  const type = getType(props);\n  const hlsType = type === ExtensionMimeTypeMap.M3U8;\n  if (!hlsType) return true;\n\n  const canUseNative = !type || (mediaEl.canPlayType(type) ?? true);\n  const { preferPlayback } = props;\n\n  const preferMse = preferPlayback === PlaybackTypes.MSE;\n  const preferNative = preferPlayback === PlaybackTypes.NATIVE;\n  const forceMse = MSE_SUPPORTED && (preferMse || shouldDefaultToMSE(mediaEl));\n\n  return canUseNative && (preferNative || !forceMse);\n}\n\nexport const setupHls = (\n  props: Partial<\n    Pick<\n      MuxMediaPropsInternal,\n      | 'debug'\n      | 'streamType'\n      | 'type'\n      | 'startTime'\n      | 'metadata'\n      | 'preferCmcd'\n      | '_hlsConfig'\n      | 'tokens'\n      | 'drmTypeCb'\n      | 'maxAutoResolution'\n      | 'capRenditionToPlayerSize'\n      | 'initialBandwidthEstimateKbps'\n    >\n  >,\n  mediaEl: HTMLMediaElement\n) => {\n  const {\n    debug,\n    streamType,\n    startTime: startPosition = -1,\n    metadata,\n    preferCmcd,\n    _hlsConfig = {},\n    maxAutoResolution,\n    initialBandwidthEstimateKbps,\n  } = props;\n  const type = getType(props);\n  const hlsType = type === ExtensionMimeTypeMap.M3U8;\n  const shouldUseNative = useNative(props, mediaEl);\n\n  // 1. if we are trying to play an hls media source create hls if we should be using it \"under the hood\"\n  if (hlsType && !shouldUseNative && MSE_SUPPORTED) {\n    const defaultConfig = {\n      backBufferLength: 30,\n      renderTextTracksNatively: false,\n      liveDurationInfinity: true,\n      capLevelOnFPSDrop: true,\n      ...(initialBandwidthEstimateKbps != null ? { abrEwmaDefaultEstimate: initialBandwidthEstimateKbps * 1000 } : {}),\n    };\n    const streamTypeConfig = getStreamTypeConfig(streamType);\n    const drmConfig = getDRMConfig(props);\n    // NOTE: `metadata.view_session_id` & `metadata.video_id` are guaranteed here (CJP)\n    // @ts-ignore\n    const cmcd = [CmcdTypes.QUERY, CmcdTypes.HEADER].includes(preferCmcd)\n      ? {\n          useHeaders: preferCmcd === CmcdTypes.HEADER,\n          sessionId: metadata?.view_session_id,\n          contentId: metadata?.video_id,\n        }\n      : undefined;\n\n    const capLevelControllerObj = getCapLevelControllerConfig(props, _hlsConfig);\n\n    const hls = new Hls({\n      // Kind of like preload metadata, but causes spinner.\n      // autoStartLoad: false,\n      debug,\n      startPosition,\n      cmcd,\n      xhrSetup: (xhr, url) => {\n        if (preferCmcd && preferCmcd !== CmcdTypes.QUERY) return;\n        const urlObj = toAbsoluteUrl(url);\n        if (!urlObj.searchParams.has('CMCD')) return;\n        const cmcdVal = (urlObj.searchParams.get('CMCD')?.split(',') ?? [])\n          .filter((cmcdKVStr) => cmcdKVStr.startsWith('sid') || cmcdKVStr.startsWith('cid'))\n          .join(',');\n        urlObj.searchParams.set('CMCD', cmcdVal);\n\n        xhr.open('GET', urlObj);\n      },\n      ...defaultConfig,\n      ...capLevelControllerObj,\n      ...streamTypeConfig,\n      ...drmConfig,\n      ..._hlsConfig,\n    }) as HlsInterface;\n\n    if (capLevelControllerObj.capLevelController === MinCapLevelController) {\n      if (maxAutoResolution !== undefined) {\n        MinCapLevelController.setMaxAutoResolution(hls, maxAutoResolution);\n      }\n    }\n\n    hls.on(Hls.Events.MANIFEST_PARSED, async function (_event, data) {\n      const chapters = data.sessionData?.['com.apple.hls.chapters'];\n      if (chapters?.URI || chapters?.VALUE.toLocaleLowerCase().startsWith('http')) {\n        fetchAndDispatchMuxMetadata(chapters?.URI ?? chapters?.VALUE, mediaEl);\n      }\n    });\n\n    return hls;\n  }\n  return undefined;\n};\n\nexport const getStreamTypeConfig = (streamType?: ValueOf<StreamTypes>) => {\n  // for regular live videos, set backBufferLength to 8\n  if (streamType === StreamTypes.LIVE) {\n    const liveConfig = {\n      backBufferLength: 8,\n    };\n\n    return liveConfig;\n  }\n\n  return {};\n};\n\nexport const getDRMConfig = (\n  props: Partial<Pick<MuxMediaPropsInternal, 'src' | 'playbackId' | 'tokens' | 'customDomain' | 'drmTypeCb'>>\n): Partial<HlsConfig> => {\n  const {\n    tokens: { drm: drmToken } = {},\n    playbackId: playbackIdWithOptionalParams, // Since Mux Player typically sets `src` instead of `playbackId`, fall back to it here (CJP)\n    drmTypeCb,\n  } = props;\n  const playbackId = toPlaybackIdFromParameterized(playbackIdWithOptionalParams);\n  if (!drmToken || !playbackId) return {};\n  return {\n    emeEnabled: true,\n    drmSystems: {\n      'com.apple.fps': {\n        licenseUrl: toLicenseKeyURL(props, 'fairplay'),\n        serverCertificateUrl: toAppCertURL(props, 'fairplay'),\n      },\n      'com.widevine.alpha': {\n        licenseUrl: toLicenseKeyURL(props, 'widevine'),\n      },\n      'com.microsoft.playready': {\n        licenseUrl: toLicenseKeyURL(props, 'playready'),\n      },\n    },\n    requestMediaKeySystemAccessFunc: (keySystem, supportedConfigurations) => {\n      if (keySystem === 'com.widevine.alpha') {\n        supportedConfigurations = [\n          // NOTE: For widevine, by default we'll duplicate the key system configs but add L1-level\n          // security to the first set of duplicates so the key system will \"prefer\" that\n          // if/when available. (CJP)\n          // See, e.g.: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMediaKeySystemAccess#supportedconfigurations\n          ...supportedConfigurations.map((mediaKeySystemConfig) => {\n            const videoCapabilities = mediaKeySystemConfig.videoCapabilities?.map((capability) => {\n              return {\n                ...capability,\n                robustness: 'HW_SECURE_ALL',\n              };\n            });\n            return {\n              ...mediaKeySystemConfig,\n              videoCapabilities,\n            };\n          }),\n          ...supportedConfigurations,\n        ];\n      }\n      return navigator.requestMediaKeySystemAccess(keySystem, supportedConfigurations).then((value) => {\n        const drmType = toDRMTypeFromKeySystem(keySystem);\n        drmTypeCb?.(drmType);\n        return value;\n      });\n    },\n  };\n};\n\nexport const getAppCertificate = async (appCertificateUrl: string) => {\n  const resp = await fetch(appCertificateUrl);\n  if (resp.status !== 200) {\n    return Promise.reject(resp);\n  }\n  const body = await resp.arrayBuffer();\n  return body;\n};\n\nexport const getLicenseKey = async (message: ArrayBuffer, licenseServerUrl: string) => {\n  const resp = await fetch(licenseServerUrl, {\n    method: 'POST',\n    headers: { 'Content-type': 'application/octet-stream' },\n    body: message,\n  });\n  if (resp.status !== 200) {\n    return Promise.reject(resp);\n  }\n  const keyBuffer = await resp.arrayBuffer();\n  return new Uint8Array(keyBuffer);\n};\n\nexport const setupNativeFairplayDRM = (\n  props: Partial<\n    Pick<\n      MuxMediaPropsInternal,\n      | 'playbackId'\n      | 'tokens'\n      | 'playbackToken'\n      | 'customDomain'\n      | 'drmTypeCb'\n      | 'useWebkitFairplay'\n      | 'fallbackToWebkitFairplay'\n    >\n  >,\n  mediaEl: HTMLMediaElement\n) => {\n  const getAppCertificateHandler = () =>\n    getAppCertificate(toAppCertURL(props, 'fairplay')).catch((errOrResp) => {\n      if (errOrResp instanceof Response) {\n        const mediaError = getErrorFromResponse(errOrResp, MuxErrorCategory.DRM, props);\n        console.error('mediaError', mediaError?.message, mediaError?.context);\n        if (mediaError) {\n          return Promise.reject(mediaError);\n        }\n        // NOTE: This should never happen. Adding for exhaustiveness (CJP).\n        return Promise.reject(new Error('Unexpected error in app cert request'));\n      }\n      return Promise.reject(errOrResp);\n    });\n\n  const getLicenseKeyHandler = (message: ArrayBuffer) =>\n    getLicenseKey(message, toLicenseKeyURL(props, 'fairplay')).catch((errOrResp) => {\n      if (errOrResp instanceof Response) {\n        const mediaError = getErrorFromResponse(errOrResp, MuxErrorCategory.DRM, props);\n        console.error('mediaError', mediaError?.message, mediaError?.context);\n\n        if (mediaError) {\n          return Promise.reject(mediaError);\n        }\n        // NOTE: This should never happen. Adding for exhaustiveness (CJP).\n        return Promise.reject(new Error('Unexpected error in license key request'));\n      }\n      return Promise.reject(errOrResp);\n    });\n\n  const commonConfig = {\n    mediaEl: mediaEl,\n    getAppCertificate: getAppCertificateHandler,\n    getLicenseKey: getLicenseKeyHandler,\n    saveAndDispatchError,\n    drmTypeCb: () => {\n      props.drmTypeCb?.(DRMType.FAIRPLAY);\n    },\n  };\n\n  if (props.useWebkitFairplay) {\n    // Note: Sets teardown event listener\n    setupWebkitNativeFairplayDRM(commonConfig);\n  } else {\n    const emeConfig = {\n      fallbackToWebkitFairplay: async () => {\n        await teardownEme();\n        props.fallbackToWebkitFairplay?.();\n      },\n      ...commonConfig,\n    };\n\n    // Note: Returns teardown to be used in fallback, but also sets teardown event listener\n    const teardownEme = setupEmeNativeFairplayDRM(emeConfig);\n  }\n};\n\nexport const toLicenseKeyURL = (\n  {\n    playbackId: playbackIdWithParams,\n    tokens: { drm: token } = {},\n    customDomain = MUX_VIDEO_DOMAIN,\n  }: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'tokens' | 'customDomain'>>,\n  scheme: 'widevine' | 'playready' | 'fairplay'\n) => {\n  const playbackId = toPlaybackIdFromParameterized(playbackIdWithParams);\n  // NOTE: Mux Video currently doesn't support custom domains for license/DRM endpoints, but\n  // customDomain can also be used for internal use cases, so treat that as an exception case for now. (CJP)\n  const domain = customDomain.toLocaleLowerCase().endsWith(MUX_VIDEO_DOMAIN) ? customDomain : MUX_VIDEO_DOMAIN;\n  return `https://license.${domain}/license/${scheme}/${playbackId}?token=${token}`;\n};\n\nexport const toAppCertURL = (\n  {\n    playbackId: playbackIdWithParams,\n    tokens: { drm: token } = {},\n    customDomain = MUX_VIDEO_DOMAIN,\n  }: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'tokens' | 'customDomain'>>,\n  scheme: 'widevine' | 'playready' | 'fairplay'\n) => {\n  const playbackId = toPlaybackIdFromParameterized(playbackIdWithParams);\n  // NOTE: Mux Video currently doesn't support custom domains for license/DRM endpoints, but\n  // customDomain can also be used for internal use cases, so treat that as an exception case for now. (CJP)\n  const domain = customDomain.toLocaleLowerCase().endsWith(MUX_VIDEO_DOMAIN) ? customDomain : MUX_VIDEO_DOMAIN;\n  return `https://license.${domain}/appcert/${scheme}/${playbackId}?token=${token}`;\n};\n\nexport const isMuxVideoSrc = ({\n  playbackId,\n  src,\n  customDomain,\n}: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'src' | 'customDomain'>>) => {\n  if (!!playbackId) return true;\n  // having no playback id and no src string should never actually happen, but could\n  if (typeof src !== 'string') return false;\n  // Include base for relative paths\n  const base = window?.location.href;\n  const hostname = new URL(src, base).hostname.toLocaleLowerCase();\n\n  return hostname.includes(MUX_VIDEO_DOMAIN) || (!!customDomain && hostname.includes(customDomain.toLocaleLowerCase()));\n};\n\nexport const getCapLevelControllerConfig = (\n  props: Pick<MuxMediaPropsInternal, 'capRenditionToPlayerSize'>,\n  _hlsConfig: Partial<HlsConfig>\n): Partial<Pick<HlsConfig, 'capLevelController' | 'capLevelToPlayerSize'>> => {\n  const capLevelControllerObj: Partial<Pick<HlsConfig, 'capLevelController' | 'capLevelToPlayerSize'>> = {};\n  // If capRenditionToPlayerSize is not explicitly set in props we enable MinCapLevelController\n  capLevelControllerObj.capLevelToPlayerSize = props.capRenditionToPlayerSize;\n  if (capLevelControllerObj.capLevelToPlayerSize == null) {\n    capLevelControllerObj.capLevelController = MinCapLevelController;\n    capLevelControllerObj.capLevelToPlayerSize = true;\n  } else {\n    capLevelControllerObj.capLevelController = CapLevelController;\n  }\n  return capLevelControllerObj;\n};\n\nexport const setupMux = (\n  props: Partial<\n    Pick<\n      MuxMediaPropsInternal,\n      | 'envKey'\n      | 'playerInitTime'\n      | 'beaconCollectionDomain'\n      | 'errorTranslator'\n      | 'metadata'\n      | 'debug'\n      | 'playerSoftwareName'\n      | 'playerSoftwareVersion'\n      | 'playbackId'\n      | 'src'\n      | 'customDomain'\n      | 'disableCookies'\n      | 'disableTracking'\n      | 'muxDataSDK'\n      | 'muxDataSDKOptions'\n    >\n  >,\n  mediaEl: HTMLMediaElement,\n  hlsjs?: HlsInterface\n) => {\n  const { envKey: env_key, disableTracking, muxDataSDK = mux, muxDataSDKOptions = {} } = props;\n  const inferredEnv = isMuxVideoSrc(props);\n\n  if (!disableTracking && (env_key || inferredEnv)) {\n    const {\n      playerInitTime: player_init_time,\n      playerSoftwareName: player_software_name,\n      playerSoftwareVersion: player_software_version,\n      beaconCollectionDomain,\n      debug,\n      disableCookies,\n    } = props;\n\n    const metadata = {\n      ...props.metadata,\n      video_title: props?.metadata?.video_title || undefined,\n    };\n\n    const muxEmbedErrorTranslator = (error: ErrorEvent) => {\n      // mux-embed auto tracks fatal hls.js errors, turn it off.\n      // playback-core will emit errors with a numeric code manually to mux-embed.\n      if (typeof error.player_error_code === 'string') return false;\n\n      if (typeof props.errorTranslator === 'function') {\n        return props.errorTranslator(error);\n      }\n\n      return error;\n    };\n\n    muxDataSDK.monitor(mediaEl, {\n      debug,\n      beaconCollectionDomain,\n      hlsjs,\n      Hls: hlsjs ? Hls : undefined,\n      automaticErrorTracking: false,\n      errorTranslator: muxEmbedErrorTranslator,\n      disableCookies,\n      ...muxDataSDKOptions,\n      data: {\n        ...(env_key ? { env_key } : {}),\n        // Metadata fields\n        player_software_name,\n        // NOTE: Adding this because there appears to be some instability on whether\n        // player_software_name or player_software \"wins\" for Mux Data (CJP)\n        player_software: player_software_name,\n        player_software_version,\n        player_init_time,\n        // Use any metadata passed in programmatically (which may override the defaults above)\n        ...metadata,\n      },\n    });\n  }\n};\n\nexport const loadMedia = (\n  props: Partial<\n    Pick<\n      MuxMediaProps,\n      | 'preferPlayback'\n      | 'src'\n      | 'type'\n      | 'startTime'\n      | 'streamType'\n      | 'autoplay'\n      | 'playbackId'\n      | 'tokens'\n      | 'customDomain'\n      | 'disablePseudoEnded'\n      | 'debug'\n      | 'useWebkitFairplay'\n      | 'fallbackToWebkitFairplay'\n    >\n  >,\n  mediaEl: HTMLMediaElement,\n  hls?: Pick<\n    Hls,\n    | 'config'\n    | 'on'\n    | 'once'\n    | 'off'\n    | 'trigger'\n    | 'startLoad'\n    | 'stopLoad'\n    | 'recoverMediaError'\n    | 'destroy'\n    | 'loadSource'\n    | 'attachMedia'\n    | 'liveSyncPosition'\n    | 'subtitleTracks'\n    | 'subtitleTrack'\n    | 'userConfig'\n    | 'audioTrack'\n    | 'audioTracks'\n    | 'autoLevelEnabled'\n    | 'nextLevel'\n    | 'levels'\n    | 'currentLevel'\n  >\n) => {\n  const shouldUseNative = useNative(props, mediaEl);\n  const { src, customDomain = MUX_VIDEO_DOMAIN } = props;\n\n  const maybeDispatchEndedCallback = () => {\n    // We want to early bail if the underlying media element is already in an ended state,\n    // since that means it will have already fired the ended event.\n    // Do the \"cheaper\" check first\n    if (mediaEl.ended) return;\n\n    if (props.disablePseudoEnded) return;\n\n    const pseudoEnded = getEnded(mediaEl, hls);\n    if (!pseudoEnded) return;\n\n    if (isStuckOnLastFragment(mediaEl, hls)) {\n      // Nudge the playhead in this case.\n      mediaEl.currentTime = mediaEl.buffered.end(mediaEl.buffered.length - 1);\n    } else {\n      mediaEl.dispatchEvent(new Event('ended'));\n    }\n  };\n\n  let prevSeekableStart: number | undefined;\n  let prevSeekableEnd: number | undefined;\n\n  const seekableChange = () => {\n    const seekableTimeRanges = getSeekable(mediaEl);\n    let nextSeekableStart: number | undefined;\n    let nextSeekableEnd: number | undefined;\n    if (seekableTimeRanges.length > 0) {\n      nextSeekableStart = seekableTimeRanges.start(0);\n      nextSeekableEnd = seekableTimeRanges.end(0);\n    }\n    if (prevSeekableEnd !== nextSeekableEnd || prevSeekableStart !== nextSeekableStart) {\n      mediaEl.dispatchEvent(new CustomEvent('seekablechange', { composed: true }));\n    }\n    prevSeekableStart = nextSeekableStart;\n    prevSeekableEnd = nextSeekableEnd;\n  };\n\n  // Make sure we track transitions from infinite to finite durations for seekable changes as well.\n  addEventListenerWithTeardown(mediaEl, 'durationchange', seekableChange);\n\n  if (mediaEl && shouldUseNative) {\n    const type = getType(props);\n\n    if (typeof src === 'string') {\n      // Fetch the Mux metadata JSON even on preload=none because it's needed for the Mux logo.\n      if (src.endsWith('.mp4') && src.includes(customDomain)) {\n        const playbackId = toPlaybackIdFromSrc(src);\n        const metadataUrl = new URL(`https://stream.${customDomain}/${playbackId}/metadata.json`);\n        fetchAndDispatchMuxMetadata(metadataUrl.toString(), mediaEl);\n      }\n\n      // NOTE: This should only be invoked after stream type has been\n      // derived after stream type has been determined.\n      const setupSeekableChangePoll = () => {\n        // Only monitor for seekable updates if StreamType is \"live\" and duration is not finite.\n        if (getStreamType(mediaEl) !== StreamTypes.LIVE || Number.isFinite(mediaEl.duration)) return;\n\n        // Use 1 second since in this context we don't know what the rate of updates\n        // should/will be.\n        // NOTE: We *could* derive the interval rate if we wanted to add logic to our playlist parsing to\n        // account for the per-spec rate of media playlist GETs. See:\n        // https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-14#section-6.3.4 (CJP)\n        const intervalId = setInterval(seekableChange, 1000);\n\n        // Make sure we clean up after ourselves.\n        mediaEl.addEventListener(\n          'teardown',\n          () => {\n            clearInterval(intervalId);\n          },\n          { once: true }\n        );\n\n        // Assume we're done updating seekable when the duration is finite, which\n        // occurs when e.g. an HLS playlist is ended (`#EXT-X-ENDLIST`).\n        addEventListenerWithTeardown(mediaEl, 'durationchange', () => {\n          if (!Number.isFinite(mediaEl.duration)) return;\n          clearInterval(intervalId);\n        });\n      };\n\n      const setupNativeStreamInfo = async () => {\n        return updateStreamInfoFromSrc(src, mediaEl, type)\n          .then(setupSeekableChangePoll)\n          .catch((errOrResp: Response | Error) => {\n            if (errOrResp instanceof Response) {\n              const mediaError = getErrorFromResponse(errOrResp, MuxErrorCategory.VIDEO, props);\n              if (mediaError) {\n                saveAndDispatchError(mediaEl, mediaError);\n                return;\n              }\n            } else if (errOrResp instanceof Error) {\n              // mediaEl.dispatchEvent(new MediaError())\n            }\n          });\n      };\n\n      if (mediaEl.preload === 'none') {\n        // NOTE: Previously, we relied on the 'loadstart' event to fetch & parse playlists for stream\n        // info for native playback scenarios. Unfortunately, per spec this event will be dispatched\n        // regardless of the preload state and regardless of whether or not fetching of the src media\n        // has, in fact, begun. In order to respect the provided preferences and avoid eager loading\n        // while still attempting to begin fetching playlists for stream info as early as possible when\n        // media *will* be loaded, we will do a \"first to the finish line\" on both the 'play' event,\n        // which will be dispatched earlier *if* it is the event that initiates media loading, and the\n        // 'loadedmetadata' event, which is dispatched only after the media has finished loading metadata,\n        // but will reliably correlate with media loading. (CJP)\n        // For more, see: Steps 7 & 8 of 'the resource selection algorithm' from \u00A74.8.11.5 Loading the\n        // media resource in the HTML Living Standard\n        // (https://html.spec.whatwg.org/multipage/media.html#concept-media-load-algorithm)\n        const playHandler = () => {\n          setupNativeStreamInfo();\n          mediaEl.removeEventListener('loadedmetadata', loadedMetadataHandler);\n        };\n        const loadedMetadataHandler = () => {\n          setupNativeStreamInfo();\n          mediaEl.removeEventListener('play', playHandler);\n        };\n        addEventListenerWithTeardown(mediaEl, 'play', playHandler, { once: true });\n        addEventListenerWithTeardown(mediaEl, 'loadedmetadata', loadedMetadataHandler, { once: true });\n      } else {\n        setupNativeStreamInfo();\n      }\n\n      // NOTE: Currently use drmToken to signal that playback is expected to be DRM-protected\n      if (props.tokens?.drm) {\n        setupNativeFairplayDRM(props, mediaEl);\n      } else {\n        // If we end up receiving an encrypted event in this case, that means the media is DRM-protected\n        // but a token was not provided.\n        addEventListenerWithTeardown(\n          mediaEl,\n          'encrypted',\n          () => {\n            const message = i18n('Attempting to play DRM-protected content without providing a DRM token.');\n            const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n            mediaError.errorCategory = MuxErrorCategory.DRM;\n            mediaError.muxCode = MuxErrorCode.ENCRYPTED_MISSING_TOKEN;\n            saveAndDispatchError(mediaEl, mediaError);\n          },\n          { once: true }\n        );\n      }\n\n      mediaEl.setAttribute('src', src);\n\n      if (props.startTime) {\n        (muxMediaState.get(mediaEl) ?? {}).startTime = props.startTime;\n        // seekable is set to the range of the entire video once durationchange fires\n        mediaEl.addEventListener('durationchange', seekInSeekableRange, { once: true });\n      }\n    } else {\n      mediaEl.removeAttribute('src');\n    }\n\n    mediaEl.addEventListener('error', handleNativeError);\n    mediaEl.addEventListener('error', handleInternalError);\n    mediaEl.addEventListener(\n      'emptied',\n      () => {\n        const trackEls: NodeListOf<HTMLTrackElement> = mediaEl.querySelectorAll('track[data-removeondestroy]');\n        trackEls.forEach((trackEl) => {\n          trackEl.remove();\n        });\n      },\n      { once: true }\n    );\n\n    addEventListenerWithTeardown(mediaEl, 'pause', maybeDispatchEndedCallback);\n    // NOTE: Browsers do not consistently fire an 'ended' event upon seeking to the\n    // end of the media while already paused. This was due to an ambiguity in the\n    // HTML specification, but is now more explicit.\n    // See: https://html.spec.whatwg.org/multipage/media.html#reaches-the-end (CJP)\n    addEventListenerWithTeardown(mediaEl, 'seeked', maybeDispatchEndedCallback);\n\n    addEventListenerWithTeardown(mediaEl, 'play', () => {\n      if (mediaEl.ended) return;\n      if (!isApproximatelyGTE(mediaEl.currentTime, mediaEl.duration)) return;\n      // If we were \"pseudo-ended\" before playback was attempted, seek back to the\n      // beginning to \"replay\", like \"real\" ended behavior.\n      mediaEl.currentTime = mediaEl.seekable.length ? mediaEl.seekable.start(0) : 0;\n    });\n  } else if (hls && src) {\n    hls.once(Hls.Events.LEVEL_LOADED, (_evt, data) => {\n      updateStreamInfoFromHlsjsLevelDetails(data.details, mediaEl, hls);\n      seekableChange();\n      // Only monitor for seekable updates if StreamType is \"live\" and duration is not finite.\n      if (getStreamType(mediaEl) === StreamTypes.LIVE && !Number.isFinite(mediaEl.duration)) {\n        hls.on(Hls.Events.LEVEL_UPDATED, seekableChange);\n\n        // Assume we're done updating seekable when the duration is finite, which\n        // occurs when e.g. an HLS playlist is ended (`#EXT-X-ENDLIST`).\n        addEventListenerWithTeardown(mediaEl, 'durationchange', () => {\n          if (!Number.isFinite(mediaEl.duration)) return;\n          hls.off(Hls.Events.LEVELS_UPDATED, seekableChange);\n        });\n      }\n    });\n\n    hls.on(Hls.Events.ERROR, (_event, data) => {\n      const error = getErrorFromHlsErrorData(data, props);\n\n      if (error.muxCode === MuxErrorCode.NETWORK_NOT_READY) {\n        const maxRetries = 6; // 5 minutes and 5 seconds total (5s, 60s, 60s, 60s, 60s, 60s)\n        const state = muxMediaState.get(mediaEl) ?? {};\n        const retryCount = state.retryCount ?? 0;\n\n        if (retryCount < maxRetries) {\n          // First retry is 5 seconds, subsequent retries are 60 seconds\n          const retryDelay = retryCount === 0 ? 5000 : 60000;\n\n          // New error with the retry delay\n          const retryDelayError = new MediaError(\n            `Retrying in ${retryDelay / 1000} seconds...`,\n            error.code,\n            error.fatal\n          );\n          Object.assign(retryDelayError, error);\n          saveAndDispatchError(mediaEl, retryDelayError);\n\n          const retryTimerId = setTimeout(() => {\n            state.retryCount = retryCount + 1;\n            if (data.details === 'manifestLoadError' && data.url) {\n              hls.loadSource(data.url);\n            }\n          }, retryDelay);\n          mediaEl.addEventListener('teardown', () => clearTimeout(retryTimerId), { once: true });\n          return;\n        } else {\n          state.retryCount = 0;\n          // New error with the retry link\n          const retryLinkError = new MediaError(\n            'Try again later or <a href=\"#\" onclick=\"window.location.reload(); return false;\" style=\"color: #4a90e2;\">click here to retry</a>',\n            error.code,\n            error.fatal\n          );\n          Object.assign(retryLinkError, error);\n          saveAndDispatchError(mediaEl, retryLinkError);\n          return;\n        }\n      }\n      saveAndDispatchError(mediaEl, error);\n    });\n\n    hls.on(Hls.Events.MANIFEST_LOADED, () => {\n      // Clear error state and UI\n      const state = muxMediaState.get(mediaEl);\n      if (state && state.error) {\n        state.error = null;\n        state.retryCount = 0;\n\n        mediaEl.dispatchEvent(new Event('emptied'));\n        mediaEl.dispatchEvent(new Event('loadstart'));\n      }\n    });\n\n    mediaEl.addEventListener('error', handleInternalError);\n    addEventListenerWithTeardown(mediaEl, 'waiting', maybeDispatchEndedCallback);\n\n    setupMediaTracks(props as HTMLMediaElement, hls);\n    setupTextTracks(mediaEl, hls);\n\n    hls.attachMedia(mediaEl);\n  } else {\n    console.error(\n      \"It looks like the video you're trying to play will not work on this system! If possible, try upgrading to the newest versions of your browser or software.\"\n    );\n  }\n};\n\nfunction seekInSeekableRange(event: Event) {\n  const mediaEl = event.target as HTMLMediaElement;\n  const startTime = muxMediaState.get(mediaEl)?.startTime;\n  if (!startTime) return;\n\n  if (inSeekableRange(mediaEl.seekable, mediaEl.duration, startTime)) {\n    // Setting preload to `none` from `auto` was required on iOS to fix a bug\n    // that caused no `timeupdate` events to fire after seeking \u00AF\\_(\u30C4)_/\u00AF\n    const wasAuto = mediaEl.preload === 'auto';\n    if (wasAuto) {\n      mediaEl.preload = 'none';\n    }\n\n    mediaEl.currentTime = startTime;\n\n    if (wasAuto) {\n      mediaEl.preload = 'auto';\n    }\n  }\n}\n\nasync function handleNativeError(event: Event) {\n  // Return if the event was created or modified by a script or dispatched\n  // via EventTarget.dispatchEvent() preventing an infinite loop.\n  if (!event.isTrusted) return;\n\n  // Stop immediate propagation of the native error event, re-dispatch below!\n  event.stopImmediatePropagation();\n\n  const mediaEl = event.target as HTMLMediaElement;\n  // Safari sometimes throws an error event with a null error.\n  if (!mediaEl?.error) return;\n\n  const { message, code } = mediaEl.error;\n  const error = new MediaError(message, code);\n\n  // This accounts for cases where native playback is being used but\n  // a non-200 response occurs on the request for the playback-id's playlist.\n  // In this case, we currently already fetch the playlist in parallel (for\n  // things like inferring the stream type, live edge start window, etc.),\n  // so we'll wait briefly for that response to translate to a more accurate\n  // error.\n  if (\n    mediaEl.src &&\n    code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED &&\n    mediaEl.readyState === HTMLMediaElement.HAVE_NOTHING\n  ) {\n    setTimeout(() => {\n      const ourError = getError(mediaEl) ?? mediaEl.error;\n      // If the code is (still) MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED,\n      // assume it's an (unlikely) case where we did, in fact, encounter\n      // media that is unsupported.\n      if (ourError?.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) {\n        saveAndDispatchError(mediaEl, error);\n      }\n      // Since a parallel request for the source should be initiated to determine\n      // stream info (e.g. streamType) at roughly the same time as when the source\n      // is loaded by the media element, we should be able to keep this timeout short.\n      // NOTE: Although there is a case where the parallel request may happen later\n      // (namely, after metadata is loaded), this should be mutually exclusive from\n      // the case we're accounting for here, since unsupported media should not\n      // ever get metadata loaded in the first place. (CJP)\n    }, 500);\n    return;\n  }\n\n  if (mediaEl.src && (code !== MediaError.MEDIA_ERR_DECODE || code !== undefined)) {\n    // Attempt to get the response code from the video src url.\n    try {\n      const { status } = await fetch(mediaEl.src);\n      // Use the same hls.js data structure.\n      error.data = { response: { code: status } };\n    } catch {}\n  }\n\n  saveAndDispatchError(mediaEl, error);\n}\n\nfunction saveAndDispatchError(mediaEl: HTMLMediaElement, error: MediaError) {\n  // Prevent dispatching non-fatal errors.\n  if (!error.fatal) return;\n\n  (muxMediaState.get(mediaEl) ?? {}).error = error as unknown as HTMLMediaElement['error'];\n\n  mediaEl.dispatchEvent(\n    new CustomEvent('error', {\n      detail: error,\n    })\n  );\n}\n\n/**\n * Use a event listener instead of a function call when dispatching the Custom error\n * event so consumers are still able to disable or intercept this error event.\n * @param {Event} event\n */\nfunction handleInternalError(event: Event | CustomEvent<MediaError>) {\n  if (!(event instanceof CustomEvent) || !(event.detail instanceof MediaError)) return;\n\n  const mediaEl = event.target as HTMLMediaElement;\n  const error = event.detail;\n  // Prevent tracking non-fatal errors in Mux data.\n  if (!error || !error.fatal) return;\n\n  (muxMediaState.get(mediaEl) ?? {}).error = error as unknown as HTMLMediaElement['error'];\n\n  // Only pass valid mux-embed props: player_error_code, player_error_message, player_error_context\n  mediaEl.mux?.emit('error', {\n    player_error_code: error.code,\n    player_error_message: error.message,\n    player_error_context: error.context,\n  });\n}\n\nconst getErrorFromHlsErrorData = (\n  data: ErrorData,\n  props: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'drmToken' | 'playbackToken' | 'tokens' | 'debug'>>\n) => {\n  // Non-fatal errors: only log when debug is enabled (using console.warn to reduce user concern)\n  const isNonFatal = !data.fatal;\n  if (isNonFatal) {\n    if (props.debug) {\n      console.warn('getErrorFromHlsErrorData() (non-fatal)', data);\n    }\n  } else {\n    console.error('getErrorFromHlsErrorData()', data);\n  }\n\n  const ErrorCodeMap: Partial<Record<ValueOf<typeof Hls.ErrorTypes>, 0 | 1 | 2 | 3 | 4 | 5>> = {\n    [Hls.ErrorTypes.NETWORK_ERROR]: MediaError.MEDIA_ERR_NETWORK,\n    [Hls.ErrorTypes.MEDIA_ERROR]: MediaError.MEDIA_ERR_DECODE,\n    [Hls.ErrorTypes.KEY_SYSTEM_ERROR]: MediaError.MEDIA_ERR_ENCRYPTED,\n  } as const;\n\n  // eslint-disable-next-line no-shadow\n  const hlsErrorDataToErrorCode = (data: ErrorData) => {\n    if (\n      [\n        Hls.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED,\n        Hls.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED,\n      ].includes(data.details)\n    ) {\n      return MediaError.MEDIA_ERR_NETWORK;\n    }\n    return ErrorCodeMap[data.type];\n  };\n\n  // eslint-disable-next-line no-shadow\n  const hlsErrorDataToCategory = (data: ErrorData) => {\n    if (data.type === Hls.ErrorTypes.KEY_SYSTEM_ERROR) return MuxErrorCategory.DRM;\n    if (data.type === Hls.ErrorTypes.NETWORK_ERROR) return MuxErrorCategory.VIDEO;\n  };\n\n  let mediaError: MediaError;\n  const errorCode = hlsErrorDataToErrorCode(data);\n  if (errorCode === MediaError.MEDIA_ERR_NETWORK && data.response) {\n    const category = hlsErrorDataToCategory(data) ?? MuxErrorCategory.VIDEO;\n    mediaError =\n      getErrorFromResponse(data.response, category, props, data.fatal) ?? new MediaError('', errorCode, data.fatal);\n  } else if (errorCode === MediaError.MEDIA_ERR_ENCRYPTED) {\n    if (data.details === Hls.ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE) {\n      const message = i18n('Attempting to play DRM-protected content without providing a DRM token.');\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_MISSING_TOKEN;\n    } else if (data.details === Hls.ErrorDetails.KEY_SYSTEM_NO_ACCESS) {\n      /** @TODO For UI message add suggestion to try another browser */\n      const message = i18n(\n        'Cannot play DRM-protected content with current security configuration on this browser. Try playing in another browser.'\n      );\n      // Should we flag this as a business exception?\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_UNSUPPORTED_KEY_SYSTEM;\n    } else if (data.details === Hls.ErrorDetails.KEY_SYSTEM_NO_SESSION) {\n      const message = i18n(\n        'Failed to generate a DRM license request. This may be an issue with the player or your protected content.'\n      );\n      // NOTE: For some reason, perhaps due to issues with EXT-X-KEY parsing, hls.js defines this as a non-fatal error.\n      // For us, we should be able to assume it is instead fatal. (CJP)\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_GENERATE_REQUEST_FAILED;\n    } else if (data.details === Hls.ErrorDetails.KEY_SYSTEM_SESSION_UPDATE_FAILED) {\n      const message = i18n(\n        'Failed to update DRM license. This may be an issue with the player or your protected content.'\n      );\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_UPDATE_LICENSE_FAILED;\n    } else if (data.details === Hls.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED) {\n      const message = i18n(\n        'Your server certificate failed when attempting to set it. This may be an issue with a no longer valid certificate.'\n      );\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_UPDATE_SERVER_CERT_FAILED;\n    } else if (data.details === Hls.ErrorDetails.KEY_SYSTEM_STATUS_INTERNAL_ERROR) {\n      const message = i18n(\n        'The DRM Content Decryption Module system had an internal failure. Try reloading the page, upading your browser, or playing in another browser.'\n      );\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_CDM_ERROR;\n    } else if (data.details === Hls.ErrorDetails.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED) {\n      const message = i18n(\n        'DRM playback is being attempted in an environment that is not sufficiently secure. User may see black screen.'\n      );\n      // NOTE: When encountered, this is a non-fatal error (though it's certainly interruptive of standard playback experience). (CJP)\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, false);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_OUTPUT_RESTRICTED;\n    } else {\n      mediaError = new MediaError(data.error.message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_ERROR;\n    }\n  } else {\n    mediaError = new MediaError('', errorCode, data.fatal);\n  }\n  if (!mediaError.context) {\n    mediaError.context =\n      `${data.url ? `url: ${data.url}\\n` : ''}` +\n      `${\n        data.response && (data.response.code || data.response.text)\n          ? `response: ${data.response.code}, ${data.response.text}\\n`\n          : ''\n      }` +\n      `${data.reason ? `failure reason: ${data.reason}\\n` : ''}` +\n      `${data.level ? `level: ${data.level}\\n` : ''}` +\n      `${data.parent ? `parent stream controller: ${data.parent}\\n` : ''}` +\n      `${data.buffer ? `buffer length: ${data.buffer}\\n` : ''}` +\n      `${data.error ? `error: ${data.error}\\n` : ''}` +\n      `${data.event ? `event: ${data.event}\\n` : ''}` +\n      `${data.err ? `error message: ${data.err?.message}\\n` : ''}`;\n  }\n  mediaError.data = data;\n  return mediaError;\n};\n", "import Hls from 'hls.js';\nimport type HlsClassType from 'hls.js';\nexport default Hls;\nexport type HlsInterface = HlsClassType;\n", "// Identifies what kind of request was made that resulted in an error\nexport const MuxErrorCategory = {\n  VIDEO: 'video',\n  THUMBNAIL: 'thumbnail',\n  STORYBOARD: 'storyboard',\n  DRM: 'drm',\n} as const;\n\nexport const MuxErrorCode = {\n  NOT_AN_ERROR: 0,\n  NETWORK_OFFLINE: 2000002,\n  NETWORK_UNKNOWN_ERROR: 2000000,\n  NETWORK_NO_STATUS: 2000001,\n  NETWORK_INVALID_URL: 2400000,\n  NETWORK_NOT_FOUND: 2404000,\n  NETWORK_NOT_READY: 2412000,\n  NETWORK_GENERIC_SERVER_FAIL: 2500000,\n  NETWORK_TOKEN_MISSING: 2403201,\n  NETWORK_TOKEN_MALFORMED: 2412202,\n  NETWORK_TOKEN_EXPIRED: 2403210,\n  NETWORK_TOKEN_AUD_MISSING: 2403221,\n  NETWORK_TOKEN_AUD_MISMATCH: 2403222,\n  NETWORK_TOKEN_SUB_MISMATCH: 2403232,\n  ENCRYPTED_ERROR: 5000000, // Generic\n  ENCRYPTED_UNSUPPORTED_KEY_SYSTEM: 5000001,\n  ENCRYPTED_GENERATE_REQUEST_FAILED: 5000002,\n  ENCRYPTED_UPDATE_LICENSE_FAILED: 5000003,\n  ENCRYPTED_UPDATE_SERVER_CERT_FAILED: 5000004,\n  ENCRYPTED_CDM_ERROR: 5000005,\n  ENCRYPTED_OUTPUT_RESTRICTED: 5000006,\n  ENCRYPTED_MISSING_TOKEN: 5000002,\n} as const;\n\nexport type MuxErrorCategory = typeof MuxErrorCategory;\nexport type MuxErrorCode = typeof MuxErrorCode;\n\nexport type MuxErrorCategoryValue = MuxErrorCategory[keyof MuxErrorCategory];\nexport type MuxErrorCodeValue = MuxErrorCode[keyof MuxErrorCode];\n\nexport const errorCategoryToTokenNameOrPrefix = (category: MuxErrorCategoryValue) => {\n  if (category === MuxErrorCategory.VIDEO) return 'playback';\n  return category;\n};\n\n// Typescript says it's strictly a string, but it can also be a number or an object with a toString method.\n// https://github.com/microsoft/TypeScript/issues/6032\n// https://262.ecma-international.org/6.0/#sec-error-message\n\ntype Stringable = string | { toString(): string };\n\ndeclare global {\n  interface ErrorConstructor {\n    new (message?: Stringable): Error;\n    (message?: Stringable): Error;\n    readonly prototype: Error;\n  }\n}\n\nexport class MediaError extends Error {\n  static MEDIA_ERR_ABORTED = 1 as const;\n  static MEDIA_ERR_NETWORK = 2 as const;\n  static MEDIA_ERR_DECODE = 3 as const;\n  static MEDIA_ERR_SRC_NOT_SUPPORTED = 4 as const;\n  static MEDIA_ERR_ENCRYPTED = 5 as const;\n  // @see https://docs.mux.com/guides/data/monitor-html5-video-element#customize-error-tracking-behavior\n  static MEDIA_ERR_CUSTOM = 100;\n\n  static defaultMessages: Record<number, string> = {\n    1: 'You aborted the media playback',\n    2: 'A network error caused the media download to fail.',\n    3: 'A media error caused playback to be aborted. The media could be corrupt or your browser does not support this format.',\n    4: 'An unsupported error occurred. The server or network failed, or your browser does not support this format.',\n    5: 'The media is encrypted and there are no keys to decrypt it.',\n  };\n\n  name: string;\n  code: number;\n  public muxCode?: MuxErrorCodeValue;\n  public errorCategory?: MuxErrorCategoryValue;\n  context?: string;\n  fatal: boolean;\n  data?: any;\n  streamType?: 'live' | 'on-demand' | 'unknown';\n\n  constructor(message?: Stringable, code: number = MediaError.MEDIA_ERR_CUSTOM, fatal?: boolean, context?: string) {\n    super(message);\n    this.name = 'MediaError';\n    this.code = code;\n    this.context = context;\n    this.fatal = fatal ?? (code >= MediaError.MEDIA_ERR_NETWORK && code <= MediaError.MEDIA_ERR_ENCRYPTED);\n\n    if (!this.message) {\n      this.message = MediaError.defaultMessages[this.code] ?? '';\n    }\n  }\n}\n", "/* eslint @typescript-eslint/triple-slash-reference: \"off\" */\n/// <reference path=\"../../../node_modules/mux-embed/dist/types/mux-embed.d.ts\" preserve=\"true\" />\nimport type { Options, Mux } from 'mux-embed';\nimport type { MediaError } from './errors';\nimport type { HlsConfig } from 'hls.js';\nimport type Hls from 'hls.js';\n\ntype KeyTypes = string | number | symbol;\ntype Maybe<T> = T | null | undefined;\n\nconst isNil = (x: unknown): x is null | undefined => x == undefined;\n\n// Type Guard to determine if a given key is actually a key of some object of type T\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport const isKeyOf = <T extends {} = any>(k: KeyTypes, o: Maybe<T>): k is keyof T => {\n  if (isNil(o)) return false;\n  return k in o;\n};\n\nexport type ValueOf<T> = T[keyof T];\nexport type Metadata = Partial<Required<Options>['data']>;\ntype MetaData = Metadata;\nexport type PlaybackEngine = Hls;\nexport type MuxDataSDK = Mux;\n\nexport type PlaybackCore = {\n  engine?: PlaybackEngine;\n  muxDataSDK?: MuxDataSDK;\n  setAutoplay: (autoplay?: Autoplay) => void;\n  setPreload: (preload?: HTMLMediaElement['preload']) => void;\n};\n\n// TODO add INVIEW_MUTED, INVIEW_ANY\nexport type AutoplayTypes = {\n  ANY: 'any';\n  MUTED: 'muted';\n};\n\nexport const AutoplayTypes: AutoplayTypes = {\n  ANY: 'any',\n  MUTED: 'muted',\n};\n\nexport type Autoplay = boolean | ValueOf<AutoplayTypes>;\n\nexport type HlsPlaylistTypes = 'VOD' | 'EVENT' | null | undefined;\n\nexport type StreamTypes = {\n  ON_DEMAND: 'on-demand';\n  LIVE: 'live';\n  UNKNOWN: 'unknown';\n};\n\nexport const StreamTypes: StreamTypes = {\n  ON_DEMAND: 'on-demand',\n  LIVE: 'live',\n  UNKNOWN: 'unknown',\n};\n\nexport type PlaybackTypes = {\n  MSE: 'mse';\n  NATIVE: 'native';\n};\n\nexport const PlaybackTypes: PlaybackTypes = {\n  MSE: 'mse',\n  NATIVE: 'native',\n};\n\nexport type CmcdTypes = {\n  HEADER: 'header';\n  QUERY: 'query';\n  NONE: 'none';\n};\n\nexport const CmcdTypes: CmcdTypes = {\n  HEADER: 'header',\n  QUERY: 'query',\n  NONE: 'none',\n};\n\nexport const CmcdTypeValues = Object.values(CmcdTypes);\n\nexport type ExtensionMimeTypeMap = {\n  M3U8: 'application/vnd.apple.mpegurl';\n  MP4: 'video/mp4';\n};\n\nexport const ExtensionMimeTypeMap: ExtensionMimeTypeMap = {\n  M3U8: 'application/vnd.apple.mpegurl',\n  MP4: 'video/mp4',\n};\n\nexport type MimeTypeShorthandMap = {\n  HLS: ExtensionMimeTypeMap['M3U8'];\n};\n\nexport const MimeTypeShorthandMap: MimeTypeShorthandMap = {\n  HLS: ExtensionMimeTypeMap.M3U8,\n};\n\nexport const shorthandKeys = Object.keys(MimeTypeShorthandMap);\n\nexport type MediaTypes =\n  | ValueOf<ExtensionMimeTypeMap>\n  | keyof MimeTypeShorthandMap\n  /** @TODO Figure out a way to \"downgrade\" derived types below to early TS syntax (e.g. 3.4) instead of explicit versions here (CJP) */\n  | 'hls';\n// | `${Lowercase<keyof MimeTypeShorthandMap>}`\n// | `${Uppercase<keyof MimeTypeShorthandMap>}`;\n\nexport const allMediaTypes = [\n  ...(Object.values(ExtensionMimeTypeMap) as ValueOf<ExtensionMimeTypeMap>[]),\n  /** @TODO Figure out a way to \"downgrade\" derived types below to early TS syntax (e.g. 3.4) instead of explicit versions here (CJP) */\n  'hls',\n  'HLS',\n  // ...(shorthandKeys as (keyof MimeTypeShorthandMap)[]),\n  // ...(shorthandKeys.map((k) => k.toUpperCase()) as `${Uppercase<keyof MimeTypeShorthandMap>}`[]),\n  // ...(shorthandKeys.map((k) => k.toLowerCase()) as `${Lowercase<keyof MimeTypeShorthandMap>}`[]),\n] as MediaTypes[];\n\n// Both cuepoints and chapters have optional end times\n// so support both joined up and sparse cue placements\ntype CueLike<T = any> = {\n  startTime: number;\n  endTime?: number;\n  value: T;\n};\nexport type CuePoint<T = any> =\n  | CueLike<T> // new shape\n  | { time: number; value: T }; // legacy shape, still supported for now\nexport type Chapter = CueLike<string>;\n\nexport const MaxResolution = {\n  upTo720p: '720p',\n  upTo1080p: '1080p',\n  upTo1440p: '1440p',\n  upTo2160p: '2160p',\n} as const;\n\nexport const MinResolution = {\n  noLessThan480p: '480p',\n  noLessThan540p: '540p',\n  noLessThan720p: '720p',\n  noLessThan1080p: '1080p',\n  noLessThan1440p: '1440p',\n  noLessThan2160p: '2160p',\n} as const;\n\nexport const RenditionOrder = {\n  DESCENDING: 'desc',\n} as const;\n\nexport const MaxAutoResolution = {\n  upTo720p: '720p',\n  upTo1080p: '1080p',\n  upTo1440p: '1440p',\n  upTo2160p: '2160p',\n} as const;\n\nexport type MaxResolutionValue = ValueOf<typeof MaxResolution>;\nexport type MinResolutionValue = ValueOf<typeof MinResolution>;\nexport type RenditionOrderValue = ValueOf<typeof RenditionOrder>;\nexport type MaxAutoResolutionValue = ValueOf<typeof MaxAutoResolution>;\n\nexport type Tokens = {\n  playback?: string;\n  drm?: string;\n  thumbnail?: string;\n  storyboard?: string;\n};\n\nexport type MuxMediaPropTypes = {\n  _hlsConfig?: Partial<HlsConfig>;\n  autoPlay?: Autoplay;\n  autoplay?: Autoplay;\n  /** Based on `cap-rendition-to-player-size` attribute and `_hlsConfig.capLevelToPlayerSize` */\n  capRenditionToPlayerSize?: boolean;\n  beaconCollectionDomain: Options['beaconCollectionDomain'];\n  customDomain: string;\n  debug: Options['debug'] & Hls['config']['debug'];\n  disableCookies: Options['disableCookies'];\n  disableTracking: boolean;\n  disablePseudoEnded: boolean;\n  drmToken?: string;\n  playbackToken?: string;\n  envKey: MetaData['env_key'];\n  error?: HTMLMediaElement['error'] | MediaError;\n  errorTranslator: Options['errorTranslator'];\n  liveEdgeStart: number;\n  maxResolution: MaxResolutionValue;\n  metadata: Partial<Options['data']>;\n  minResolution: MinResolutionValue;\n  maxAutoResolution: MaxAutoResolutionValue;\n  playbackId: string;\n  playerInitTime: MetaData['player_init_time'];\n  preferCmcd: ValueOf<CmcdTypes> | undefined;\n  preferPlayback: ValueOf<PlaybackTypes> | undefined;\n  programStartTime: number;\n  programEndTime: number;\n  assetStartTime: number;\n  assetEndTime: number;\n  renditionOrder: RenditionOrderValue;\n  startTime: Hls['config']['startPosition'];\n  initialBandwidthEstimateKbps: number;\n  initialEstimateSegments: number;\n  minPreloadSegments: number;\n  streamType: ValueOf<StreamTypes>;\n  targetLiveWindow: number;\n  tokens: Tokens;\n  type: MediaTypes;\n  extraSourceParams: Record<string, any>;\n};\n\nexport type HTMLMediaElementProps = Partial<Pick<HTMLMediaElement, 'src' | 'preload' | 'error' | 'seekable'>>;\n\nexport type MuxMediaProps = HTMLMediaElementProps &\n  MuxMediaPropTypes & {\n    // TODO: useWebkitFairplay and fallbackToWebkitFairplay can be removed once webkit fallback is no longer necessary\n    useWebkitFairplay?: boolean;\n    fallbackToWebkitFairplay: () => void;\n  };\nexport type MuxMediaPropsInternal = MuxMediaProps & {\n  playerSoftwareName: MetaData['player_software_name'];\n  playerSoftwareVersion: MetaData['player_software_version'];\n  muxDataSDK?: Mux;\n  muxDataSDKOptions?: Mux;\n  muxDataKeepSession?: boolean;\n  drmTypeCb?: (drmType: Metadata['view_drm_type']) => void;\n};\n\n// TODO: Make these more uniform, remove bubbles, discuss to remove detail.\nexport type MuxMediaEventsMap = {\n  cuepointchange: CustomEvent<{ composed: true; bubbles: true; detail: CuePoint }>;\n  chapterchange: CustomEvent<{ composed: true; bubbles: true; detail: Chapter }>;\n  targetlivewindowchange: CustomEvent<{ composed: true; bubbles: true }>;\n  streamtypechange: CustomEvent<{ composed: true; bubbles: true }>;\n  seekablechange: CustomEvent<{ composed: true }>;\n  error: CustomEvent<{ detail: MediaError }>;\n};\n", "const code = 'en'; export default { code }", "import { isKeyOf, ExtensionMimeTypeMap, MimeTypeShorthandMap, StreamTypes } from './types';\nimport type { HlsPlaylistTypes, MuxMediaProps } from './types';\n// @ts-ignore\nimport lang from '../lang/en.json';\n\ntype addEventListenerWithTeardown = <\n  K extends keyof HTMLMediaElementEventMap,\n  T extends EventTarget = HTMLMediaElement,\n>(\n  mediaEl: HTMLMediaElement,\n  type: K,\n  listener: (this: T, ev: HTMLMediaElementEventMap[K]) => any,\n  options?: boolean | AddEventListenerOptions,\n  target?: T | HTMLMediaElement\n) => void;\n\n// Adds an event listener to a media element that will be removed when an 'teardown' event is dispatched.\n// Using this instead of 'emptied' as that can fire on initial load based on prior state of the media element\n// Will be fired as a result of (directly or indirectly) invoking playback-core's `teardown()` function.\nexport const addEventListenerWithTeardown: addEventListenerWithTeardown = (\n  mediaEl,\n  type,\n  listener,\n  options,\n  target = mediaEl\n) => {\n  /** @TODO fix types (hard problem due to lack of explicit relationship between Element and EventMap definitions) */\n  // @ts-ignore\n  target.addEventListener(type, listener, options);\n  // NOTE: Using custom teardown\n  mediaEl.addEventListener(\n    'teardown',\n    () => {\n      /** @TODO fix types (hard problem due to lack of explicit relationship between Element and EventMap definitions) */\n      // @ts-ignore\n      target.removeEventListener(type, listener);\n    },\n    { once: true }\n  );\n};\n\nexport function inSeekableRange(seekable: TimeRanges, duration: number, time: number) {\n  if (duration && time > duration) {\n    time = duration;\n  }\n  for (let i = 0; i < seekable.length; i++) {\n    if (seekable.start(i) <= time && seekable.end(i) >= time) {\n      return true;\n    }\n  }\n  return false;\n}\n\nexport const toPlaybackIdParts = (playbackIdWithOptionalParams: string): [string, string?] => {\n  const qIndex = playbackIdWithOptionalParams.indexOf('?');\n  if (qIndex < 0) return [playbackIdWithOptionalParams];\n  const idPart = playbackIdWithOptionalParams.slice(0, qIndex);\n  const queryPart = playbackIdWithOptionalParams.slice(qIndex);\n  return [idPart, queryPart];\n};\n\nexport const getType = (props: Partial<Pick<MuxMediaProps, 'type' | 'src' | 'customDomain'>>) => {\n  const { type } = props;\n  if (type) {\n    const upperType = type.toUpperCase();\n    return isKeyOf(upperType, MimeTypeShorthandMap) ? MimeTypeShorthandMap[upperType] : type;\n  }\n  return inferMimeTypeFromURL(props);\n};\n\nexport const toStreamTypeFromPlaylistType = (playlistType: HlsPlaylistTypes) => {\n  return playlistType === 'VOD' ? StreamTypes.ON_DEMAND : StreamTypes.LIVE;\n};\n\nexport const toTargetLiveWindowFromPlaylistType = (playlistType: HlsPlaylistTypes) => {\n  if (playlistType === 'EVENT') return Number.POSITIVE_INFINITY;\n  if (playlistType === 'VOD') return Number.NaN;\n  return 0;\n};\n\nexport const inferMimeTypeFromURL = (props: Partial<Pick<MuxMediaProps, 'src' | 'customDomain'>>) => {\n  const { src } = props;\n  if (!src) return '';\n\n  let pathname = '';\n  try {\n    pathname = toAbsoluteUrl(src).pathname;\n  } catch (_e) {\n    console.error('Invalid url when trying to infer mime type', src);\n  }\n\n  const extDelimIdx = pathname.lastIndexOf('.');\n  if (extDelimIdx < 0) {\n    if (isExtensionLessMuxM3U8URL(props)) {\n      return ExtensionMimeTypeMap.M3U8; // Treat extension-less Mux URLs as HLS\n    }\n    return '';\n  }\n\n  const ext = pathname.slice(extDelimIdx + 1);\n  const upperExt = ext.toUpperCase();\n\n  return isKeyOf(upperExt, ExtensionMimeTypeMap) ? ExtensionMimeTypeMap[upperExt] : '';\n};\n\nexport const isRelativeUrl = (url: string): boolean => {\n  try {\n    new URL(url);\n    return false;\n  } catch {\n    return true;\n  }\n};\n\n/**\n * Returns the first media playlist URL from a multivariant HLS playlist string,\n * i.e. the URI line that immediately follows an `#EXT-X-STREAM-INF` tag.\n *\n * @returns The URL string, or `undefined` if no `#EXT-X-STREAM-INF` entry is found.\n */\nexport const getFirstMediaPlaylistUrl = (multivariantPlaylist: string): string | undefined => {\n  return multivariantPlaylist.split('\\n').find((_line, idx, lines) => {\n    return idx > 0 && lines[idx - 1].startsWith('#EXT-X-STREAM-INF');\n  });\n};\n\n/**\n * Resolves `url` to an absolute `URL` instance.\n *\n * - If `url` is already absolute it is returned as-is.\n * - If `url` is relative, `base` is used to resolve it. When `base` is itself\n *   relative it is first resolved against `window?.location?.href`.\n * - If undefined, `base` defaults to `window?.location?.href`.\n *\n * @throws {TypeError} If both `url` and `base` are relative, or if\n *   either `url` or `base` value cannot be parsed as a valid URL.\n */\nexport const toAbsoluteUrl = (url: string, base?: string | URL): URL => {\n  if (!isRelativeUrl(url)) return new URL(url);\n  const windowLocation = window?.location?.href;\n  let absoluteBase: string | URL = base ?? windowLocation;\n  if (base && isRelativeUrl(base.toString())) {\n    absoluteBase = new URL(base, windowLocation);\n  }\n  return new URL(url, absoluteBase);\n};\n\nconst MUX_VIDEO_DOMAIN = 'mux.com';\nexport const isExtensionLessMuxM3U8URL = ({\n  src,\n  customDomain = MUX_VIDEO_DOMAIN,\n}: Partial<Pick<MuxMediaProps, 'src' | 'customDomain'>>) => {\n  let urlObj;\n  try {\n    urlObj = new URL(`${src}`);\n  } catch {\n    return false;\n  }\n  const validProtocol = urlObj.protocol === 'https:';\n  const validHostname = urlObj.hostname === `stream.${customDomain}`.toLowerCase();\n  const pathParts = urlObj.pathname.split('/');\n  const validPathPartsLength = pathParts.length === 2;\n  const validExtensionlessPath = !pathParts?.[1].includes('.');\n  return validProtocol && validHostname && validPathPartsLength && validExtensionlessPath;\n};\n\nexport type MuxJWT = {\n  sub: string;\n  aud: 'v' | 't' | 'g' | 's' | 'd';\n  exp: number;\n};\n\nexport const parseJwt = (token: string | undefined): Partial<MuxJWT> | undefined => {\n  const base64Url = (token ?? '').split('.')[1];\n\n  // exit early on invalid value\n  if (!base64Url) return undefined;\n\n  // Account for malformed JWTs\n  try {\n    const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');\n    const jsonPayload = decodeURIComponent(\n      atob(base64)\n        .split('')\n        .map(function (c) {\n          return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n        })\n        .join('')\n    );\n    return JSON.parse(jsonPayload);\n  } catch {\n    return undefined;\n  }\n};\n\nexport const isJWTExpired = ({ exp }: Partial<Pick<MuxJWT, 'exp'>>, referenceTime: number = Date.now()) => {\n  return !exp || exp * 1000 < referenceTime;\n};\n\n// NOTE: Treating missing sub (and expected sub) as mismatches for now (CJP)\nexport const isJWTSubMismatch = ({ sub }: Partial<Pick<MuxJWT, 'sub'>>, expectedSub: string | undefined) => {\n  return sub !== expectedSub;\n};\n\nexport const isJWTAudMissing = ({ aud }: Partial<Pick<MuxJWT, 'aud'>>, _expectedAud: string | undefined) => {\n  return !aud;\n};\n\nexport const isJWTAudMismatch = ({ aud }: Partial<Pick<MuxJWT, 'aud'>>, expectedAud: string | undefined) => {\n  return aud !== expectedAud;\n};\n\nconst DEFAULT_LOCALE = 'en';\n\n// NL example\n// lang = {\n//   \"Network Error\": \"Netwerk Fout\",\n// };\nexport function i18n(str: string, translate = true) {\n  const message = translate ? ((lang as unknown as any)?.[str] ?? str) : str;\n  const locale = translate ? (lang as unknown as any).code : DEFAULT_LOCALE;\n  return new IntlMessageFormat(message, locale);\n}\n\n/**\n * Poor man's IntlMessageFormat, enrich if need be.\n * @see https://formatjs.io/docs/intl-messageformat/\n */\nclass IntlMessageFormat {\n  message: string;\n  locale: string;\n\n  /** @TODO re-implement esbuild custom plugin for code usage (CJP) */\n  constructor(message: string, locale = (lang as unknown as any) ?? DEFAULT_LOCALE) {\n    this.message = message;\n    this.locale = locale;\n  }\n\n  format(values: Record<string, any>): string {\n    return this.message.replace(/\\{(\\w+)\\}/g, (_match, key) => {\n      return values[key] ?? '';\n    });\n  }\n\n  toString() {\n    return this.message;\n  }\n}\n", "import { addEventListenerWithTeardown } from './util';\nimport { ValueOf, Autoplay, AutoplayTypes, PlaybackEngine, MuxMediaPropsInternal, StreamTypes } from './types';\nimport Hls from './hls';\n\nconst AutoplayTypeValues = Object.values(AutoplayTypes);\nexport const isAutoplayValue = (value: unknown): value is Autoplay => {\n  return (\n    typeof value === 'boolean' ||\n    (typeof value === 'string' && AutoplayTypeValues.includes(value as ValueOf<AutoplayTypes>))\n  );\n};\n\n// Given a video element, will listen to lifecycle events to determine important\n// things like whether the video is live or whether the video has played\n// and then handles autoplaying the video as appropraite.\n// It works with both the native video element or hls.js.\n// This returns a method UpdateAutoplay, that allows the user to change\n// the value of the autoplay attribute and it will react appropriately.\nexport const setupAutoplay = (\n  props: Partial<MuxMediaPropsInternal>,\n  mediaEl: HTMLMediaElement,\n  hls?: PlaybackEngine\n) => {\n  const { autoplay: maybeAutoplay } = props;\n  let hasPlayed = false;\n  let isLive = false;\n  let autoplay: Autoplay = isAutoplayValue(maybeAutoplay) ? maybeAutoplay : !!maybeAutoplay;\n\n  const updateHasPlayed = () => {\n    // hasPlayed\n\n    if (!hasPlayed) {\n      addEventListenerWithTeardown(\n        mediaEl,\n        'playing',\n        () => {\n          hasPlayed = true;\n        },\n        { once: true }\n      );\n    }\n  };\n\n  updateHasPlayed();\n\n  // on `loadstart`\n  // hasPlayed should default to false\n  // we should try and autoplay\n  addEventListenerWithTeardown(\n    mediaEl,\n    'loadstart',\n    () => {\n      hasPlayed = false;\n      updateHasPlayed();\n      handleAutoplay(mediaEl, autoplay);\n    },\n    { once: true }\n  );\n\n  // on `loadedmetadata` we can check whether we're live in the case of native playback\n  addEventListenerWithTeardown(\n    mediaEl,\n    'loadstart',\n    () => {\n      // only update isLive here if we're using native playback\n      if (!hls) {\n        // defer to streamType if set (including inferred)\n        if (props.streamType && props.streamType !== StreamTypes.UNKNOWN) {\n          isLive = props.streamType === StreamTypes.LIVE;\n        } else {\n          isLive = !Number.isFinite(mediaEl.duration);\n        }\n      }\n      handleAutoplay(mediaEl, autoplay);\n    },\n    { once: true }\n  );\n\n  // determine if we're live for hls.js\n  if (hls) {\n    hls.once(Hls.Events.LEVEL_LOADED, (_event: any, data: any) => {\n      // defer to streamType if set (including inferred)\n      if (props.streamType && props.streamType !== StreamTypes.UNKNOWN) {\n        isLive = props.streamType === StreamTypes.LIVE;\n      } else {\n        isLive = data.details.live ?? false;\n      }\n    });\n  }\n\n  // When we are not auto-playing, we should seek to the live sync position\n  // This will seek first play event of *any* live video including event-type,\n  // which probably shouldn't seek\n  if (!autoplay) {\n    const handleSeek = () => {\n      // don't seek if we're not live or if a `startTime` has been explicitly set\n      if (!isLive || Number.isFinite(props.startTime)) {\n        return;\n      }\n      // seek to either hls.js's liveSyncPosition or the native seekable end\n      if (hls?.liveSyncPosition) {\n        mediaEl.currentTime = hls.liveSyncPosition;\n      } else {\n        if (Number.isFinite(mediaEl.seekable.end(0))) {\n          mediaEl.currentTime = mediaEl.seekable.end(0);\n        }\n      }\n    };\n    if (hls) {\n      addEventListenerWithTeardown(\n        mediaEl,\n        'play',\n        () => {\n          if (mediaEl.preload === 'metadata') {\n            hls.once(Hls.Events.LEVEL_UPDATED, handleSeek);\n          } else {\n            handleSeek();\n          }\n        },\n        { once: true }\n      );\n    }\n  }\n\n  // this method allows us to update the value of autoplay\n  // and try autoplaying appropriately.\n  const updateAutoplay = (newAutoplay?: Autoplay) => {\n    if (!hasPlayed) {\n      autoplay = isAutoplayValue(newAutoplay) ? newAutoplay : !!newAutoplay;\n      handleAutoplay(mediaEl, autoplay);\n    }\n  };\n\n  return updateAutoplay;\n};\n\nexport const handleAutoplay = (mediaEl: HTMLMediaElement, autoplay: Autoplay) => {\n  if (!autoplay) {\n    return;\n  }\n\n  const oldMuted = mediaEl.muted;\n  const restoreMuted = () => (mediaEl.muted = oldMuted);\n\n  switch (autoplay) {\n    // ANY:\n    // try to play with current options\n    // if it fails, mute and try playing again\n    // if that fails, restore muted state and don't try playing again\n    case AutoplayTypes.ANY:\n      mediaEl.play().catch(() => {\n        mediaEl.muted = true;\n        mediaEl.play().catch(restoreMuted);\n      });\n      break;\n\n    // MUTED:\n    // mute the player and then try playing\n    // if that fails, restore muted state\n    case AutoplayTypes.MUTED:\n      mediaEl.muted = true;\n      mediaEl.play().catch(restoreMuted);\n      break;\n\n    // Default or if autoplay is a boolean attribute:\n    // Try playing the video and catch the failed autoplay warning\n    default: // eslint-disable-next-line\n      mediaEl.play().catch(() => {});\n      break;\n  }\n};\n", "import { addEventListenerWithTeardown } from './util';\nimport { PlaybackEngine } from './types';\n\nexport const setupPreload = (\n  { preload, src }: Partial<HTMLMediaElement>,\n  mediaEl: HTMLMediaElement,\n  hls?: PlaybackEngine\n) => {\n  const updatePreload = (val?: HTMLMediaElement['preload']) => {\n    if (val != null && ['', 'none', 'metadata', 'auto'].includes(val)) {\n      mediaEl.setAttribute('preload', val);\n    } else {\n      mediaEl.removeAttribute('preload');\n    }\n  };\n\n  // handle native without hls.js (MSE)\n  if (!hls) {\n    updatePreload(preload);\n    return updatePreload;\n  }\n\n  let hasLoadedSource = false;\n  let hasPlayFired = false;\n\n  const originalLength = hls.config.maxBufferLength;\n  const originalSize = hls.config.maxBufferSize;\n\n  const updateHlsPreload = (val?: HTMLMediaElement['preload']) => {\n    // even if it doesn't have an effect on a <video> w/ MSE\n    // still update the `preload` attribute.\n    updatePreload(val);\n\n    const newPreload = val ?? mediaEl.preload;\n    if (hasPlayFired || newPreload === 'none') return;\n    if (newPreload === 'metadata') {\n      // load the least amount of data possible\n      hls.config.maxBufferLength = 1;\n      hls.config.maxBufferSize = 1;\n    } else {\n      hls.config.maxBufferLength = originalLength;\n      hls.config.maxBufferSize = originalSize;\n    }\n\n    safeLoadSource();\n  };\n\n  const safeLoadSource = () => {\n    if (!hasLoadedSource && src) {\n      hasLoadedSource = true;\n      hls.loadSource(src);\n    }\n  };\n\n  addEventListenerWithTeardown(\n    mediaEl,\n    'play',\n    () => {\n      hasPlayFired = true;\n\n      // once a user has played, allow for it to load data as normal\n      hls.config.maxBufferLength = originalLength;\n      hls.config.maxBufferSize = originalSize;\n\n      // load the source on first play if needed\n      safeLoadSource();\n    },\n    { once: true }\n  );\n\n  updateHlsPreload(preload);\n\n  return updateHlsPreload;\n};\n", "import { addEventListenerWithTeardown } from './util';\nimport { MuxMediaPropsInternal, PlaybackEngine } from './types';\nimport Hls from './hls';\n\n// Defers visible playback until N main segments have buffered. Rather\n// than intercepting play()/pause() (which races with their async events\n// and complicates autoplay/muted-fallback logic), we pin the media\n// element's `playbackRate` to 0 while preloading. This lets all normal\n// playback APIs run unchanged \u2014 the element just doesn't advance\n// frames \u2014 giving ABR real bandwidth data and buffer runway before\n// playback visually starts.\nexport const setupMinPreload = (\n  props: Partial<MuxMediaPropsInternal>,\n  mediaEl: HTMLMediaElement,\n  hls?: PlaybackEngine\n) => {\n  const { minPreloadSegments } = props;\n  if (minPreloadSegments == null || minPreloadSegments <= 0 || !hls) return;\n\n  let mainSegmentsBuffered = 0;\n  let restored = false;\n  let userPlaybackRate = mediaEl.playbackRate || 1;\n\n  // While the listener is attached we only ever write rate=0 internally.\n  // `ratechange` is dispatched async (queued as a media element task per\n  // the HTML spec), so a synchronous \"is this our own write?\" flag would\n  // always be cleared by the time the event fires and cannot be used to\n  // distinguish internal vs. user-driven changes. Instead, any non-zero\n  // rate observed here must be user-driven: capture it and re-clamp to 0.\n  // The single non-zero internal write (restoration, below) happens only\n  // after the listener has been removed, preserving this invariant.\n  const onRateChange = () => {\n    if (mediaEl.playbackRate !== 0) {\n      userPlaybackRate = mediaEl.playbackRate;\n      mediaEl.playbackRate = 0;\n    }\n  };\n\n  mediaEl.playbackRate = 0;\n  // Use addEventListenerWithTeardown so the listener is removed on\n  // `teardown` (e.g. source change). Otherwise, if the player is torn\n  // down before the preload threshold is reached, the leaked listener\n  // would keep clamping playbackRate to 0 on the media element.\n  addEventListenerWithTeardown(mediaEl, 'ratechange', onRateChange);\n\n  const onFragBuffered = (_e: any, { frag }: any) => {\n    if (restored || frag.type !== 'main') return;\n    mainSegmentsBuffered++;\n    if (mainSegmentsBuffered >= minPreloadSegments) {\n      restored = true;\n      // Remove the listener BEFORE restoring rate. The restoring write is\n      // the only non-zero internal write; if the listener were still\n      // attached, the resulting (async) `ratechange` would be misread as\n      // a user change and immediately re-clamp to 0.\n      mediaEl.removeEventListener('ratechange', onRateChange);\n      mediaEl.playbackRate = userPlaybackRate;\n    }\n  };\n  hls.on(Hls.Events.FRAG_BUFFERED, onFragBuffered);\n\n  // If teardown happens before the preload threshold is reached (e.g. source\n  // change, destroy), restore playbackRate so the media element isn't left\n  // pinned at 0 for any future reuse. The `ratechange` listener is already\n  // removed by addEventListenerWithTeardown, so this write won't be re-clamped.\n  // Also explicitly detach the FRAG_BUFFERED handler \u2014 `hls.destroy()` already\n  // tears down its listeners, but this guards against the case where the same\n  // hls instance outlives this preload setup.\n  mediaEl.addEventListener(\n    'teardown',\n    () => {\n      if (restored) return;\n      restored = true;\n      hls.off(Hls.Events.FRAG_BUFFERED, onFragBuffered);\n      mediaEl.playbackRate = userPlaybackRate;\n    },\n    { once: true }\n  );\n};\n\n// TCP slow start poisons the first bandwidth measurements. When set,\n// the first N segments use the initial estimate. We reset the EWMA\n// estimator after each of the first N-1 segments so ABR doesn't\n// downshift from poisoned measurements before TCP is warm.\nexport const setupInitialEstimate = (\n  props: Partial<MuxMediaPropsInternal>,\n  _mediaEl: HTMLMediaElement,\n  hls?: PlaybackEngine\n) => {\n  const { initialEstimateSegments } = props;\n  if (initialEstimateSegments == null || initialEstimateSegments <= 0 || !hls) return;\n\n  let mainSegmentsBuffered = 0;\n  hls.on(Hls.Events.FRAG_BUFFERED, (_e: any, { frag }: any) => {\n    if (frag.type !== 'main') return;\n    mainSegmentsBuffered++;\n    if (mainSegmentsBuffered < initialEstimateSegments) {\n      // abrController is private in HLS.js types but accessible at runtime\n      (hls as any).abrController.resetEstimator(hls.config.abrEwmaDefaultEstimate);\n    }\n  });\n};\n", "import Hls from './hls';\n\nexport function setupMediaTracks(\n  customMediaEl: HTMLMediaElement,\n  hls: Pick<\n    Hls,\n    'audioTrack' | 'audioTracks' | 'autoLevelEnabled' | 'nextLevel' | 'levels' | 'on' | 'once' | 'off' | 'trigger'\n  >\n) {\n  if (!('videoTracks' in customMediaEl)) return;\n\n  // Create a map to save the unique id's we create for each level and rendition.\n  // hls.js uses the levels array index primarily but we'll use the id to have a\n  // 1 to 1 relation from rendition to level.\n  const levelIdMap = new WeakMap();\n\n  hls.on(Hls.Events.MANIFEST_PARSED, function (_event, data) {\n    removeAllMediaTracks();\n\n    const videoTrack = customMediaEl.addVideoTrack('main');\n    videoTrack.selected = true;\n\n    for (const [id, level] of data.levels.entries()) {\n      const videoRendition = videoTrack.addRendition(\n        level.url[0],\n        level.width,\n        level.height,\n        level.videoCodec,\n        level.bitrate\n      );\n\n      // The returned levels all have an id of `0`, save the id in a WeakMap.\n      levelIdMap.set(level, `${id}`);\n      videoRendition.id = `${id}`;\n    }\n  });\n\n  hls.on(Hls.Events.AUDIO_TRACKS_UPDATED, function (_event, data) {\n    removeAudioTracks();\n\n    for (const a of data.audioTracks) {\n      // hls.js doesn't return a `kind` property for audio tracks yet.\n      const kind = a.default ? 'main' : 'alternative';\n      const audioTrack = customMediaEl.addAudioTrack(kind, a.name, a.lang);\n      audioTrack.id = `${a.id}`;\n\n      if (a.default) {\n        audioTrack.enabled = true;\n      }\n    }\n  });\n\n  const switchAudioTrack = () => {\n    // Cast to number, hls.js uses numeric id's.\n    const audioTrackId = +[...customMediaEl.audioTracks].find((t) => t.enabled)?.id;\n    const availableIds = hls.audioTracks.map((t) => t.id);\n    if (audioTrackId != hls.audioTrack && availableIds.includes(audioTrackId)) {\n      hls.audioTrack = audioTrackId;\n    }\n  };\n\n  customMediaEl.audioTracks.addEventListener('change', switchAudioTrack);\n\n  // Fired when a level is removed after calling `removeLevel()`\n  hls.on(Hls.Events.LEVELS_UPDATED, function (_event, data) {\n    const videoTrack = customMediaEl.videoTracks[customMediaEl.videoTracks.selectedIndex ?? 0];\n    if (!videoTrack) return;\n\n    const levelIds: string[] = data.levels.map((l) => levelIdMap.get(l));\n\n    for (const rendition of customMediaEl.videoRenditions) {\n      if (rendition.id && !levelIds.includes(rendition.id)) {\n        videoTrack.removeRendition(rendition);\n      }\n    }\n  });\n\n  // hls.js doesn't support enabling multiple renditions.\n  //\n  // 1. if all renditions are enabled it's auto selection.\n  // 2. if 1 of the renditions is disabled we assume a selection was made\n  //    and lock it to the first rendition that is enabled.\n  const switchRendition = (event: Event) => {\n    // @ts-ignore\n    const level = event.target.selectedIndex as number;\n    if (level != hls.nextLevel) {\n      hls.nextLevel = level;\n    }\n  };\n\n  customMediaEl.videoRenditions?.addEventListener('change', switchRendition);\n\n  const removeVideoTracks = () => {\n    for (const videoTrack of customMediaEl.videoTracks) {\n      customMediaEl.removeVideoTrack(videoTrack);\n    }\n  };\n\n  const removeAudioTracks = () => {\n    for (const audioTrack of customMediaEl.audioTracks) {\n      customMediaEl.removeAudioTrack(audioTrack);\n    }\n  };\n\n  const removeAllMediaTracks = () => {\n    removeVideoTracks();\n    removeAudioTracks();\n  };\n\n  // NOTE: Since this is only relevant for hls, using destroying event (CJP).\n  hls.once(Hls.Events.DESTROYING, () => {\n    removeAllMediaTracks();\n    customMediaEl.audioTracks?.removeEventListener('change', switchAudioTrack);\n    customMediaEl.videoRenditions?.removeEventListener('change', switchRendition);\n  });\n}\n", "import Hls from './hls';\nimport { CuePoint, Chapter } from './types';\nimport { addEventListenerWithTeardown } from './util';\n\ntype Config = { label: string };\n\n// Shared utils\n\n// Extracts the start time from a cuepoint, considering legacy \"time\" prop\nconst cuePointStart = (cuePoint: CuePoint): number => {\n  if ('time' in cuePoint) {\n    return cuePoint.time;\n  }\n  return cuePoint.startTime;\n};\n\nexport function setupTextTracks(\n  mediaEl: HTMLMediaElement,\n  hls: Pick<Hls, 'on' | 'once' | 'subtitleTracks' | 'subtitleTrack'>\n) {\n  hls.on(Hls.Events.NON_NATIVE_TEXT_TRACKS_FOUND, (_type, { tracks }) => {\n    tracks.forEach((trackObj) => {\n      const baseTrackObj = trackObj.subtitleTrack ?? trackObj.closedCaptions;\n      const idx = hls.subtitleTracks.findIndex(({ lang, name, type }) => {\n        return lang == baseTrackObj?.lang && name === trackObj.label && type.toLowerCase() === trackObj.kind;\n      });\n\n      // NOTE: Undocumented method for determining identifier by hls.js. Relied on for\n      // ensuring CUES_PARSED events can identify and apply cues to the appropriate track (CJP).\n      // See: https://github.com/video-dev/hls.js/blob/master/src/controller/timeline-controller.ts#L640\n      const id = (trackObj._id ?? trackObj.default) ? 'default' : `${trackObj.kind}${idx}`;\n\n      addTextTrack(mediaEl, trackObj.kind as TextTrackKind, trackObj.label, baseTrackObj?.lang, id, trackObj.default);\n    });\n  });\n\n  const changeHandler = () => {\n    if (!hls.subtitleTracks.length) return;\n\n    const showingTrack = Array.from(mediaEl.textTracks).find((textTrack) => {\n      return textTrack.id && textTrack.mode === 'showing' && ['subtitles', 'captions'].includes(textTrack.kind);\n    });\n\n    if (!showingTrack) return;\n\n    const currentHlsTrack = hls.subtitleTracks[hls.subtitleTrack];\n\n    // If hls.subtitleTrack is -1 or its id changed compared to the one that is showing load the new subtitle track.\n    const hlsTrackId = !currentHlsTrack\n      ? undefined\n      : currentHlsTrack.default\n        ? 'default'\n        : `${hls.subtitleTracks[hls.subtitleTrack].type.toLowerCase()}${hls.subtitleTrack}`;\n\n    if (hls.subtitleTrack < 0 || showingTrack?.id !== hlsTrackId) {\n      const idx = hls.subtitleTracks.findIndex(({ lang, name, type, default: defaultTrack }) => {\n        return (\n          (showingTrack.id === 'default' && defaultTrack) ||\n          (lang == showingTrack.language && name === showingTrack.label && type.toLowerCase() === showingTrack.kind)\n        );\n      });\n      // After the subtitleTrack is set here, hls.js will load the playlist and CUES_PARSED events will be fired below.\n      hls.subtitleTrack = idx;\n    }\n\n    if (showingTrack?.id === hlsTrackId) {\n      // Refresh the cues after a texttrack mode change to fix a Chrome bug causing the captions not to render.\n      if (showingTrack.cues) {\n        Array.from(showingTrack.cues).forEach((cue) => {\n          showingTrack.addCue(cue);\n        });\n      }\n    }\n  };\n\n  mediaEl.textTracks.addEventListener('change', changeHandler);\n\n  hls.on(Hls.Events.CUES_PARSED, (_type, { track, cues }) => {\n    const textTrack = mediaEl.textTracks.getTrackById(track);\n    if (!textTrack) return;\n\n    const disabled = textTrack.mode === 'disabled';\n    if (disabled) {\n      textTrack.mode = 'hidden';\n    }\n\n    cues.forEach((cue: VTTCue) => {\n      if (textTrack.cues?.getCueById(cue.id)) return;\n      textTrack.addCue(cue);\n    });\n\n    if (disabled) {\n      textTrack.mode = 'disabled';\n    }\n  });\n\n  // NOTE: Since this is only relevant for hls, using destroying event (CJP).\n  hls.once(Hls.Events.DESTROYING, () => {\n    mediaEl.textTracks.removeEventListener('change', changeHandler);\n    // Use data attribute to identify tracks that should be removed when switching sources/destroying hls.js instance.\n    const trackEls: NodeListOf<HTMLTrackElement> = mediaEl.querySelectorAll('track[data-removeondestroy]');\n    trackEls.forEach((trackEl) => {\n      trackEl.remove();\n    });\n  });\n\n  const forceHiddenTracks = () => {\n    // Keeping this a forEach in case we want to expand the scope of this.\n    Array.from(mediaEl.textTracks).forEach((track) => {\n      if (['subtitles', 'caption'].includes(track.kind)) return;\n      if (!(track.label === 'thumbnails' || track.kind === 'chapters')) return;\n      if (!track.cues?.length) {\n        let selector = 'track';\n        if (track.kind) selector += `[kind=\"${track.kind}\"]`;\n        if (track.label) selector += `[label=\"${track.label}\"]`;\n        const trackEl = mediaEl.querySelector(selector);\n        // Force a reload of the cues if they've been removed\n        const src = trackEl?.getAttribute('src') ?? '';\n        trackEl?.removeAttribute('src');\n        setTimeout(() => {\n          trackEl?.setAttribute('src', src);\n        }, 0);\n      }\n      // Force hidden mode if it's not hidden\n      if (track.mode !== 'hidden') {\n        track.mode = 'hidden';\n      }\n    });\n  };\n\n  // hls.js will forcibly clear all cues from tracks on manifest loads or media attaches.\n  // This ensures that we re-load them after it's done that.\n  hls.once(Hls.Events.MANIFEST_LOADED, forceHiddenTracks);\n  hls.once(Hls.Events.MEDIA_ATTACHED, forceHiddenTracks);\n}\n\nexport function addTextTrack(\n  mediaEl: HTMLMediaElement,\n  kind: TextTrackKind,\n  label: string,\n  lang?: string,\n  id?: string,\n  defaultTrack?: boolean\n): TextTrack {\n  const trackEl = document.createElement('track');\n  trackEl.kind = kind;\n  trackEl.label = label;\n  if (lang) {\n    // This attribute must be present if the element's kind attribute is in the subtitles state.\n    trackEl.srclang = lang;\n  }\n  if (id) {\n    trackEl.id = id;\n  }\n  if (!!defaultTrack) {\n    trackEl.default = true;\n  }\n  trackEl.track.mode = ['subtitles', 'captions'].includes(kind) ? 'disabled' : 'hidden';\n\n  // Add data attribute to identify tracks that should be removed when switching sources/destroying hls.js instance.\n  trackEl.setAttribute('data-removeondestroy', '');\n  mediaEl.append(trackEl);\n\n  return trackEl.track as TextTrack;\n}\n\nexport function removeTextTrack(mediaEl: HTMLMediaElement, track: TextTrack) {\n  const trackElement: HTMLTrackElement | undefined = Array.prototype.find.call(\n    mediaEl.querySelectorAll('track'),\n    (trackEl: HTMLTrackElement) => trackEl.track === track\n  );\n  trackElement?.remove();\n}\n\nexport function getTextTrack(mediaEl: HTMLMediaElement, label: string, kind: TextTrackKind) {\n  return Array.from(mediaEl.querySelectorAll('track')).find((trackEl) => {\n    return trackEl.track.label === label && trackEl.track.kind === kind;\n  })?.track;\n}\n\nexport async function addCuesToTextTrack<T = any>(\n  mediaEl: HTMLMediaElement,\n  cues: CuePoint<T>[] | Chapter[],\n  label: string,\n  kind: TextTrackKind\n) {\n  // If the track has already been created/added, use it.\n  let track = getTextTrack(mediaEl, label, kind);\n  if (!track) {\n    // Otherwise, create a new one\n    track = addTextTrack(mediaEl, kind, label);\n    track.mode = 'hidden';\n    // Wait a tick before providing a newly created track. Otherwise e.g. cues disappear when using track.addCue().\n    await new Promise((resolve) => setTimeout(() => resolve(undefined), 0));\n  }\n\n  if (track.mode !== 'hidden') {\n    track.mode = 'hidden';\n  }\n\n  // Copy cuePoints to ensure sort is not mutative\n  [...cues]\n    // Sort descending to ensure last cuepoints are added as cues first. This is done\n    // so the track's cue's can be used for reference when determining an appropriate\n    // endTime, allowing support of multiple invocations of addCuePoints\n    .sort((cuePointA, cuePointB) => cuePointStart(cuePointB) - cuePointStart(cuePointA))\n    .forEach((cuePoint) => {\n      const value = cuePoint.value;\n      const startTime = cuePointStart(cuePoint);\n\n      if ('endTime' in cuePoint && cuePoint.endTime != undefined) {\n        track?.addCue(\n          new VTTCue(\n            startTime,\n            cuePoint.endTime,\n            kind === 'chapters' ? (value as string) : JSON.stringify(value ?? null)\n          )\n        );\n      } else {\n        // find the cue that starts immediately after the cuePoint's time\n        const cueAfterIndex = Array.prototype.findIndex.call(track?.cues, (cue) => cue.startTime >= startTime);\n        const cueAfter = track?.cues?.[cueAfterIndex];\n        const endTime = cueAfter\n          ? cueAfter.startTime\n          : Number.isFinite(mediaEl.duration)\n            ? mediaEl.duration\n            : Number.MAX_SAFE_INTEGER;\n\n        // Adjust the endTime of the already added previous cue,\n        // if present, so it does not overlap with the newly added cue.\n        const previousCue = track?.cues?.[cueAfterIndex - 1];\n        if (previousCue) {\n          previousCue.endTime = startTime;\n        }\n        track?.addCue(\n          new VTTCue(startTime, endTime, kind === 'chapters' ? (value as string) : JSON.stringify(value ?? null))\n        );\n      }\n    });\n\n  // NOTE: this doesn't naturally fire when we update the list\n  // of cue points (without changing the active cue). We manually\n  // fire this to force the state manager to reflect the new change\n  mediaEl.textTracks.dispatchEvent(\n    new Event('change', {\n      bubbles: true,\n      composed: true,\n    })\n  );\n\n  return track;\n}\n\n// Cuepoints\n\nconst DEFAULT_CUEPOINTS_TRACK_LABEL = 'cuepoints';\nexport const DefaultCuePointsConfig: Config = Object.freeze({ label: DEFAULT_CUEPOINTS_TRACK_LABEL });\n\nexport async function addCuePoints<T>(\n  mediaEl: HTMLMediaElement,\n  cuePoints: CuePoint<T>[],\n  cuePointsConfig: Config = DefaultCuePointsConfig\n) {\n  return addCuesToTextTrack(mediaEl, cuePoints, cuePointsConfig.label, 'metadata');\n}\n\nconst toCuePoint = (cue: VTTCue) => ({\n  time: cue.startTime,\n  value: JSON.parse(cue.text),\n});\n\nexport function getCuePoints(\n  mediaEl: HTMLMediaElement,\n  cuePointsConfig: Config = { label: DEFAULT_CUEPOINTS_TRACK_LABEL }\n) {\n  const track = getTextTrack(mediaEl, cuePointsConfig.label, 'metadata');\n  if (!track?.cues) return [];\n  return Array.from(track.cues, (cue) => toCuePoint(cue as VTTCue));\n}\n\nexport function getActiveCuePoint(\n  mediaEl: HTMLMediaElement,\n  cuePointsConfig: Config = { label: DEFAULT_CUEPOINTS_TRACK_LABEL }\n) {\n  const track = getTextTrack(mediaEl, cuePointsConfig.label, 'metadata');\n  if (!track?.activeCues?.length) return undefined;\n  if (track.activeCues.length === 1) return toCuePoint(track.activeCues[0] as VTTCue);\n  // NOTE: There is a bug in Chromium where there may be \"lingering activeCues\" even\n  // after the playhead is no longer within their [startTime, endTime) bounds. This\n  // accounts for those cases (CJP)\n  const { currentTime } = mediaEl;\n  const actualActiveCue = Array.prototype.find.call(track.activeCues ?? [], ({ startTime, endTime }) => {\n    return startTime <= currentTime && endTime > currentTime;\n  }) as VTTCue | undefined;\n  if (!actualActiveCue) {\n    return toCuePoint(track.activeCues[0] as VTTCue);\n  }\n  return toCuePoint(actualActiveCue);\n}\n\nexport async function setupCuePoints(mediaEl: HTMLMediaElement, cuePointsConfig: Config = DefaultCuePointsConfig) {\n  return new Promise((resolve) => {\n    addEventListenerWithTeardown(mediaEl, 'loadstart', async () => {\n      const track = await addCuePoints(mediaEl, [], cuePointsConfig);\n      addEventListenerWithTeardown(\n        mediaEl,\n        'cuechange',\n        () => {\n          const activeCuePoint = getActiveCuePoint(mediaEl);\n          if (activeCuePoint) {\n            const evt = new CustomEvent('cuepointchange', {\n              composed: true,\n              bubbles: true,\n              detail: activeCuePoint,\n            });\n            mediaEl.dispatchEvent(evt);\n          }\n        },\n        {},\n        track\n      );\n      resolve(track);\n    });\n  });\n}\n\n/**\n * Chapters\n */\n\nconst DEFAULT_CHAPTERS_TRACK_LABEL = 'chapters';\nexport const DefaultChaptersConfig: Config = Object.freeze({ label: DEFAULT_CHAPTERS_TRACK_LABEL });\n\nconst vttCueToChapter = (cue: VTTCue) => ({\n  startTime: cue.startTime,\n  endTime: cue.endTime,\n  value: cue.text,\n});\n\nexport async function addChapters(\n  mediaEl: HTMLMediaElement,\n  chapters: Chapter[],\n  chaptersConfig: Config = DefaultChaptersConfig\n) {\n  return addCuesToTextTrack(mediaEl, chapters, chaptersConfig.label, 'chapters');\n}\n\nexport function getChapters(\n  mediaEl: HTMLMediaElement,\n  chaptersConfig: Config = { label: DEFAULT_CHAPTERS_TRACK_LABEL }\n) {\n  const track = getTextTrack(mediaEl, chaptersConfig.label, 'chapters');\n  if (!track?.cues?.length) return [];\n  return Array.from(track.cues, (cue) => vttCueToChapter(cue as VTTCue));\n}\n\nexport function getActiveChapter(\n  mediaEl: HTMLMediaElement,\n  chaptersConfig: Config = { label: DEFAULT_CHAPTERS_TRACK_LABEL }\n) {\n  const track = getTextTrack(mediaEl, chaptersConfig.label, 'chapters');\n  if (!track?.activeCues?.length) return undefined;\n  if (track.activeCues.length === 1) return vttCueToChapter(track.activeCues[0] as VTTCue);\n  // NOTE: There is a bug in Chromium where there may be \"lingering activeCues\" even\n  // after the playhead is no longer within their [startTime, endTime) bounds. This\n  // accounts for those cases (CJP)\n  const { currentTime } = mediaEl;\n  const actualActiveCue = Array.prototype.find.call(track.activeCues ?? [], ({ startTime, endTime }) => {\n    return startTime <= currentTime && endTime > currentTime;\n  }) as VTTCue | undefined;\n  if (!actualActiveCue) {\n    return vttCueToChapter(track.activeCues[0] as VTTCue);\n  }\n  return vttCueToChapter(actualActiveCue);\n}\n\nexport async function setupChapters(mediaEl: HTMLMediaElement, chaptersConfig: Config = DefaultChaptersConfig) {\n  return new Promise((resolve) => {\n    addEventListenerWithTeardown(mediaEl, 'loadstart', async () => {\n      const track = await addChapters(mediaEl, [], chaptersConfig);\n\n      addEventListenerWithTeardown(\n        mediaEl,\n        'cuechange',\n        () => {\n          const activeCuePoint = getActiveChapter(mediaEl);\n          if (activeCuePoint) {\n            const evt = new CustomEvent('chapterchange', {\n              composed: true,\n              bubbles: true,\n              detail: activeCuePoint,\n            });\n            mediaEl.dispatchEvent(evt);\n          }\n        },\n        {},\n        track\n      );\n\n      resolve(track);\n    });\n  });\n}\n", "import { PlaybackEngine } from './types';\n\ntype MediaWithPDT = HTMLMediaElement & { getStartDate?: () => Date };\n\nexport function getStartDate(mediaEl: MediaWithPDT, hls: PlaybackEngine | undefined) {\n  if (hls) {\n    const playingDate = hls.playingDate;\n\n    if (playingDate != null) {\n      // If the video is very long and the currentTime will transition day boundaries,\n      // this may end up not being accurate\n      return new Date(playingDate.getTime() - mediaEl.currentTime * 1000);\n    }\n  }\n\n  if (typeof mediaEl.getStartDate === 'function') {\n    return mediaEl.getStartDate();\n  }\n\n  return new Date(NaN);\n}\n\nexport function getCurrentPdt(mediaEl: MediaWithPDT, hls: PlaybackEngine | undefined) {\n  if (hls && hls.playingDate) {\n    return hls.playingDate;\n  }\n\n  if (typeof mediaEl.getStartDate === 'function') {\n    const startDate = mediaEl.getStartDate();\n\n    // If the video is very long and the currentTime will transition day boundaries,\n    // this may end up not being accurate\n    return new Date(startDate.getTime() + mediaEl.currentTime * 1000);\n  }\n\n  return new Date(NaN);\n}\n", "import type { LoaderResponse } from 'hls.js';\nimport {\n  i18n,\n  isJWTAudMismatch,\n  isJWTAudMissing,\n  isJWTExpired,\n  isJWTSubMismatch,\n  parseJwt,\n  toPlaybackIdParts,\n} from './util';\nimport { isKeyOf, MuxMediaPropsInternal, StreamTypes } from './types';\nimport type { MuxErrorCategoryValue } from './errors';\nimport { errorCategoryToTokenNameOrPrefix, MediaError, MuxErrorCategory, MuxErrorCode } from './errors';\n\nexport const MuxJWTAud = {\n  VIDEO: 'v',\n  // NOTE: These are not \"built in\" for mux-video/mux-audio (only mux-player) (CJP)\n  THUMBNAIL: 't',\n  STORYBOARD: 's',\n  // GIF: 'g', // currently unused\n  DRM: 'd',\n} as const;\n\nexport const categoryToAud = (category: MuxErrorCategoryValue) => {\n  if (category === MuxErrorCategory.VIDEO) return MuxJWTAud.VIDEO;\n  if (category === MuxErrorCategory.DRM) return MuxJWTAud.DRM;\n};\n\nexport const categoryToToken = (\n  category: MuxErrorCategoryValue,\n  muxMediaEl: Partial<Pick<MuxMediaPropsInternal, 'drmToken' | 'playbackToken' | 'tokens'>>\n) => {\n  const nameOrPrefix = errorCategoryToTokenNameOrPrefix(category);\n  const tokenName = `${nameOrPrefix}Token` as const;\n  if (muxMediaEl.tokens?.[nameOrPrefix]) return muxMediaEl.tokens?.[nameOrPrefix];\n  return isKeyOf(tokenName, muxMediaEl) ? muxMediaEl[tokenName] : undefined;\n};\n\nexport const getErrorFromResponse = (\n  resp: Pick<Response, 'status' | 'url'> | Pick<LoaderResponse, 'code' | 'url'>,\n  category: MuxErrorCategoryValue,\n  muxMediaEl: Partial<\n    Pick<MuxMediaPropsInternal, 'playbackId' | 'drmToken' | 'playbackToken' | 'tokens' | 'streamType'>\n  >,\n  fatal?: boolean,\n  translate = false,\n  offline = !globalThis.navigator?.onLine // NOTE: Passing this in for testing purposes\n) => {\n  if (offline) {\n    const message = i18n(`Your device appears to be offline`, translate);\n    const context = undefined;\n    const mediaErrorCode = MediaError.MEDIA_ERR_NETWORK;\n    // Being offline is not immediately a fatal error for playback.\n    const mediaError = new MediaError(message, mediaErrorCode, false, context);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_OFFLINE;\n    mediaError.data = resp;\n    return mediaError;\n  }\n  const status = 'status' in resp ? resp.status : resp.code;\n  const requestTime = Date.now();\n  const mediaErrorCode = MediaError.MEDIA_ERR_NETWORK;\n  // Not an error. WHAT ARE YOU EVEN DOING HERE?!?\n  if (status === 200) return undefined;\n  const tokenNamePrefix = errorCategoryToTokenNameOrPrefix(category);\n  const token = categoryToToken(category, muxMediaEl);\n  const expectedAud = categoryToAud(category);\n  const [playbackId] = toPlaybackIdParts(muxMediaEl.playbackId ?? '');\n  // NOTE: *should* have playback id when reaching here\n  // if (!status) return MuxErrorCode.NETWORK_NO_STATUS;\n  if (!status || !playbackId) return undefined;\n\n  const jwtObj = parseJwt(token);\n  // Make sure we didn't get here because of a malformed JWT and/or claim\n  if (!!token && !jwtObj) {\n    // 403 for DRM\n    const message = i18n(`The {tokenNamePrefix}-token provided is invalid or malformed.`, translate).format({\n      tokenNamePrefix,\n    });\n    const context = i18n(`Compact JWT string: {token}`, translate).format({\n      token,\n    });\n    const mediaError = new MediaError(message, mediaErrorCode, true, context);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_MALFORMED;\n    mediaError.data = resp;\n    return mediaError;\n  }\n\n  if (status >= 500) {\n    /**\n     * @TODO We plausibly should have some basic retry logic for all other 500 status\n     * cases (CJP)\n     **/\n    const mediaError = new MediaError('', mediaErrorCode, fatal ?? true);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_UNKNOWN_ERROR;\n    /** @TODO Add error msg + context crud here (NOT YET DEFINED) (CJP) */\n    return mediaError;\n  }\n\n  if (status === 403) {\n    if (jwtObj) {\n      if (isJWTExpired(jwtObj, requestTime)) {\n        const dateOptions: any = {\n          timeStyle: 'medium',\n          dateStyle: 'medium',\n        };\n        // E.g. for DRM: \"The video\u2019s secured drm-token has expired.\"\n        // E.g. for Video: \"The video\u2019s secured playback-token has expired.\"\n        const message = i18n(`The video\u2019s secured {tokenNamePrefix}-token has expired.`, translate).format({\n          tokenNamePrefix,\n        });\n        const context = i18n(`Expired at: {expiredDate}. Current time: {currentDate}.`, translate).format({\n          expiredDate: new Intl.DateTimeFormat('en', dateOptions).format(jwtObj.exp ?? 0 * 1000),\n          currentDate: new Intl.DateTimeFormat('en', dateOptions).format(requestTime),\n        });\n        const mediaError = new MediaError(message, mediaErrorCode, true, context);\n        mediaError.errorCategory = category;\n        mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_EXPIRED;\n        mediaError.data = resp;\n        return mediaError;\n      }\n      if (isJWTSubMismatch(jwtObj, playbackId)) {\n        const message = i18n(\n          `The video\u2019s playback ID does not match the one encoded in the {tokenNamePrefix}-token.`,\n          translate\n        ).format({\n          tokenNamePrefix,\n        });\n        const context = i18n(\n          `Specified playback ID: {playbackId} and the playback ID encoded in the {tokenNamePrefix}-token: {tokenPlaybackId}`,\n          translate\n        ).format({\n          tokenNamePrefix,\n          playbackId,\n          tokenPlaybackId: jwtObj.sub,\n        });\n        const mediaError = new MediaError(message, mediaErrorCode, true, context);\n        mediaError.errorCategory = category;\n        mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_SUB_MISMATCH;\n        mediaError.data = resp;\n        return mediaError;\n      }\n      if (isJWTAudMissing(jwtObj, expectedAud)) {\n        const message = i18n(`The {tokenNamePrefix}-token is formatted with incorrect information.`, translate).format({\n          tokenNamePrefix,\n        });\n        const context = i18n(\n          `The {tokenNamePrefix}-token has no aud value. aud value should be {expectedAud}.`,\n          translate\n        ).format({\n          tokenNamePrefix,\n          expectedAud,\n        });\n        const mediaError = new MediaError(message, mediaErrorCode, true, context);\n        mediaError.errorCategory = category;\n        mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_AUD_MISSING;\n        mediaError.data = resp;\n        return mediaError;\n      }\n      if (isJWTAudMismatch(jwtObj, expectedAud)) {\n        const message = i18n(`The {tokenNamePrefix}-token is formatted with incorrect information.`, translate).format({\n          tokenNamePrefix,\n        });\n        const context = i18n(\n          `The {tokenNamePrefix}-token has an incorrect aud value: {aud}. aud value should be {expectedAud}.`,\n          translate\n        ).format({\n          tokenNamePrefix,\n          expectedAud,\n          aud: jwtObj.aud,\n        });\n        const mediaError = new MediaError(message, mediaErrorCode, true, context);\n        mediaError.errorCategory = category;\n        mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_AUD_MISMATCH;\n        mediaError.data = resp;\n        return mediaError;\n      }\n\n      // NOTE: This *should* not happen for DRM, since the drm token\n      // is currently used to detect whether or not DRM should\n      // be setup at all. Including for exhaustiveness. (CJP)\n    } else {\n      const message = i18n(\n        `Authorization error trying to access this {category} URL. If this is a signed URL, you might need to provide a {tokenNamePrefix}-token.`,\n        translate\n      ).format({\n        tokenNamePrefix,\n        category,\n      });\n      const context = i18n(`Specified playback ID: {playbackId}`, translate).format({ playbackId });\n      const mediaError = new MediaError(message, mediaErrorCode, fatal ?? true, context);\n      mediaError.errorCategory = category;\n      mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_MISSING;\n      mediaError.data = resp;\n      return mediaError;\n    }\n  }\n\n  if (status === 412) {\n    const message = i18n(\n      `This playback-id may belong to a live stream that is not currently active or an asset that is not ready.`,\n      translate\n    );\n    const context = i18n(`Specified playback ID: {playbackId}`, translate).format({ playbackId });\n    const mediaError = new MediaError(message, mediaErrorCode, fatal ?? true, context);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_NOT_READY;\n    mediaError.streamType =\n      muxMediaEl.streamType === StreamTypes.LIVE\n        ? 'live'\n        : muxMediaEl.streamType === StreamTypes.ON_DEMAND\n          ? 'on-demand'\n          : 'unknown';\n    mediaError.data = resp;\n    return mediaError;\n  }\n\n  /**\n   * NOTE: When using a \"structurally valid but non-existent\" playback id for a DRM (license or app certificate) request, this will result in a 403 status.\n   * However, since we will only currently make a DRM request after successfully loading the media, this case should not need\n   * to be accounted for. If we ever eagerly fetch FPS app certs prior to or in parallel to media requests, we would potentially\n   * want to account for that case (either by normalizing statuses, in our messaging for generic 403 above, or through more complex\n   * solutions like waiting for the media response). (CJP)\n   */\n  if (status === 404) {\n    // NOTE: This *should* not happen for DRM (only playback/media requests), since the URL should never be invalid if code\n    // is correct. Aka if we end up here it's almost definitely a bug.\n    const message = i18n(\n      `This URL or playback-id does not exist. You may have used an Asset ID or an ID from a different resource.`,\n      translate\n    );\n    const context = i18n(`Specified playback ID: {playbackId}`, translate).format({ playbackId });\n    const mediaError = new MediaError(message, mediaErrorCode, fatal ?? true, context);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_NOT_FOUND;\n    mediaError.data = resp;\n    return mediaError;\n  }\n\n  /**\n   * NOTE: Omitting a token for a DRM (license or app certificate) request results in a 400 status, unlike playback/media requests,\n   * which are a 403 status (See above).\n   * However, since we will only currently setup Mux Player for DRM if a drm token is provided, this case should not need\n   * to be accounted for. If we ever change this, we would potentially\n   * want to account for that case (either by normalizing statuses, in our messaging for generic 400 above, or through more complex\n   * solutions like checking the category before deciding on error details here). (CJP)\n   */\n  if (status === 400) {\n    const message = i18n(`The URL or playback-id was invalid. You may have used an invalid value as a playback-id.`);\n    const context = i18n(`Specified playback ID: {playbackId}`, translate).format({ playbackId });\n    const mediaError = new MediaError(message, mediaErrorCode, fatal ?? true, context);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_INVALID_URL;\n    mediaError.data = resp;\n    return mediaError;\n  }\n\n  const mediaError = new MediaError('', mediaErrorCode, fatal ?? true);\n  mediaError.errorCategory = category;\n  mediaError.muxCode = MuxErrorCode.NETWORK_UNKNOWN_ERROR;\n  mediaError.data = resp;\n  return mediaError;\n};\n", "import Hls from './hls';\nimport type { HlsInterface } from './hls';\nimport type { Level } from 'hls.js';\nimport type { MaxAutoResolutionValue } from './types';\n\n// The hls.js commonJS module doesn't export CapLevelController, so get it from the default config.\nconst CapLevelController = Hls.DefaultConfig.capLevelController;\n\n/**\n * Resolution pricing tiers based on total pixels (width * height)\n * Values align with Mux Video pricing tiers: https://www.mux.com/docs/pricing/video#resolution-based-pricing\n */\nconst RESOLUTION_PIXEL_LIMITS: Record<string, number> = {\n  '720p': 921600, // Up to 921,600 pixels (1280x720)\n  '1080p': 2073600, // Up to 2,073,600 pixels (1920x1080)\n  '1440p': 4194304, // Up to 4,194,304 pixels (2560x1440)\n  '2160p': 8294400, // Up to 8,294,400 pixels (3840x2160)\n};\n\n/**\n * Convert resolution string to maximum total pixels\n * Only accepts predefined tiers from the list\n */\nfunction resolutionToMaxPixels(resolution: string): number | undefined {\n  const normalized = resolution.toLowerCase().trim();\n\n  return RESOLUTION_PIXEL_LIMITS[normalized];\n}\n\n/**\n * A custom HLS.js CapLevelController that behaves like the default one, except\n * it enforces a \"minimum maximum\" to avoid forced capping to lower quality at small sizes\n */\nclass MinCapLevelController extends CapLevelController {\n  // Never cap below this level.\n  static minMaxResolution = 720;\n  private static maxAutoResolution = new WeakMap<HlsInterface, MaxAutoResolutionValue>();\n\n  constructor(hls: HlsInterface) {\n    super(hls);\n  }\n\n  static setMaxAutoResolution(hls: HlsInterface, maxAutoResolution: MaxAutoResolutionValue | undefined) {\n    if (maxAutoResolution) {\n      MinCapLevelController.maxAutoResolution.set(hls, maxAutoResolution);\n    } else {\n      MinCapLevelController.maxAutoResolution.delete(hls);\n    }\n  }\n\n  private getMaxAutoResolution(): MaxAutoResolutionValue | undefined {\n    // NOTE: hls is a TS-private member in CapLevelController. Should be TS-protected\n    // @ts-ignore\n    const hlsInstance = this.hls;\n    return MinCapLevelController.maxAutoResolution.get(hlsInstance) ?? undefined;\n  }\n\n  get levels() {\n    // NOTE: hls is a TS-private member in CapLevelController. Should be TS-protected (CJP)\n    // @ts-ignore\n    return (this.hls.levels ?? []) as Level[];\n  }\n\n  getValidLevels(capLevelIndex: number) {\n    return this.levels.filter(\n      // NOTE: isLevelAllowed is a TS-private member in CapLevelController. Should be TS-protected (CJP)\n      // @ts-ignore\n      (level, index) => this.isLevelAllowed(level) && index <= capLevelIndex\n    );\n  }\n\n  /**\n   * Get the maximum level capped to maxAutoResolution\n   *\n   * Selection logic (in order of priority):\n   * 1. If there's an exact match for maxAutoResolution, use it\n   * 2. If no exact match exists, always select the highest quality that doesn't exceed the cap\n   *    (to prevent extra costs by going over the resolution limit)\n   */\n  private getMaxLevelCapped(capLevelIndex: number): number {\n    const validLevels = this.getValidLevels(capLevelIndex);\n    const maxAutoResolution = this.getMaxAutoResolution();\n\n    if (!maxAutoResolution) {\n      return super.getMaxLevel(capLevelIndex);\n    }\n\n    // Convert resolution string to maximum total pixels\n    const maxPixels = resolutionToMaxPixels(maxAutoResolution);\n    if (!maxPixels) {\n      // Invalid resolution string, fallback to default behavior\n      return super.getMaxLevel(capLevelIndex);\n    }\n\n    // Compare by total pixels (width * height) to match Mux Video pricing tiers\n    // Find levels that don't exceed the cap (total pixels <= maxPixels)\n    const levelsWithinCap = validLevels.filter((level) => {\n      const totalPixels = level.width * level.height;\n      return totalPixels <= maxPixels;\n    });\n\n    // Check if there's an exact match first (total pixels === maxPixels)\n    const exactMatch = levelsWithinCap.findIndex((level) => {\n      const totalPixels = level.width * level.height;\n      return totalPixels === maxPixels;\n    });\n\n    if (exactMatch !== -1) {\n      const exactLevel = levelsWithinCap[exactMatch];\n      return validLevels.findIndex((level) => level === exactLevel);\n    }\n\n    // No exact match - always select the highest quality that doesn't exceed the cap\n    if (levelsWithinCap.length === 0) {\n      // No levels within cap, return the lowest level\n      return 0;\n    }\n    // Return the highest quality within cap (last item, since levels are ordered from lowest to highest)\n    const highestQualityWithinCap = levelsWithinCap[levelsWithinCap.length - 1];\n    return validLevels.findIndex((level) => level === highestQualityWithinCap);\n  }\n\n  getMaxLevel(capLevelIndex: number) {\n    if (this.getMaxAutoResolution() !== undefined) {\n      return this.getMaxLevelCapped(capLevelIndex);\n    }\n\n    const baseMaxLevel = super.getMaxLevel(capLevelIndex);\n    const validLevels = this.getValidLevels(capLevelIndex);\n\n    // Default maxLevel selection ended up out of bounds to indicate e.g. no capping/no levels available (yet), so use it\n    if (!validLevels[baseMaxLevel]) return baseMaxLevel;\n\n    const baseMaxLevelResolution = Math.min(validLevels[baseMaxLevel].width, validLevels[baseMaxLevel].height);\n    const preferredMinMaxResolution = MinCapLevelController.minMaxResolution;\n\n    // Default maxLevel selection already meets our conditions, so use it\n    if (baseMaxLevelResolution >= preferredMinMaxResolution) return baseMaxLevel;\n\n    // Default maxLevel selection is below the preferred \"min max\", so find the lowest level\n    // that is >= the preference. We can simply repurpose CapLevelController:getMaxLevelByMediaSize()\n    // for this, \"lying\" about the element's size.\n    // NOTE: Since CapLevelController:getMaxLevelByMediaSize() uses \"max square size\" under the hood\n    // already, we don't need to duplicate that logic here.\n    const maxLevel = CapLevelController.getMaxLevelByMediaSize(\n      validLevels,\n      preferredMinMaxResolution * (16 / 9),\n      preferredMinMaxResolution\n    );\n\n    return maxLevel;\n  }\n}\n\nexport default MinCapLevelController;\n", "/// <reference types=\"./webkit-fairplay.d.ts\" />\n\nimport { NativeFairplayConfig } from './eme-fairplay';\nimport { MediaError, MuxErrorCategory, MuxErrorCode } from './errors';\nimport { i18n } from './util';\n\nconst LEGACY_KEY_SYSTEM = 'com.apple.fps.1_0';\nconst MIME_TYPE = 'application/vnd.apple.mpegurl';\n\n/**\n * Legacy implementation of FairPlay setup.\n * The purpose of this flow is to address an OS specific issue when playing DRM\n * protected content over AirPlay on newer OS versions. Tries to replicate the setup\n * we do for EME DRM but using legacy WebKit functions.\n *\n * This flow can be removed once that issue is no longer present.\n */\nexport const setupWebkitNativeFairplayDRM = ({\n  mediaEl,\n  getAppCertificate,\n  getLicenseKey,\n  saveAndDispatchError,\n  drmTypeCb,\n}: NativeFairplayConfig) => {\n  // Support for this may be dropped in future WebKit versions so we add this guard.\n  if (!window.WebKitMediaKeys || !('onwebkitneedkey' in mediaEl)) {\n    console.error('No WebKitMediaKeys. FairPlay may not be supported');\n\n    const message = i18n(\n      'Cannot play DRM-protected content with current security configuration on this browser. Try playing in another browser.'\n    );\n    const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n    mediaError.errorCategory = MuxErrorCategory.DRM;\n    mediaError.muxCode = MuxErrorCode.ENCRYPTED_CDM_ERROR;\n\n    saveAndDispatchError(mediaEl, mediaError);\n    // empty teardown\n    return () => {};\n  }\n\n  const wkMediaEl = mediaEl as unknown as WebkitHTMLMediaElement;\n\n  // Don't await as to not block setup to fetch certificate\n  const certificatePromise = getAppCertificate();\n  // Hold a reference to teardown session on this function's teardown\n  let teardownSession: (() => void) | null = null;\n\n  /**\n   * Listener for \"webkitneedkey\" event.\n   * Will be called when we receive EXT-X-KEY tags and will setup media keys and session.\n   */\n  const onWebkitNeedKey = (ev: WebkitNeedKeyEvent) => {\n    // note: Promises only resolve once, so we wrap it in an anonymous funciton to use as an event listener\n    const handle = async () => {\n      try {\n        // Setup 1 - set up the keys based on the data type (currently only \"skd\" for Native Safari FPS DRM)\n        if (!wkMediaEl.webkitKeys) {\n          setupWebkitKey();\n        }\n\n        const certificate = await certificatePromise;\n        // Early bail if the init data is missing (corresponds to EXT-X-KEY values for Native Safari FPS DRM)\n        // NOTE: This could happen before Step 1, but also shouldn't happen.\n        if (ev.initData === null || certificate == null) return;\n\n        const initData = getInitData(ev.initData, certificate);\n        // Setup 2 - set up the key session based on the data type and the data (corresponds to EXT-X-KEY values for Native Safari FPS DRM)\n        setupWebkitKeySession(initData);\n      } catch (e) {\n        console.error('Could not start encrypted playback due to exception', e);\n        saveAndDispatchError(wkMediaEl, e as MediaError);\n      }\n    };\n\n    handle();\n  };\n\n  /** Setup 1\n   *\n   * If successful will:\n   *  - create a Webkit Media Keys object,\n   *  - signal what DRM type was selected.\n   *  - set the Webkit Media Keys to mediaEl.\n   *\n   * If it fails will throw an error in order to abort setup.\n   */\n  const setupWebkitKey = () => {\n    try {\n      // (Step 1.b in EME)\n      const mediaKeys = new WebKitMediaKeys(LEGACY_KEY_SYSTEM);\n      // (Step 1.d in EME)\n      wkMediaEl.webkitSetMediaKeys(mediaKeys);\n      // This is just a simple callback to signal what DRM type was selected\n      drmTypeCb();\n    } catch {\n      const message =\n        'Cannot play DRM-protected content with current security configuration on this browser. Try playing in another browser.';\n      const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_UNSUPPORTED_KEY_SYSTEM;\n\n      throw mediaError;\n    }\n  };\n\n  /** Setup 2\n   * If successful will:\n   *  - Create a new media key session with it's respective 'webkitkeyerror' and 'webkitkeymessage' events.\n   *  - Generate an SPC request\n   *  - Use that SPC to fetch a CKC\n   *  - Update the session with the obtained CKC.\n   *  - Add a teardown listener to cleanup the session.\n   *\n   * If it fails:\n   *  - Will dispatch an error and session should be torn down\n   */\n  const setupWebkitKeySession = (initData: BufferSource) => {\n    // Step 2.a - Create the session now that we have ready media keys on the Media Element.\n    const session = wkMediaEl.webkitKeys.createSession(MIME_TYPE, initData);\n\n    /** Step 2.b\n     * At some point a WebKit Key Message event is fired with a SPC.\n     * We use that SPC to fetch the FPS license key from the server.\n     *\n     * On EME this would be Step 2.c, but session.generateRequest is not done in WebKit\n     */\n    const onWebkitKeyMessage = async (event: WebkiKeyMessageEvent) => {\n      try {\n        const spc = event.message;\n        const ckc = await getLicenseKey(spc);\n        session.update(ckc);\n      } catch (errOrResp) {\n        console.error('Error on FairPlay session message', errOrResp);\n        saveAndDispatchError(mediaEl, errOrResp as MediaError);\n      }\n    };\n\n    const onWebkitKeyError = (event: WebkitKeyErrorEvent) => {\n      const error = event.target.error;\n      if (!error) return;\n      console.error(`Internal Webkit Key Session Error - sysCode: ${error.systemCode} code: ${error.code}`);\n\n      const message = i18n(\n        'The DRM Content Decryption Module system had an internal failure. Try reloading the page, upading your browser, or playing in another browser.'\n      );\n      const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_CDM_ERROR;\n\n      saveAndDispatchError(mediaEl, mediaError);\n    };\n\n    // TODO: Improvement: It's possible that many JS Session objects are created\n    // for the same internal session resource (this is not documented, but could happen if\n    // many webkitneedkey events are fired).\n    // This may lead to unnecessary event listeners being created.\n    // If this becomes an issue, we should implement better cleanup.\n    // For example separating event cleanup from session.close\n    const newTeardown = () => {\n      // Remove all event listeners first to prevent events firing during cleanup\n      // @ts-ignore\n      session.removeEventListener('webkitkeymessage', onWebkitKeyMessage);\n      // @ts-ignore\n      session.removeEventListener('webkitkeyerror', onWebkitKeyError);\n      mediaEl.removeEventListener('teardown', newTeardown);\n      if ('webkitCurrentPlaybackTargetIsWireless' in mediaEl) {\n        mediaEl.removeEventListener('webkitcurrentplaybacktargetiswirelesschanged', newTeardown);\n      }\n\n      teardownSession = null;\n\n      try {\n        session.close();\n      } catch {}\n    };\n\n    if ('webkitCurrentPlaybackTargetIsWireless' in mediaEl) {\n      mediaEl.addEventListener('webkitcurrentplaybacktargetiswirelesschanged', newTeardown, { once: true });\n    }\n\n    // @ts-ignore\n    session.addEventListener('webkitkeymessage', onWebkitKeyMessage);\n    // @ts-ignore\n    session.addEventListener('webkitkeyerror', onWebkitKeyError);\n    mediaEl.addEventListener('teardown', newTeardown);\n\n    teardownSession = newTeardown;\n  };\n\n  const teardownWebkit = () => {\n    // Remove event listeners first to prevent new key requests during cleanup\n    // @ts-ignore\n    mediaEl.removeEventListener('webkitneedkey', onWebkitNeedKey);\n    mediaEl.removeEventListener('teardown', teardownWebkit);\n\n    teardownSession?.();\n\n    try {\n      wkMediaEl.webkitSetMediaKeys(null);\n    } catch {}\n  };\n\n  // @ts-ignore\n  mediaEl.addEventListener('webkitneedkey', onWebkitNeedKey);\n  mediaEl.addEventListener('teardown', teardownWebkit, { once: true });\n\n  return teardownWebkit;\n};\n\n/// Utility functions\n\n/**\n * Expects initData buffer to come in the following format:\n * [4 bytes length][init data words] where the words consist of 16 bit LE words, and length is number of bytes (i.e. 2 * number of words)\n *\n * @param initDataBuffer as obtained from the native event.\n * @param getAppCertificate a function that returns the needed certificate in .dar format as an ArrayBuffer of bytes.\n * @returns Uint8Array of initData in the format:\n * [4 bytes init data length][init data bytes]\n * [4 bytes content Id length][content id bytes]\n * [4 bytes certificate length][certificate bytes]\n */\nconst getInitData = (initDataBuffer: ArrayBuffer, certificateBuffer: ArrayBuffer) => {\n  const contentIdBuffer = stringToUtf16LE(getContentId(initDataBuffer));\n\n  const initData: Uint8Array = new Uint8Array(initDataBuffer);\n  const contentId: Uint8Array = new Uint8Array(contentIdBuffer);\n  const certificate: Uint8Array = new Uint8Array(certificateBuffer);\n\n  const newLength = initData.byteLength + 4 + certificate.byteLength + 4 + contentId.byteLength;\n  const rebuiltInitData = new Uint8Array(newLength);\n  let offset = 0;\n  const append = (array: Uint8Array) => {\n    rebuiltInitData.set(array, offset);\n    offset += array.byteLength;\n  };\n  const appendWithLength = (array: Uint8Array) => {\n    const view = new DataView(rebuiltInitData.buffer);\n    const value = array.byteLength;\n    view.setUint32(offset, value, /* littleEndian= */ true);\n    offset += 4;\n    append(array);\n  };\n\n  append(initData);\n  appendWithLength(contentId);\n  appendWithLength(certificate);\n\n  return rebuiltInitData;\n};\n\nconst getContentId = (initData: ArrayBuffer) => {\n  const sdkUrl = new TextDecoder('utf-16le').decode(initData);\n  return sdkUrl.replace('skd://', '').slice(1); // First char is length\n};\n\nfunction stringToUtf16LE(str: string) {\n  const buffer = new ArrayBuffer(str.length * 2);\n  const view = new DataView(buffer);\n\n  for (let i = 0; i < str.length; i++) {\n    view.setUint16(i * 2, str.charCodeAt(i), true); // little-endian\n  }\n\n  return buffer;\n}\n", "import { MediaError, MuxErrorCategory, MuxErrorCode } from './errors';\nimport { i18n } from './util';\n\nexport interface NativeFairplayConfig {\n  mediaEl: HTMLMediaElement;\n  getAppCertificate: () => Promise<ArrayBuffer>;\n  getLicenseKey: (spc: ArrayBuffer) => Promise<BufferSource>;\n  saveAndDispatchError: (mediaEl: HTMLMediaElement, error: MediaError) => void;\n  drmTypeCb: () => void;\n  fallbackToWebkitFairplay?: () => Promise<void>;\n}\n\nexport const setupEmeNativeFairplayDRM = ({\n  mediaEl,\n  getAppCertificate,\n  getLicenseKey,\n  saveAndDispatchError,\n  drmTypeCb,\n  fallbackToWebkitFairplay,\n}: NativeFairplayConfig) => {\n  let teardownSession: null | (() => Promise<void>) = null;\n  /**\n   * Listener for \"encrypted\" event.\n   * Will be called when we receive EXT-X-KEY tags and will setup media keys and session.\n   */\n  const onFpEncrypted = async (event: MediaEncryptedEvent) => {\n    try {\n      const initDataType = event.initDataType;\n      // Early bail if data type is not supported (currently only \"skd\" for Native Safari DRM)\n      if (initDataType !== 'skd') {\n        console.error(`Received unexpected initialization data type \"${initDataType}\"`);\n        return;\n      }\n\n      // Setup 1 - set up the keys based on the data type (currently only \"skd\" for Native Safari FPS DRM)\n      if (!mediaEl.mediaKeys) {\n        await setupMediaKeys(initDataType);\n      }\n\n      const initData = event.initData;\n      // Early bail if the init data is missing (corresponds to EXT-X-KEY values for Native Safari FPS DRM)\n      // NOTE: This could happen before Step 1, but also shouldn't happen.\n      if (initData == null) {\n        console.error(`Could not start encrypted playback due to missing initData in ${event.type} event`);\n        return;\n      }\n\n      // Setup 2 - set up the key session based on the data type and the data (corresponds to EXT-X-KEY values for Native Safari FPS DRM)\n      await setupMediaKeySession(initDataType, initData);\n      // @ts-ignore\n    } catch (error: Error | MediaError) {\n      saveAndDispatchError(mediaEl, error);\n      return;\n    }\n  };\n\n  /** Setup 1\n   *\n   * If successful will:\n   *  - request media key system access,\n   *  - create a media keys object,\n   *  - signal what DRM type was selected,\n   *  - request a FPS certificate,\n   *  - set the certificate to the media keys,\n   *  - set the media keys to mediaEl.\n   *\n   * If any step fails will dispatch an error and mediaEl.mediaKeys will not be set.\n   */\n  const setupMediaKeys = async (initDataType: string) => {\n    // Step 1.a - Get access to the Key System\n    const access = await navigator\n      .requestMediaKeySystemAccess('com.apple.fps', [\n        {\n          initDataTypes: [initDataType],\n          videoCapabilities: [{ contentType: 'application/vnd.apple.mpegurl', robustness: '' }],\n          distinctiveIdentifier: 'not-allowed',\n          persistentState: 'not-allowed',\n          sessionTypes: ['temporary'],\n        },\n      ])\n      .then((value) => {\n        // This is just a simple callback to signal what DRM type was selected\n        drmTypeCb();\n        return value;\n      })\n      .catch(() => {\n        // This is just error management\n        const message = i18n(\n          'Cannot play DRM-protected content with current security configuration on this browser. Try playing in another browser.'\n        );\n        // Should we flag this as a business exception?\n        const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n        mediaError.errorCategory = MuxErrorCategory.DRM;\n        mediaError.muxCode = MuxErrorCode.ENCRYPTED_UNSUPPORTED_KEY_SYSTEM;\n        saveAndDispatchError(mediaEl, mediaError);\n      });\n\n    if (!access) return;\n\n    // Step 1.b - Create the keys now that access to the key system is available\n    const keys = await access.createMediaKeys();\n\n    try {\n      // Step 1.c.i - Fetch the FPS App Certificate from the server to use with the keys\n      // NOTE: We could pre-emptively do this as an optimization, but\n      // this simplifies things and has been sufficient thus far (CJP).\n      const fairPlayAppCert = await getAppCertificate();\n      // Step 1.c.ii - Apply the fetched FPS App Certificate to the keys\n      await keys.setServerCertificate(fairPlayAppCert).catch(() => {\n        // This is just error management\n        const message = i18n(\n          'Your server certificate failed when attempting to set it. This may be an issue with a no longer valid certificate.'\n        );\n        const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n        mediaError.errorCategory = MuxErrorCategory.DRM;\n        mediaError.muxCode = MuxErrorCode.ENCRYPTED_UPDATE_SERVER_CERT_FAILED;\n        return Promise.reject(mediaError);\n      });\n      // @ts-ignore\n    } catch (error: Error | MediaError) {\n      // This is just catch all error management\n      saveAndDispatchError(mediaEl, error);\n      return;\n    }\n\n    // Step 1.d - Now that the keys are ready, set them on the Media Element\n    // NOTE: After this, we will move on to Step 2 - set up the key session\n    await mediaEl.setMediaKeys(keys);\n  };\n\n  /** Setup 2\n   * If successful will:\n   *  - Create a new media key session with it's respective 'keystatuseschange' and 'message' events.\n   *  - Generate an SPC request\n   *  - Use that SPC to fetch a CKC\n   *  - Update the session with the obtained CKC.\n   *  - Add a teardown listener to cleanup the session.\n   *\n   * If it fails:\n   *  - Will dispatch an error and session should be torn down\n   *  - If the session.generateRequest call fails, will fallback to WebKit FairPlay implementation\n   */\n  const setupMediaKeySession = async (initDataType: string, initData: ArrayBuffer) => {\n    // Step 2.a - Create the session now that we have ready media keys on the Media Element.\n    const session = (mediaEl.mediaKeys as MediaKeys).createSession();\n\n    // Step 2.b - Call session.generateRequest (done below, after event listeners are set up)\n\n    /** Step 2.c\n     * When session.generateRequest succeeds, it returns a spc via this event's message.\n     * We use that SPC to fetch the FPS license key from the server.\n     */\n    const onMessage = async (event: MediaKeyMessageEvent) => {\n      const spc = event.message;\n      // Step 2.c.i Now that we have an FPS SPC (license request payload) from 2.b, fetch the FPS license key from the server\n      const ckc = await getLicenseKey(spc);\n\n      try {\n        // This is the same call whether we are local or AirPlay.\n        // Safari will forward CKC to Apple TV automatically.\n        // Step 2.c.ii - update the session with the license key\n        await session.update(ckc);\n      } catch {\n        // This is just catch all error management\n        const message = i18n(\n          'Failed to update DRM license. This may be an issue with the player or your protected content.'\n        );\n        const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n        mediaError.errorCategory = MuxErrorCategory.DRM;\n        mediaError.muxCode = MuxErrorCode.ENCRYPTED_UPDATE_LICENSE_FAILED;\n\n        saveAndDispatchError(mediaEl, mediaError);\n      }\n    };\n\n    /**\n     * This is just to monitor for errors.\n     */\n    const onKeyStatusChange = () => {\n      const recheckMediaKeyStatus = (mediaKeyStatus: MediaKeyStatus) => {\n        // This is just error management\n        let mediaError;\n        if (mediaKeyStatus === 'internal-error') {\n          const message = i18n(\n            'The DRM Content Decryption Module system had an internal failure. Try reloading the page, upading your browser, or playing in another browser.'\n          );\n          mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n          mediaError.errorCategory = MuxErrorCategory.DRM;\n          mediaError.muxCode = MuxErrorCode.ENCRYPTED_CDM_ERROR;\n        } else if (mediaKeyStatus === 'output-restricted' || mediaKeyStatus === 'output-downscaled') {\n          const message = i18n(\n            'DRM playback is being attempted in an environment that is not sufficiently secure. User may see black screen.'\n          );\n          // NOTE: When encountered, this is a non-fatal error (though it's certainly interruptive of standard playback experience). (CJP)\n          mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, false);\n          mediaError.errorCategory = MuxErrorCategory.DRM;\n          mediaError.muxCode = MuxErrorCode.ENCRYPTED_OUTPUT_RESTRICTED;\n        }\n\n        if (mediaError) {\n          saveAndDispatchError(mediaEl, mediaError);\n        }\n      };\n      // NOTE: As an improvement, we could also add checks for a status of 'expired' and\n      // attempt to renew the license here (CJP)\n      session.keyStatuses.forEach((keyStatus) => recheckMediaKeyStatus(keyStatus));\n    };\n\n    session.addEventListener('keystatuseschange', onKeyStatusChange);\n    session.addEventListener('message', onMessage);\n\n    const newTeardown = async () => {\n      session.removeEventListener('keystatuseschange', onKeyStatusChange);\n      session.removeEventListener('message', onMessage);\n      if ('webkitCurrentPlaybackTargetIsWireless' in mediaEl) {\n        // @ts-ignore\n        mediaEl.removeEventListener('webkitcurrentplaybacktargetiswirelesschanged', newTeardown);\n      }\n      mediaEl.removeEventListener('teardown', newTeardown);\n\n      await session.close().catch((e) => {\n        /* Will throw an error if closed in an invalid state */\n        console.warn('There was an error when closing EME session', e);\n      });\n      teardownSession = null;\n    };\n\n    // If we have a new device, we want a new session\n    if ('webkitCurrentPlaybackTargetIsWireless' in mediaEl) {\n      // @ts-ignore\n      mediaEl.addEventListener('webkitcurrentplaybacktargetiswirelesschanged', newTeardown, { once: true });\n    }\n    mediaEl.addEventListener('teardown', newTeardown, { once: true });\n    teardownSession = newTeardown;\n\n    // Step 2.b - We're finally ready to create a key request from the session. This will trigger a message event\n    await session.generateRequest(initDataType, initData).catch(async (e) => {\n      if (\n        e.name === 'NotSupportedError' &&\n        'webkitCurrentPlaybackTargetIsWireless' in mediaEl &&\n        mediaEl.webkitCurrentPlaybackTargetIsWireless\n      ) {\n        console.warn('Failed to generate a DRM license request. Attempting to fallback to Webkit DRM');\n        // This is used to address an OS bug when casting DRM protected content with AirPlay\n        // TODO: Remove this once Apple fixes this bug.\n        fallbackToWebkitFairplay?.();\n      } else {\n        const message = i18n(\n          'Failed to generate a DRM license request. This may be an issue with the player or your protected content.'\n        );\n        const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n        mediaError.errorCategory = MuxErrorCategory.DRM;\n        mediaError.muxCode = MuxErrorCode.ENCRYPTED_GENERATE_REQUEST_FAILED;\n\n        console.error('Failed to generate license request', e);\n        return Promise.reject(mediaError);\n      }\n    });\n  };\n\n  /* note: Manually adding/removing teardown function instead of\n   * addEventListenerWithTeardown to add extra cleanup logic\n   */\n  const teardownEme = async () => {\n    mediaEl.removeEventListener('encrypted', onFpEncrypted);\n    mediaEl.removeEventListener('teardown', teardownEme);\n    if (teardownSession) {\n      await teardownSession();\n    }\n    await mediaEl.setMediaKeys(null).catch(() => {});\n  };\n\n  mediaEl.addEventListener('encrypted', onFpEncrypted);\n  mediaEl.addEventListener('teardown', teardownEme, { once: true });\n\n  return teardownEme;\n};\n"],
  "mappings": "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",
  "names": ["mux", "Hls", "hls_default", "CapLevelController", "MuxErrorCategory", "MuxErrorCode", "errorCategoryToTokenNameOrPrefix", "category", "_MediaError", "message", "code", "fatal", "context", "_a", "MediaError", "isNil", "x", "isKeyOf", "k", "o", "AutoplayTypes", "StreamTypes", "PlaybackTypes", "CmcdTypes", "CmcdTypeValues", "ExtensionMimeTypeMap", "MimeTypeShorthandMap", "shorthandKeys", "allMediaTypes", "MaxResolution", "MinResolution", "RenditionOrder", "MaxAutoResolution", "code", "en_default", "addEventListenerWithTeardown", "mediaEl", "type", "listener", "options", "target", "inSeekableRange", "seekable", "duration", "time", "i", "toPlaybackIdParts", "playbackIdWithOptionalParams", "qIndex", "idPart", "queryPart", "getType", "props", "upperType", "isKeyOf", "MimeTypeShorthandMap", "inferMimeTypeFromURL", "toStreamTypeFromPlaylistType", "playlistType", "StreamTypes", "toTargetLiveWindowFromPlaylistType", "src", "pathname", "toAbsoluteUrl", "extDelimIdx", "isExtensionLessMuxM3U8URL", "ExtensionMimeTypeMap", "upperExt", "isRelativeUrl", "url", "getFirstMediaPlaylistUrl", "multivariantPlaylist", "_line", "idx", "lines", "base", "_a", "windowLocation", "absoluteBase", "MUX_VIDEO_DOMAIN", "customDomain", "urlObj", "validProtocol", "validHostname", "pathParts", "validPathPartsLength", "validExtensionlessPath", "parseJwt", "token", "base64Url", "base64", "jsonPayload", "c", "isJWTExpired", "exp", "referenceTime", "isJWTSubMismatch", "sub", "expectedSub", "isJWTAudMissing", "aud", "_expectedAud", "isJWTAudMismatch", "expectedAud", "DEFAULT_LOCALE", "i18n", "str", "translate", "_b", "message", "en_default", "locale", "IntlMessageFormat", "values", "_match", "key", "AutoplayTypeValues", "AutoplayTypes", "isAutoplayValue", "value", "setupAutoplay", "props", "mediaEl", "hls", "maybeAutoplay", "hasPlayed", "isLive", "autoplay", "updateHasPlayed", "addEventListenerWithTeardown", "handleAutoplay", "StreamTypes", "hls_default", "_event", "data", "_a", "handleSeek", "newAutoplay", "oldMuted", "restoreMuted", "setupPreload", "preload", "src", "mediaEl", "hls", "updatePreload", "val", "hasLoadedSource", "hasPlayFired", "originalLength", "originalSize", "updateHlsPreload", "newPreload", "safeLoadSource", "addEventListenerWithTeardown", "setupMinPreload", "props", "mediaEl", "hls", "minPreloadSegments", "mainSegmentsBuffered", "restored", "userPlaybackRate", "onRateChange", "addEventListenerWithTeardown", "onFragBuffered", "_e", "frag", "hls_default", "setupInitialEstimate", "_mediaEl", "initialEstimateSegments", "setupMediaTracks", "customMediaEl", "hls", "_a", "levelIdMap", "hls_default", "_event", "data", "removeAllMediaTracks", "videoTrack", "id", "level", "videoRendition", "removeAudioTracks", "a", "kind", "audioTrack", "switchAudioTrack", "audioTrackId", "t", "availableIds", "levelIds", "l", "rendition", "switchRendition", "event", "removeVideoTracks", "_b", "cuePointStart", "cuePoint", "setupTextTracks", "mediaEl", "hls", "hls_default", "_type", "tracks", "trackObj", "_a", "_b", "baseTrackObj", "idx", "lang", "name", "type", "id", "addTextTrack", "changeHandler", "showingTrack", "textTrack", "currentHlsTrack", "hlsTrackId", "defaultTrack", "cue", "track", "cues", "disabled", "trackEl", "forceHiddenTracks", "selector", "src", "kind", "label", "removeTextTrack", "trackElement", "getTextTrack", "addCuesToTextTrack", "resolve", "cuePointA", "cuePointB", "value", "startTime", "cueAfterIndex", "cueAfter", "endTime", "previousCue", "DEFAULT_CUEPOINTS_TRACK_LABEL", "DefaultCuePointsConfig", "addCuePoints", "cuePoints", "cuePointsConfig", "toCuePoint", "getCuePoints", "getActiveCuePoint", "currentTime", "actualActiveCue", "setupCuePoints", "addEventListenerWithTeardown", "activeCuePoint", "evt", "DEFAULT_CHAPTERS_TRACK_LABEL", "DefaultChaptersConfig", "vttCueToChapter", "addChapters", "chapters", "chaptersConfig", "getChapters", "getActiveChapter", "setupChapters", "getStartDate", "mediaEl", "hls", "playingDate", "getCurrentPdt", "startDate", "MuxJWTAud", "categoryToAud", "category", "MuxErrorCategory", "categoryToToken", "muxMediaEl", "_a", "_b", "nameOrPrefix", "errorCategoryToTokenNameOrPrefix", "tokenName", "isKeyOf", "getErrorFromResponse", "resp", "fatal", "translate", "offline", "message", "i18n", "context", "mediaErrorCode", "MediaError", "mediaError", "MuxErrorCode", "status", "requestTime", "tokenNamePrefix", "token", "expectedAud", "playbackId", "toPlaybackIdParts", "jwtObj", "parseJwt", "isJWTExpired", "dateOptions", "isJWTSubMismatch", "isJWTAudMissing", "isJWTAudMismatch", "StreamTypes", "CapLevelController", "hls_default", "RESOLUTION_PIXEL_LIMITS", "resolutionToMaxPixels", "resolution", "normalized", "_MinCapLevelController", "hls", "maxAutoResolution", "_a", "hlsInstance", "capLevelIndex", "level", "index", "validLevels", "maxPixels", "levelsWithinCap", "exactMatch", "exactLevel", "highestQualityWithinCap", "baseMaxLevel", "baseMaxLevelResolution", "preferredMinMaxResolution", "MinCapLevelController", "min_cap_level_controller_default", "LEGACY_KEY_SYSTEM", "MIME_TYPE", "setupWebkitNativeFairplayDRM", "mediaEl", "getAppCertificate", "getLicenseKey", "saveAndDispatchError", "drmTypeCb", "message", "i18n", "mediaError", "MediaError", "MuxErrorCategory", "MuxErrorCode", "wkMediaEl", "certificatePromise", "teardownSession", "onWebkitNeedKey", "ev", "setupWebkitKey", "certificate", "initData", "getInitData", "setupWebkitKeySession", "e", "mediaKeys", "session", "onWebkitKeyMessage", "event", "spc", "ckc", "errOrResp", "onWebkitKeyError", "error", "newTeardown", "teardownWebkit", "initDataBuffer", "certificateBuffer", "contentIdBuffer", "stringToUtf16LE", "getContentId", "contentId", "newLength", "rebuiltInitData", "offset", "append", "array", "appendWithLength", "view", "value", "str", "buffer", "i", "setupEmeNativeFairplayDRM", "mediaEl", "getAppCertificate", "getLicenseKey", "saveAndDispatchError", "drmTypeCb", "fallbackToWebkitFairplay", "teardownSession", "onFpEncrypted", "event", "initDataType", "setupMediaKeys", "initData", "setupMediaKeySession", "error", "access", "value", "message", "i18n", "mediaError", "MediaError", "MuxErrorCategory", "MuxErrorCode", "keys", "fairPlayAppCert", "session", "onMessage", "spc", "ckc", "onKeyStatusChange", "recheckMediaKeyStatus", "mediaKeyStatus", "keyStatus", "newTeardown", "e", "teardownEme", "DRMType", "toDRMTypeFromKeySystem", "keySystem", "getMediaPlaylistFromMultivariantPlaylist", "multivariantPlaylist", "masterPlaylistUrl", "mediaPlaylistUrl", "getFirstMediaPlaylistUrl", "isRelativeUrl", "fetchUrl", "toAbsoluteUrl", "e", "resp", "getMultivariantPlaylistSessionData", "playlist", "sessionDataLines", "line", "sessionData", "sessionDataAttrs", "parseTagAttributes", "dataId", "ATTR_LIST_REGEX", "str", "matches", "key", "value", "getStreamInfoFromPlaylist", "_a", "_b", "_c", "playlistLines", "playlistType", "streamType", "toStreamTypeFromPlaylistType", "targetLiveWindow", "toTargetLiveWindowFromPlaylistType", "liveEdgeStartOffset", "StreamTypes", "partInfLine", "targetDurationLine", "targetDurationValue", "getStreamInfoFromSrcAndType", "src", "type", "ExtensionMimeTypeMap", "multivariantPlaylistResponse", "mediaPlaylist", "updateStreamInfoFromSrc", "mediaEl", "getType", "_d", "metadata", "fetchAndDispatchMuxMetadata", "muxMediaState", "metadataUrl", "json", "item", "eventUpdateMetadata", "error", "getStreamInfoFromHlsjsLevelDetails", "levelDetails", "lowLatency", "updateStreamInfoFromHlsjsLevelDetails", "hls", "_e", "_f", "_g", "_h", "seekable", "index", "userAgentStr", "userAgentPlatform", "isAndroidLike", "platformStr", "isSafari", "MUX_VIDEO_DOMAIN", "MSE_SUPPORTED", "hls_default", "shouldDefaultToMSE", "generatePlayerInitTime", "mux", "generateUUID", "toMuxVideoURL", "playbackIdWithParams", "domain", "maxResolution", "minResolution", "renditionOrder", "programStartTime", "programEndTime", "assetStartTime", "assetEndTime", "playbackToken", "token", "extraSourceParams", "playbackId", "queryPart", "toPlaybackIdParts", "url", "_", "k", "v", "toPlaybackIdFromParameterized", "toPlaybackIdFromSrc", "toVideoId", "props", "isMuxVideoSrc", "getError", "getMetadata", "getStreamType", "getTargetLiveWindow", "getSeekable", "getLiveEdgeStart", "getCoreReference", "DEFAULT_ENDED_MOE", "isApproximatelyEqual", "x", "y", "moe", "isApproximatelyGTE", "isPseudoEnded", "isStuckOnLastFragment", "videoLevelDetails", "level", "fragments", "lastFragment", "lastFragmentMidpoint", "lastBufferedStart", "lastBufferedEnd", "getEnded", "initialize", "core", "teardown", "view_session_id", "video_id", "drmTypeCb", "drmType", "wasPlaying", "currentTime", "muxDataKeepSession", "oldCore", "nextHlsInstance", "setupHls", "setPreload", "setupPreload", "setupMux", "loadMedia", "setupCuePoints", "setupChapters", "setAutoplay", "setupAutoplay", "setupMinPreload", "setupInitialEstimate", "newCore", "state", "handleNativeError", "handleInternalError", "seekInSeekableRange", "useNative", "canUseNative", "preferPlayback", "preferMse", "PlaybackTypes", "preferNative", "forceMse", "debug", "startPosition", "preferCmcd", "_hlsConfig", "maxAutoResolution", "initialBandwidthEstimateKbps", "hlsType", "shouldUseNative", "defaultConfig", "streamTypeConfig", "getStreamTypeConfig", "drmConfig", "getDRMConfig", "cmcd", "CmcdTypes", "capLevelControllerObj", "getCapLevelControllerConfig", "xhr", "urlObj", "cmcdVal", "cmcdKVStr", "min_cap_level_controller_default", "_event", "data", "chapters", "drmToken", "playbackIdWithOptionalParams", "toLicenseKeyURL", "toAppCertURL", "supportedConfigurations", "mediaKeySystemConfig", "videoCapabilities", "capability", "getAppCertificate", "appCertificateUrl", "getLicenseKey", "message", "licenseServerUrl", "keyBuffer", "setupNativeFairplayDRM", "commonConfig", "errOrResp", "mediaError", "getErrorFromResponse", "MuxErrorCategory", "saveAndDispatchError", "setupWebkitNativeFairplayDRM", "emeConfig", "teardownEme", "setupEmeNativeFairplayDRM", "customDomain", "scheme", "base", "hostname", "CapLevelController", "hlsjs", "env_key", "disableTracking", "muxDataSDK", "muxDataSDKOptions", "inferredEnv", "player_init_time", "player_software_name", "player_software_version", "beaconCollectionDomain", "disableCookies", "muxEmbedErrorTranslator", "maybeDispatchEndedCallback", "prevSeekableStart", "prevSeekableEnd", "seekableChange", "seekableTimeRanges", "nextSeekableStart", "nextSeekableEnd", "addEventListenerWithTeardown", "setupSeekableChangePoll", "intervalId", "setupNativeStreamInfo", "playHandler", "loadedMetadataHandler", "i18n", "MediaError", "MuxErrorCode", "trackEl", "_evt", "getErrorFromHlsErrorData", "retryCount", "retryDelay", "retryDelayError", "retryTimerId", "retryLinkError", "setupMediaTracks", "setupTextTracks", "event", "startTime", "inSeekableRange", "wasAuto", "code", "ourError", "status", "ErrorCodeMap", "hlsErrorDataToErrorCode", "hlsErrorDataToCategory", "errorCode", "category"]
}
