video-dev / video-dev/hls.js

Playback stops when AES-128, SAMPLE-AES, MPEG-TS, and/or fMP4 assets are mixed within a media playlist

Open
#8,002 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Needs Triage
Dominant language
TypeScript
Stars
16.9k
Forks
2.8k
Avg merge
1d 12h
Merged PRs (30d)
27

Description

What version of HLS.js are you using?

hls.js version 1.5.11

What browser (including version) are you using?

Firefox Mac (Intel) 154.0

What OS (including version) are you using?

MacOS (Intel) Sequoia 15.7.9

Test stream

I may not be able to provide a publicly accessible test stream because the media and encryption keys cannot be shared publicly. I can provide representative working and non-working multivariant and media playlists. If needed, I can also provide additional packaging details required to reproduce the streams.

Configuration
{
  "autoStartLoad": true,
  "startPosition": -1,
  "debug": false,
  "capLevelOnFPSDrop": false,
  "capLevelToPlayerSize": false,
  "ignoreDevicePixelRatio": false,
  "preferManagedMediaSource": true,
  "initialLiveManifestSize": 1,
  "maxBufferLength": 30,
  "backBufferLength": null,
  "frontBufferFlushThreshold": null,
  "maxBufferSize": 60000000,
  "maxBufferHole": 0.1,
  "highBufferWatchdogPeriod": 2,
  "nudgeOffset": 0.1,
  "nudgeMaxRetry": 3,
  "maxFragLookUpTolerance": 0.25,
  "liveSyncDurationCount": 3,
  "liveMaxLatencyDurationCount": null,
  "maxLiveSyncPlaybackRate": 1,
  "liveDurationInfinity": false,
  "liveBackBufferLength": null,
  "maxMaxBufferLength": 600,
  "enableWorker": true,
  "workerPath": null,
  "enableSoftwareAES": true,
  "startFragPrefetch": false,
  "fpsDroppedMonitoringPeriod": 5000,
  "fpsDroppedMonitoringThreshold": 0.2,
  "appendErrorMaxRetry": 3,
  "stretchShortVideoTrack": false,
  "maxAudioFramesDrift": 1,
  "forceKeyFrameOnDiscontinuity": true,
  "abrEwmaFastLive": 3,
  "abrEwmaSlowLive": 9,
  "abrEwmaFastVoD": 3,
  "abrEwmaSlowVoD": 9,
  "abrEwmaDefaultEstimate": 500000,
  "abrEwmaDefaultEstimateMax": 5000000,
  "abrBandWidthFactor": 0.95,
  "abrBandWidthUpFactor": 0.7,
  "abrMaxWithRealBitrate": false,
  "maxStarvationDelay": 4,
  "maxLoadingDelay": 4,
  "minAutoBitrate": 0,
  "emeEnabled": false,
  "drmSystems": {},
  "drmSystemOptions": {},
  "testBandwidth": true,
  "progressive": false,
  "lowLatencyMode": true,
  "enableDateRangeMetadataCues": true,
  "enableEmsgMetadataCues": true,
  "enableID3MetadataCues": true,
  "useMediaCapabilities": true,
  "certLoadPolicy": {
    "default": {
      "maxTimeToFirstByteMs": 8000,
      "maxLoadTimeMs": 20000,
      "timeoutRetry": null,
      "errorRetry": null
    }
  },
  "keyLoadPolicy": {
    "default": {
      "maxTimeToFirstByteMs": 8000,
      "maxLoadTimeMs": 20000,
      "timeoutRetry": {
        "maxNumRetry": 1,
        "retryDelayMs": 1000,
        "maxRetryDelayMs": 20000,
        "backoff": "linear"
      },
      "errorRetry": {
        "maxNumRetry": 8,
        "retryDelayMs": 1000,
        "maxRetryDelayMs": 20000,
        "backoff": "linear"
      }
    }
  },
  "manifestLoadPolicy": {
    "default": {
      "maxTimeToFirstByteMs": null,
      "maxLoadTimeMs": 20000,
      "timeoutRetry": {
        "maxNumRetry": 2,
        "retryDelayMs": 0,
        "maxRetryDelayMs": 0
      },
      "errorRetry": {
        "maxNumRetry": 1,
        "retryDelayMs": 1000,
        "maxRetryDelayMs": 8000
      }
    }
  },
  "playlistLoadPolicy": {
    "default": {
      "maxTimeToFirstByteMs": 10000,
      "maxLoadTimeMs": 20000,
      "timeoutRetry": {
        "maxNumRetry": 2,
        "retryDelayMs": 0,
        "maxRetryDelayMs": 0
      },
      "errorRetry": {
        "maxNumRetry": 2,
        "retryDelayMs": 1000,
        "maxRetryDelayMs": 8000
      }
    }
  },
  "fragLoadPolicy": {
    "default": {
      "maxTimeToFirstByteMs": 10000,
      "maxLoadTimeMs": 120000,
      "timeoutRetry": {
        "maxNumRetry": 4,
        "retryDelayMs": 0,
        "maxRetryDelayMs": 0
      },
      "errorRetry": {
        "maxNumRetry": 6,
        "retryDelayMs": 1000,
        "maxRetryDelayMs": 8000
      }
    }
  },
  "steeringManifestLoadPolicy": {
    "default": {
      "maxTimeToFirstByteMs": 10000,
      "maxLoadTimeMs": 20000,
      "timeoutRetry": {
        "maxNumRetry": 2,
        "retryDelayMs": 0,
        "maxRetryDelayMs": 0
      },
      "errorRetry": {
        "maxNumRetry": 1,
        "retryDelayMs": 1000,
        "maxRetryDelayMs": 8000
      }
    }
  },
  "manifestLoadingTimeOut": 10000,
  "manifestLoadingMaxRetry": 1,
  "manifestLoadingRetryDelay": 1000,
  "manifestLoadingMaxRetryTimeout": 64000,
  "levelLoadingTimeOut": 10000,
  "levelLoadingMaxRetry": 4,
  "levelLoadingRetryDelay": 1000,
  "levelLoadingMaxRetryTimeout": 64000,
  "fragLoadingTimeOut": 20000,
  "fragLoadingMaxRetry": 6,
  "fragLoadingRetryDelay": 1000,
  "fragLoadingMaxRetryTimeout": 64000,
  "cueHandler": {},
  "enableWebVTT": true,
  "enableIMSC1": true,
  "enableCEA708Captions": true,
  "captionsTextTrack1Label": "English",
  "captionsTextTrack1LanguageCode": "en",
  "captionsTextTrack2Label": "Spanish",
  "captionsTextTrack2LanguageCode": "es",
  "captionsTextTrack3Label": "Unknown CC",
  "captionsTextTrack3LanguageCode": "",
  "captionsTextTrack4Label": "Unknown CC",
  "captionsTextTrack4LanguageCode": "",
  "renderTextTracksNatively": true
}
Additional player setup steps

The presentation is VOD and has a multivariant playlist containing five bitrate variants.

Each variant media playlist contains a chronological sequence of VOD assets. Every variant uses the same asset order and changes container format at the same asset boundaries.

The affected media playlists combine:

  • MPEG-TS media segments encrypted using METHOD=AES-128
  • fMP4 media segments encrypted using METHOD=AES-128
  • An encrypted fMP4 initialization section referenced by EXT-X-MAP
  • EXT-X-KEY placed before the applicable encrypted EXT-X-MAP
  • EXT-X-DISCONTINUITY at each asset/container boundary

The following configurations work:

  1. All assets in every variant media playlist are AES-128-encrypted MPEG-TS.
  2. All assets in every variant media playlist are AES-128-encrypted fMP4.

For the all-fMP4 configuration, both the fMP4 media segments and the initialization section referenced by EXT-X-MAP are AES-128 encrypted. The applicable EXT-X-KEY appears before EXT-X-MAP. This configuration plays correctly in HLS.js.

Playback fails only when the variant media playlists contain both AES-128 MPEG-TS and AES-128 fMP4 assets. The failure occurs regardless of which container format appears first.

Checklist
Steps to reproduce

I found related issues, but none appears to cover this exact case:

  • #1510 — MPEG-TS and muxed fMP4 in the same HLS presentation
  • #5195 — freezing when a multivariant presentation contains fMP4 and TS variants
  • #2259 — AES-128 support for fMP4/ISOBMFF
  • #4933 — AES-128-encrypted fMP4 playback and encrypted initialization-section handling

Unlike #5195, the container transition in this case occurs chronologically inside each variant media playlist. It is not caused by switching from a TS variant to an fMP4 variant.

Steps to reproduce
  1. Create a VOD multivariant playlist containing five bitrate variants.
  2. For each bitrate, create a media playlist containing at least two sequential VOD assets.
  3. Package one asset as MPEG-TS and encrypt its complete media segments using HLS METHOD=AES-128.
  4. Package the other asset as fMP4 and encrypt both its initialization section and media segments using HLS METHOD=AES-128.
  5. In each variant media playlist, place the applicable EXT-X-KEY before the encrypted EXT-X-MAP.
  6. Mark the asset/container transition with EXT-X-DISCONTINUITY.
  7. Load the multivariant playlist in HLS.js and begin playback.
  8. Repeat with the fMP4 asset first and the MPEG-TS asset second.

Control tests:

  1. Create the same presentation using only AES-128 MPEG-TS assets. Playback completes normally.
  2. Create the same presentation using only AES-128 fMP4 assets. Playback completes normally.
  3. Create the presentation using both containers. Playback stops after the first asset.
Expected behaviour

Playback should continue across an EXT-X-DISCONTINUITY when the next asset changes from AES-128 MPEG-TS to AES-128 fMP4, or from AES-128 fMP4 to AES-128 MPEG-TS.

HLS.js should reset or replace any container-specific demuxer, transmuxer, initialization-segment, decryption, timestamp, and buffering state required for the next asset.

What actually happened?

Only the first VOD asset in the mixed-container media playlist plays.

When playback reaches the first transition between MPEG-TS and fMP4, it does not continue into the second asset. The result is the same in both directions:

  • AES-128 MPEG-TS followed by AES-128 fMP4
  • AES-128 fMP4 followed by AES-128 MPEG-TS

The same underlying assets play successfully when the complete presentation contains only MPEG-TS or only fMP4.

Representative playlists
Multivariant playlist
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-STREAM-INF:BANDWIDTH=2592576,RESOLUTION=1280x720,CODECS="avc1.4d001f,mp4a.40.2"
http://192.168.118.129/appapi/v1/vodmedia/5e2b0220-7abf-11ef-a8a7-239b4eabb0df/1280x/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1667968,RESOLUTION=960x540,CODECS="avc1.4d001f,mp4a.40.2"
http://192.168.118.129/appapi/v1/vodmedia/5e2b0220-7abf-11ef-a8a7-239b4eabb0df/960x/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=976168,RESOLUTION=640x360,CODECS="avc1.4d001f,mp4a.40.2"
http://192.168.118.129/appapi/v1/vodmedia/5e2b0220-7abf-11ef-a8a7-239b4eabb0df/640x/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=621848,RESOLUTION=480x270,CODECS="avc1.4d001f,mp4a.40.2"
http://192.168.118.129/appapi/v1/vodmedia/5e2b0220-7abf-11ef-a8a7-239b4eabb0df/480x/index.m3u8
Working media playlist: AES-128 fMP4 only
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-DISCONTINUITY-SEQUENCE:0
#EXT-X-CUE-OUT:30.000
#EXT-X-KEY:METHOD=AES-128,URI="http://192.168.118.129/appapi/v1/hlskeypayload/811ed060-40da-11f1-91e4-4d5d1500a384",IV=0x338ceefb449abaf629b367d3cf7d1292
#EXT-X-MAP:URI="http://192.168.118.129/appapi/v1/segment/1280x811ed06040da11f191e44d5d1500a384x/1280x811ed06040da11f191e44d5d1500a384x.m4s"
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:00:11.000+00:00
#EXT-X-DATERANGE:START-DATE="2026-08-22T20:00:11.000+00:00"
#EXTINF:10.010,
http://192.168.118.129/appapi/v1/segment/1280x811ed06040da11f191e44d5d1500a384x/1280x811ed06040da11f191e44d5d1500a384x0000.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:00:22.000+00:00
#EXT-X-DATERANGE:START-DATE="2026-08-22T20:00:22.000+00:00"
#EXTINF:10.010,
http://192.168.118.129/appapi/v1/segment/1280x811ed06040da11f191e44d5d1500a384x/1280x811ed06040da11f191e44d5d1500a384x0001.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:00:33.000+00:00
#EXT-X-DATERANGE:START-DATE="2026-08-22T20:00:33.000+00:00"
#EXTINF:10.010,
http://192.168.118.129/appapi/v1/segment/1280x811ed06040da11f191e44d5d1500a384x/1280x811ed06040da11f191e44d5d1500a384x0002.m4s
#EXT-X-CUE-IN
#EXT-X-DISCONTINUITY
#EXT-X-KEY:METHOD=AES-128,URI="http://192.168.118.129/appapi/v1/hlskeypayload/5e2b0220-7abf-11ef-a8a7-239b4eabb0df",IV=0x800b820bf3624a3fb7aa25f7a7b38bc7
#EXT-X-MAP:URI="http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx.m4s"
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:00:43.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:00:43.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0000.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:00:53.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:00:53.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0001.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:03.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:03.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0002.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:13.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:13.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0003.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:23.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:23.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0004.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:33.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:33.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0005.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:43.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:43.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0006.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:44.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:44.000+00:00"
#EXTINF:0.830,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0007.m4s
#EXT-X-CUE-OUT:30.000
#EXT-X-DISCONTINUITY
#EXT-X-KEY:METHOD=AES-128,URI="http://192.168.118.129/appapi/v1/hlskeypayload/7bef40e0-40da-11f1-83bf-87e1ba602778",IV=0x9e0029e8132de414ca3341d25bb9f9ed
#EXT-X-MAP:URI="http://192.168.118.129/appapi/v1/segment/1280x7bef40e040da11f183bf87e1ba602778x/1280x7bef40e040da11f183bf87e1ba602778x.m4s"
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:54.000+00:00
#EXT-X-DATERANGE:ID="20000",START-DATE="2026-08-22T20:01:54.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x7bef40e040da11f183bf87e1ba602778x/1280x7bef40e040da11f183bf87e1ba602778x0000.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:02:04.000+00:00
#EXT-X-DATERANGE:ID="20000",START-DATE="2026-08-22T20:02:04.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x7bef40e040da11f183bf87e1ba602778x/1280x7bef40e040da11f183bf87e1ba602778x0001.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:02:14.000+00:00
#EXT-X-DATERANGE:ID="20000",START-DATE="2026-08-22T20:02:14.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x7bef40e040da11f183bf87e1ba602778x/1280x7bef40e040da11f183bf87e1ba602778x0002.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:02:15.000+00:00
#EXT-X-DATERANGE:ID="20000",START-DATE="2026-08-22T20:02:15.000+00:00"
#EXTINF:0.040,
http://192.168.118.129/appapi/v1/segment/1280x7bef40e040da11f183bf87e1ba602778x/1280x7bef40e040da11f183bf87e1ba602778x0003.m4s
#EXT-X-CUE-IN
#EXT-X-ENDLIST
Failing media playlist: MPEG-TS followed by fMP4
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-DISCONTINUITY-SEQUENCE:0
#EXT-X-CUE-OUT:30.000
#EXT-X-KEY:METHOD=AES-128,URI="http://192.168.118.129/appapi/v1/hlskeypayload/ba886e00-e7f3-11eb-a656-e7f5b1035698",IV=0x8dc3182970979e3e6b8a05009b4d45ac
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:00:11.000+00:00
#EXT-X-DATERANGE:START-DATE="2026-08-22T20:00:11.000+00:00"
#EXTINF:10.800,
http://192.168.118.129/appapi/v1/segment/1280xba886e00e7f311eba656e7f5b1035698x/1280xba886e00e7f311eba656e7f5b1035698x0.ts
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:00:21.000+00:00
#EXT-X-DATERANGE:START-DATE="2026-08-22T20:00:21.000+00:00"
#EXTINF:9.600,
http://192.168.118.129/appapi/v1/segment/1280xba886e00e7f311eba656e7f5b1035698x/1280xba886e00e7f311eba656e7f5b1035698x1.ts
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:00:31.000+00:00
#EXT-X-DATERANGE:START-DATE="2026-08-22T20:00:31.000+00:00"
#EXTINF:9.600,
http://192.168.118.129/appapi/v1/segment/1280xba886e00e7f311eba656e7f5b1035698x/1280xba886e00e7f311eba656e7f5b1035698x2.ts
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:00:31.000+00:00
#EXT-X-DATERANGE:START-DATE="2026-08-22T20:00:31.000+00:00"
#EXTINF:0.000,
http://192.168.118.129/appapi/v1/segment/1280xba886e00e7f311eba656e7f5b1035698x/1280xba886e00e7f311eba656e7f5b1035698x3.ts
#EXT-X-CUE-IN
#EXT-X-DISCONTINUITY
#EXT-X-KEY:METHOD=AES-128,URI="http://192.168.118.129/appapi/v1/hlskeypayload/5e2b0220-7abf-11ef-a8a7-239b4eabb0df",IV=0x800b820bf3624a3fb7aa25f7a7b38bc7
#EXT-X-MAP:URI="http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx.m4s"
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:00:41.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:00:41.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0000.m4s?
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:00:51.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:00:51.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0001.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:01.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:01.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0002.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:11.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:11.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0003.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:21.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:21.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0004.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:31.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:31.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0005.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:41.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:41.000+00:00"
#EXTINF:10.000,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0006.m4s
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:42.000+00:00
#EXT-X-DATERANGE:ID="10000",START-DATE="2026-08-22T20:01:42.000+00:00"
#EXTINF:0.830,
http://192.168.118.129/appapi/v1/segment/1280x5e2b02207abf11efa8a7239b4eabb0dfx/1280x5e2b02207abf11efa8a7239b4eabb0dfx0007.m4s
#EXT-X-CUE-OUT:30.000
#EXT-X-DISCONTINUITY
#EXT-X-KEY:METHOD=AES-128,URI="http://192.168.118.129/appapi/v1/hlskeypayload/5540b1f0-2cd2-11ee-a71d-fd02cbc1ae8b",IV=0x1a140acbcabb4807be0674326efd5c57
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:01:53.000+00:00
#EXT-X-DATERANGE:ID="20000",START-DATE="2026-08-22T20:01:53.000+00:00"
#EXTINF:10.010,
http://192.168.118.129/appapi/v1/segment/1280x5540b1f02cd211eea71dfd02cbc1ae8bx/1280x5540b1f02cd211eea71dfd02cbc1ae8bx0.ts
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:02:04.000+00:00
#EXT-X-DATERANGE:ID="20000",START-DATE="2026-08-22T20:02:04.000+00:00"
#EXTINF:10.010,
http://192.168.118.129/appapi/v1/segment/1280x5540b1f02cd211eea71dfd02cbc1ae8bx/1280x5540b1f02cd211eea71dfd02cbc1ae8bx1.ts
#EXT-X-PROGRAM-DATE-TIME:2026-08-22T20:02:14.000+00:00
#EXT-X-DATERANGE:ID="20000",START-DATE="2026-08-22T20:02:14.000+00:00"
#EXTINF:9.980,
http://192.168.118.129/appapi/v1/segment/1280x5540b1f02cd211eea71dfd02cbc1ae8bx/1280x5540b1f02cd211eea71dfd02cbc1ae8bx2.ts
#EXT-X-CUE-IN
#EXT-X-ENDLIST

Sensitive hostnames, tokens, and key URIs have been replaced consistently where necessary. Tag ordering and playlist structure are unchanged.

Console output
[HTTP/1 204 No Content 22ms]
[warn] > Ignoring invalid DATERANGE tag: "START-DATE="2026-08-22T20:00:11.000+00:00"" [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[warn] > Ignoring invalid DATERANGE tag: "START-DATE="2026-08-22T20:00:21.000+00:00"" [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[warn] > Ignoring invalid DATERANGE tag: "START-DATE="2026-08-22T20:00:31.000+00:00"" 2 [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[warn] > DATERANGE tag attribute: "START-DATE" does not match for tags with ID: "10000" [app.js:30561:18](http://192.168.118.129:8443/js/app.js)
[warn] > Ignoring invalid DATERANGE tag: "ID="10000",START-DATE="2026-08-22T20:00:51.000+00:00"" [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[warn] > DATERANGE tag attribute: "START-DATE" does not match for tags with ID: "10000" [app.js:30561:18](http://192.168.118.129:8443/js/app.js)
[warn] > Ignoring invalid DATERANGE tag: "ID="10000",START-DATE="2026-08-22T20:01:01.000+00:00"" [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[warn] > DATERANGE tag attribute: "START-DATE" does not match for tags with ID: "10000" [app.js:30561:18](http://192.168.118.129:8443/js/app.js)
[warn] > Ignoring invalid DATERANGE tag: "ID="10000",START-DATE="2026-08-22T20:01:11.000+00:00"" [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[warn] > DATERANGE tag attribute: "START-DATE" does not match for tags with ID: "10000" [app.js:30561:18](http://192.168.118.129:8443/js/app.js)
[warn] > Ignoring invalid DATERANGE tag: "ID="10000",START-DATE="2026-08-22T20:01:21.000+00:00"" [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[warn] > DATERANGE tag attribute: "START-DATE" does not match for tags with ID: "10000" [app.js:30561:18](http://192.168.118.129:8443/js/app.js)
[warn] > Ignoring invalid DATERANGE tag: "ID="10000",START-DATE="2026-08-22T20:01:31.000+00:00"" [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[warn] > DATERANGE tag attribute: "START-DATE" does not match for tags with ID: "10000" [app.js:30561:18](http://192.168.118.129:8443/js/app.js)
[warn] > Ignoring invalid DATERANGE tag: "ID="10000",START-DATE="2026-08-22T20:01:41.000+00:00"" [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[warn] > DATERANGE tag attribute: "START-DATE" does not match for tags with ID: "10000" [app.js:30561:18](http://192.168.118.129:8443/js/app.js)
[warn] > Ignoring invalid DATERANGE tag: "ID="10000",START-DATE="2026-08-22T20:01:42.000+00:00"" [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[warn] > DATERANGE tag attribute: "START-DATE" does not match for tags with ID: "20000" [app.js:30561:18](http://192.168.118.129:8443/js/app.js)
[warn] > Ignoring invalid DATERANGE tag: "ID="20000",START-DATE="2026-08-22T20:02:04.000+00:00"" [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[warn] > DATERANGE tag attribute: "START-DATE" does not match for tags with ID: "20000" [app.js:30561:18](http://192.168.118.129:8443/js/app.js)
[warn] > Ignoring invalid DATERANGE tag: "ID="20000",START-DATE="2026-08-22T20:02:14.000+00:00"" [app.js:33468:24](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: Level 1 loaded [0,14][part-14--1], cc [0, 2] duration:130.83 [app.js:57091:10](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: WAITING_LEVEL->IDLE [app.js:40398:12](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: Loading key for initSegment of [0-14], level 1 [app.js:39575:12](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: IDLE->KEY_LOADING [app.js:40398:12](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: Loading fragment initSegment cc: 0 of [0-14] level: 1, target: 30 [app.js:39635:10](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: KEY_LOADING->FRAG_LOADING [app.js:40398:12](http://192.168.118.129:8443/js/app.js)
XHR 
GET
http://192.168.118.129/appapi/v1/segment/640x5e2b02207abf11efa8a7239b4eabb0dfx/640x5e2b02207abf11efa8a7239b4eabb0dfx.m4s
[HTTP/1.1 200 OK 12ms]
XHR 
OPTIONS
http://192.168.118.129/appapi/v1/segment/640x5e2b02207abf11efa8a7239b4eabb0dfx/640x5e2b02207abf11efa8a7239b4eabb0dfx.m4s
[HTTP/1 204 No Content 10ms]
[log] > [stream-controller]: FRAG_LOADING->IDLE [app.js:40398:12](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: Loading fragment 4 cc: 1 of [0-14] level: 1, target: 30.023 [app.js:39635:10](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: IDLE->FRAG_LOADING [app.js:40398:12](http://192.168.118.129:8443/js/app.js)
XHR 
GET
http://192.168.118.129/appapi/v1/segment/640x5e2b02207abf11efa8a7239b4eabb0dfx/640x5e2b02207abf11efa8a7239b4eabb0dfx0000.m4s
[HTTP/1.1 200 OK 14ms]
XHR 
OPTIONS
http://192.168.118.129/appapi/v1/segment/640x5e2b02207abf11efa8a7239b4eabb0dfx/640x5e2b02207abf11efa8a7239b4eabb0dfx0000.m4s
[HTTP/1 204 No Content 10ms]
[log] > [transmuxer-interface, main]: Starting new transmux session for sn: 4 p: -1 level: 1 id: 1
        discontinuity: false
        trackSwitch: true
        contiguous: false
        accurateTimeOffset: true
        timeOffset: 30
        initSegmentChange: true [app.js:45531:14](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: FRAG_LOADING->PARSING [app.js:40398:12](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: Loaded fragment 4 of level 1 [app.js:39369:14](http://192.168.118.129:8443/js/app.js)
[log] > [transmuxer.ts]: Flushed fragment 4 of level 1 [app.js:44865:12](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: Init audiovideo buffer, container:video/mp4, codecs[level/parsed]=[avc1.4d001f,mp4a.40.2/mp4a.40.2,avc1.4D481F] [app.js:57641:12](http://192.168.118.129:8443/js/app.js)
[warn] > [buffer-operation-queue]: Exception executing "audiovideo" SourceBuffer operation: Error: Attempting to append to the audiovideo SourceBuffer, but it does not exist [app.js:47705:16](http://192.168.118.129:8443/js/app.js)
[warn] > [buffer-controller] Failed 3/3 times to append segment in "audiovideo" sourceBuffer [app.js:48199:16](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: PARSING->ERROR [app.js:40398:12](http://192.168.118.129:8443/js/app.js)
[log] > [audio-stream-controller]: STOPPED->ERROR [app.js:40398:12](http://192.168.118.129:8443/js/app.js)
[log] > stopLoad [app.js:58060:12](http://192.168.118.129:8443/js/app.js)
[log] > [stream-controller]: ERROR->STOPPED [app.js:40398:12](http://192.168.118.129:8443/js/app.js)
[log] > [audio-stream-controller]: ERROR->STOPPED [app.js:40398:12](http://192.168.118.129:8443/js/app.js)
[log] > [subtitle-stream-controller]: IDLE->STOPPED [app.js:40398:12](http://192.168.118.129:8443/js/app.js)
Chrome media internals output
Not available

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the mixed-container playlists on the hls.js demo, using the AES-128 MPEG-TS-to-fMP4 and fMP4-to-MPEG-TS transitions described here. Trace handling around EXT-X-DISCONTINUITY, encrypted EXT-X-MAP sections, and demuxer or buffering state. Done means playback continues in both transition directions while the all-TS and all-fMP4 control cases still pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
audio-video-rtc, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.