Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encrypted HLS failing to play with "no demux matching with content found" error. #2441

Closed
mikemerritt opened this issue Nov 8, 2019 · 5 comments

Comments

@mikemerritt
Copy link

mikemerritt commented Nov 8, 2019

What do you want to do with Hls.js?
I am trying to play an encrypted HLS stream that is transcoded via AWS Elemental MediaConvert. The stream plays fine with encryption disabled but when enabled I get the following error.

{ type: "mediaError", details: "fragParsingError", fatal: true, reason: "no demux matching with content found" }

What have you tried so far?

I re-transcoded the file with no encryption and it plays perfectly. This leads me to believe it's not actually a demux issue and is a decryption issue. The fragment looks like it decrypts successfully as the FRAG_DECRYPTED event is fired and it looks like valid frag data, but I'm unsure. I've found some other issues about the no demux matching with content found error but those all seem to be related to an invalid container format, but that doesn't seem to explain my issue as the container works fine when decryption is disabled.

Here are the encryption settings from MediaConvert

Screen Shot 2019-11-07 at 9 33 55 PM

Here is the output with debug enabled. I logged out the fragment when the decryption event fires.


hls.js?ba56:16977 [log] > loadSource:https://signed_cloudfront_url_to_m3u8_playlist
hls.js?ba56:16977 [log] > trigger BUFFER_RESET
hls.js?ba56:16977 [log] > attachMedia
hls.js?ba56:16977 [log] > loadSource:https://signed_cloudfront_url_to_m3u8_playlist
hls.js?ba56:16977 [log] > trigger BUFFER_RESET
hls.js?ba56:16977 [log] > attachMedia
hls.js?ba56:16977 [log] > media source opened
hls.js?ba56:16977 [log] > media source closed
hls.js?ba56:16977 [log] > manifest loaded,6 level(s) found, first bitrate:1783296
hls.js?ba56:16977 [log] > 1 bufferCodec event(s) expected
hls.js?ba56:16977 [log] > startLoad(-1)
hls.js?ba56:16977 [log] > switching to level 0
hls.js?ba56:16977 [log] > main stream:STOPPED->IDLE
hls.js?ba56:16977 [log] > audio tracks updated
hls.js?ba56:16977 [log] > subtitle tracks updated
hls.js?ba56:16977 [log] > level 0 loaded [1,1],duration:9
hls.js?ba56:16977 [log] > Loading key for 1 of [1 ,1],level 0
hls.js?ba56:16977 [log] > main stream:IDLE->KEY_LOADING
hls.js?ba56:16977 [log] > main stream:KEY_LOADING->IDLE
hls.js?ba56:16977 [log] > Loading 1 of [1 ,1],level 0, currentTime:0.000,bufferEnd:0.000
hls.js?ba56:16977 [log] > demuxing in webworker
hls.js?ba56:16977 [log] > main stream:IDLE->FRAG_LOADING
hls.js?ba56:16977 [log] > Loaded 1 of [1 ,1],level 0
hls.js?ba56:16977 [log] > Parsing 1 of [1 ,1],level 0, cc 0
hls.js?ba56:16977 [log] > main stream:FRAG_LOADING->PARSING
hls.js?ba56:16977 [log] > main:discontinuity detected
hls.js?ba56:16977 [log] > main:switch detected
0953785e-3bdc-4316-a1ab-439270b840de:499 [log] > JS AES decrypt
index.js?a796:72 FRAGMENT DECRYPTED
index.js?a796:73 {stats: {…}, frag: Fragment, id: "main"}frag: FragmentautoLevel: truebaseurl: "https://url_to_level_playlist"bitrateTest: undefinedbyteRange: (...)byteRangeEndOffset: (...)byteRangeStartOffset: (...)cc: 0decryptdata: (...)duration: 9encrypted: (...)endProgramDateTime: (...)level: 0levelkey: LevelKey {method: "AES-128", key: Uint8Array(32), iv: Uint8Array(16), _uri: "https://api.blackdove.io/hls/authorize", baseuri: "https://url_to_level_playlist", …}loaded: 1839024loader: undefinedprogramDateTime: nullrawProgramDateTime: nullrelurl: "artwork_360_00001.ts"sn: 1start: 0tagList: [Array(2)]title: nulltype: "main"url: (...)urlId: 0_byteRange: null_decryptdata: LevelKey {method: "AES-128", key: Uint8Array(32), iv: Uint8Array(16), _uri: "https://api.blackdove.io/hls/authorize", baseuri: "https://url_to_level_playlist", …}_elementaryStreams: {audio: false, video: false}_url: "https://url_to_fragment"__proto__: Objectid: "main"stats: tdecrypt: 887.1250000083819tstart: 849.1200000280514__proto__: Object__proto__: Object
index.js?a796:72 FRAGMENT DECRYPTED
index.js?a796:73 {stats: {…}, frag: Fragment, id: "main"}frag: FragmentautoLevel: truebaseurl: "https://url_to_level_playlist"bitrateTest: undefinedbyteRange: (...)byteRangeEndOffset: (...)byteRangeStartOffset: (...)cc: 0decryptdata: (...)duration: 9encrypted: (...)endProgramDateTime: (...)level: 0levelkey: LevelKey {method: "AES-128", key: Uint8Array(32), iv: Uint8Array(16), _uri: "https://api.blackdove.io/hls/authorize", baseuri: "https://url_to_level_playlist", …}loaded: 1839024loader: undefinedprogramDateTime: nullrawProgramDateTime: nullrelurl: "artwork_360_00001.ts"sn: 1start: 0tagList: [Array(2)]title: nulltype: "main"url: (...)urlId: 0_byteRange: null_decryptdata: LevelKey {method: "AES-128", key: Uint8Array(32), iv: Uint8Array(16), _uri: "https://api.blackdove.io/hls/authorize", baseuri: "https://url_to_level_playlist", …}_elementaryStreams: {audio: false, video: false}_url: "https://url_to_fragment"__proto__: Objectid: "main"stats: tdecrypt: 887.1250000083819tstart: 849.1200000280514__proto__: Object__proto__: Object
index.js?a796:108 {type: "mediaError", details: "fragParsingError", fatal: true, reason: "no demux matching with content found", frag: Fragment, …}details: "fragParsingError"fatal: truefrag: FragmentautoLevel: truebaseurl: "https://url_to_level_playlist"bitrateTest: undefinedbyteRange: (...)byteRangeEndOffset: (...)byteRangeStartOffset: (...)cc: 0decryptdata: (...)duration: 9encrypted: (...)endProgramDateTime: (...)level: 0levelkey: LevelKey {method: "AES-128", key: Uint8Array(32), iv: Uint8Array(16), _uri: "https://api.blackdove.io/hls/authorize", baseuri: "https://url_to_level_playlist", …}loaded: 1839024loader: undefinedprogramDateTime: nullrawProgramDateTime: nullrelurl: "artwork_360_00001.ts"sn: 1start: 0tagList: [Array(2)]title: nulltype: "main"url: (...)urlId: 0_byteRange: null_decryptdata: LevelKey {method: "AES-128", key: Uint8Array(32), iv: Uint8Array(16), _uri: "https://api.blackdove.io/hls/authorize", baseuri: "https://url_to_level_playlist", …}_elementaryStreams: {audio: false, video: false}_url: "https://url_to_fragment"__proto__: Objectid: "main"reason: "no demux matching with content found"type: "mediaError"__proto__: Object
index.js?a796:108 {type: "mediaError", details: "fragParsingError", fatal: true, reason: "no demux matching with content found", frag: Fragment, …}details: "fragParsingError"fatal: truefrag: FragmentautoLevel: truebaseurl: "https://url_to_level_playlist"bitrateTest: undefinedbyteRange: (...)byteRangeEndOffset: (...)byteRangeStartOffset: (...)cc: 0decryptdata: (...)duration: 9encrypted: (...)endProgramDateTime: (...)level: 0levelkey: LevelKey {method: "AES-128", key: Uint8Array(32), iv: Uint8Array(16), _uri: "https://api.blackdove.io/hls/authorize", baseuri: "https://url_to_level_playlist", …}loaded: 1839024loader: undefinedprogramDateTime: nullrawProgramDateTime: nullrelurl: "artwork_360_00001.ts"sn: 1start: 0tagList: [Array(2)]title: nulltype: "main"url: (...)urlId: 0_byteRange: null_decryptdata: LevelKey {method: "AES-128", key: Uint8Array(32), iv: Uint8Array(16), _uri: "https://api.blackdove.io/hls/authorize", baseuri: "https://url_to_level_playlist", …}_elementaryStreams: {audio: false, video: false}_url: "https://url_to_fragment"__proto__: Objectid: "main"reason: "no demux matching with content found"type: "mediaError"__proto__: Object

And here is the full error data with fragment data included. This is a test encryption key.

{
  "type": "mediaError",
  "details": "fragParsingError",
  "fatal": true,
  "reason": "no demux matching with content found",
  "frag": {
    "_url": "https://fragment_url",
    "_byteRange": null,
    "_decryptdata": {
      "method": "AES-128",
      "key": {
        "0": 55,
        "1": 48,
        "2": 51,
        "3": 53,
        "4": 53,
        "5": 101,
        "6": 98,
        "7": 48,
        "8": 102,
        "9": 48,
        "10": 98,
        "11": 49,
        "12": 57,
        "13": 57,
        "14": 49,
        "15": 50,
        "16": 53,
        "17": 56,
        "18": 101,
        "19": 53,
        "20": 99,
        "21": 52,
        "22": 50,
        "23": 53,
        "24": 51,
        "25": 52,
        "26": 54,
        "27": 48,
        "28": 98,
        "29": 55,
        "30": 54,
        "31": 100
      },
      "iv": {
        "0": 0,
        "1": 0,
        "2": 0,
        "3": 0,
        "4": 0,
        "5": 0,
        "6": 0,
        "7": 0,
        "8": 0,
        "9": 0,
        "10": 0,
        "11": 0,
        "12": 0,
        "13": 0,
        "14": 0,
        "15": 1
      },
      "_uri": "https://auth_url",
      "baseuri": "https://level_playlist_m3u8_url",
      "reluri": "https://auth_url"
    },
    "tagList": [
      [
        "INF",
        "9"
      ]
    ],
    "programDateTime": null,
    "rawProgramDateTime": null,
    "_elementaryStreams": {
      "audio": false,
      "video": false
    },
    "duration": 9,
    "title": null,
    "type": "main",
    "start": 0,
    "levelkey": {
      "method": "AES-128",
      "key": {
        "0": 55,
        "1": 48,
        "2": 51,
        "3": 53,
        "4": 53,
        "5": 101,
        "6": 98,
        "7": 48,
        "8": 102,
        "9": 48,
        "10": 98,
        "11": 49,
        "12": 57,
        "13": 57,
        "14": 49,
        "15": 50,
        "16": 53,
        "17": 56,
        "18": 101,
        "19": 53,
        "20": 99,
        "21": 52,
        "22": 50,
        "23": 53,
        "24": 51,
        "25": 52,
        "26": 54,
        "27": 48,
        "28": 98,
        "29": 55,
        "30": 54,
        "31": 100
      },
      "iv": {
        "0": 0,
        "1": 0,
        "2": 0,
        "3": 0,
        "4": 0,
        "5": 0,
        "6": 0,
        "7": 0,
        "8": 0,
        "9": 0,
        "10": 0,
        "11": 0,
        "12": 0,
        "13": 0,
        "14": 0,
        "15": 1
      },
      "_uri": "https://auth_url",
      "baseuri": "https://level_playlist_m3u8_url",
      "reluri": "https://auth_url"
    },
    "sn": 1,
    "level": 0,
    "cc": 0,
    "urlId": 0,
    "baseurl": "https://level_playlist_m3u8_url",
    "relurl": "artwork_360_00001.ts",
    "autoLevel": true,
    "loaded": 1839024
  },
  "id": "main"
}
@kuuroro
Copy link

kuuroro commented Nov 13, 2019

the same issue

@stale
Copy link

stale bot commented Jan 12, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the Stale label Jan 12, 2020
@stale stale bot closed this as completed Feb 11, 2020
@elv-peter
Copy link
Contributor

elv-peter commented Apr 9, 2020

We see what seems to be the same issue when audio is AES-128 encrypted. I believe there's a race condition during initialization where an audio decryption error sometimes occurs, depending on the order of the following events:

  • receiving/processing the video manifest + init segment + aes key
  • receiving/processing audio manifest + init segment + aes key
  • the ABR controller deciding to switch to a different variant
  • the canceling of any of the above requests due to switching variants
  • when the decryption is done in the web worker
  • when (and how many times) the first audio segment is received

I have not pinpointed the cause, but here is the order of HTTP requests in one case where I observed the error:

  1. Received master manifest
  2. Received 1080p video manifest
  3. Received audio manifest
  4. Received 1080p video init
  5. Received audio init (request audio key)
  6. Received video key
  7. Received 360p video manifest
  8. Received audio segment 1
  9. Web worker spawned where decrypt error occurs
  10. 360p video init is canceled at some point
  11. Received 1080p video segment 1
  12. Received audio segment 1 (second time)
  13. Received audio segment 1 (third time)
  14. Request 360p video init
  15. Received audio key

Note that the audio key is not received until several requests for the first audio segment have been received.

Log snippet (full log here):

logger.js:40 [log] > main stream-controller: IDLE->FRAG_LOADING
logger.js:40 [log] > track 0 loaded [60,1524],duration:2936.6661180000497
logger.js:40 [log] > start time offset found in playlist, adjust startPosition to 0.005922
logger.js:40 [log] > Loading initSegment, cc: undefined of [60 ,1524],track 0, currentTime:0.005922,bufferEnd:0.006
logger.js:40 [log] > audio stream:IDLE->FRAG_LOADING
logger.js:40 [log] > audioTrack 0 loaded
logger.js:40 [log] > Loaded initSegment of [60 ,1527],level 4
logger.js:40 [log] > main stream-controller: FRAG_LOADING->IDLE
logger.js:40 [log] > Loading key for 60 of [60 ,1527],level 4
logger.js:40 [log] > main stream-controller: IDLE->KEY_LOADING
logger.js:40 [warn] > frag loader destroy or aborted, disarm abandonRules
logger.js:40 [log] > audio stream:FRAG_LOADING->IDLE
logger.js:40 [log] > Loading key for 60 of [60 ,1524],track 0
logger.js:40 [log] > audio stream:IDLE->KEY_LOADING
logger.js:40 [log] > main stream-controller: KEY_LOADING->IDLE
logger.js:40 [log] > switching to level 0
logger.js:40 [debug] > Loading playlist of type level, level: 0, id: 0
logger.js:40 [debug] > Calling internal loader delegate for URL: https://host-38-142-50-110.contentfabric.io/qlibs/ilib4Db4bZJWkLTvqpFqFUHhfF7rGXBm/q/hq__JoCEZvVxM27uH7yaf94gf1mMBWzybo5JXPPcBqEitMd6NHyLpzErq6vqUTSy9qqQEjXYJAYveb/rep/playout/default/hls-aes128/video/video_640x360@400000/playlist.m3u8
logger.js:40 [log] > main stream-controller: IDLE->WAITING_LEVEL
logger.js:40 [log] > audio stream:KEY_LOADING->IDLE
logger.js:40 [log] > Loading key for 60 of [60 ,1524],track 0
logger.js:40 [log] > audio stream:IDLE->KEY_LOADING
logger.js:40 [log] > audio stream:KEY_LOADING->IDLE
logger.js:40 [log] > Loading 60, cc: 0 of [60 ,1524],track 0, currentTime:0.005922,bufferEnd:0.006
logger.js:40 [log] > audio stream:IDLE->FRAG_LOADING
logger.js:40 [log] > level 0 loaded [60,1527],duration:2937.3298329999448
logger.js:40 [log] > main stream-controller: WAITING_LEVEL->IDLE
logger.js:40 [log] > Loading initSegment of [60 ,1527],level 0, currentTime:0.104,bufferEnd:0.104
logger.js:40 [log] > main stream-controller: IDLE->FRAG_LOADING
logger.js:40 [log] > audio stream:FRAG_LOADING->PARSING
logger.js:40 [log] > demuxing in webworker
logger.js:40 [log] > Demuxing 60 of [60 ,1524],track 0
logger.js:40 [log] > audio:discontinuity detected
logger.js:40 [log] > audio:switch detected
blob:http://localhost:8000/a1220b61-0939-4931-a3fc-26177733c756:562 [log] > WebCrypto AES decrypt
blob:http://localhost:8000/a1220b61-0939-4931-a3fc-26177733c756:562 [log] > WebCrypto Error, disable WebCrypto API
blob:http://localhost:8000/a1220b61-0939-4931-a3fc-26177733c756:562 [log] > JS AES decrypt
main.js:539 Error event: {type: "mediaError", details: "fragParsingError", fatal: true, reason: "no demux matching with content found", frag: Fragment, …}type: "mediaError"details: "fragParsingError"fatal: truereason: "no demux matching with content found"frag: Fragmenturl: (...)byteRange: (...)byteRangeStartOffset: (...)byteRangeEndOffset: (...)decryptdata: (...)endProgramDateTime: (...)encrypted: (...)_url: "https://host-38-142-50-110.contentfabric.io/qlibs/ilib4Db4bZJWkLTvqpFqFUHhfF7rGXBm/q/hq__JoCEZvVxM27uH7yaf94gf1mMBWzybo5JXPPcBqEitMd6NHyLpzErq6vqUTSy9qqQEjXYJAYveb/rep/playout/default/hls-aes128/audio/audio@128000/60.m4s"_byteRange: null_decryptdata: LevelKey {_uri: "https://host-38-142-50-110.contentfabric.io/qlibs/…jdpQ3hoMVAxRWVXQkgyTm1DWFBH&player_profile=hls-js", baseuri: "https://host-38-142-50-110.contentfabric.io/qlibs/…jdpQ3hoMVAxRWVXQkgyTm1DWFBH&player_profile=hls-js", reluri: "../key.bin?authorization=eyJxc3BhY2VfaWQiOiJpc3BjM…jdpQ3hoMVAxRWVXQkgyTm1DWFBH&player_profile=hls-js", method: "AES-128", key: Uint8Array(16), …}_elementaryStreams: {audio: false, video: false}deltaPTS: 0rawProgramDateTime: nullprogramDateTime: nulltitle: nulltagList: (15) [Array(1), Array(2), Array(2), Array(1), Array(2), Array(2), Array(1), Array(2), Array(2), Array(1), Array(2), Array(2), Array(2), Array(2), Array(2)]cc: 0type: "audio"relurl: "60.m4s?authorization=eyJxc3BhY2VfaWQiOiJpc3BjM0FOb1ZTek5BM1A2dDdhYkxSNjlobzVZUFBaVSIsInFsaWJfaWQiOiJpbGliNERiNGJaSldrTFR2cXBGcUZVSGhmRjdyR1hCbSIsImFkZHIiOiIweEQ0RGE5NjczMzA3RDM1ODBkNjI4OUM1QjgxZTI2ZjgxMjAxN0U1MTMiLCJxaWQiOiJpcV9fMlR4WjU3M2NWcjk1NG5YVVo3R0ZmbWZiamJ4SyIsImdyYW50IjoicmVhZCIsInR4X3JlcXVpcmVkIjpmYWxzZSwiaWF0IjoxNTg2MzcyMTU1LCJleHAiOjE1ODY0NTg1NTUsImF1dGhfc2lnIjoiRVMyNTZLXzN1M1cyeVdheHdocTZSc0FiRUVIS3ZDMVNhNDJYNmlBblJVbm5yNm82b3dENlNXR29KR05ybmNWN1NqZFZqWURyMmpMWVBjdUdwTER3ZUhYUmJndWV0a1ZOIiwiYWZnaF9wayI6IiJ9.RVMyNTZLX014MVBOamF2NHF5akJ5eFY0TmJuWVJ4UTRGUjhnZ3QxcWpNcUVzalJZRXRiOFNUbmhyYVR6a29OeEh4VmQ5R0V1eVVEbjdpQ3hoMVAxRWVXQkgyTm1DWFBH&player_profile=hls-js"baseurl: "https://host-38-142-50-110.contentfabric.io/qlibs/ilib4Db4bZJWkLTvqpFqFUHhfF7rGXBm/q/hq__JoCEZvVxM27uH7yaf94gf1mMBWzybo5JXPPcBqEitMd6NHyLpzErq6vqUTSy9qqQEjXYJAYveb/rep/playout/default/hls-aes128/audio/audio@128000/playlist.m3u8"duration: 2.005333start: 0sn: 60urlId: 0level: 0levelkey: LevelKey {_uri: "https://host-38-142-50-110.contentfabric.io/qlibs/…jdpQ3hoMVAxRWVXQkgyTm1DWFBH&player_profile=hls-js", baseuri: "https://host-38-142-50-110.contentfabric.io/qlibs/…jdpQ3hoMVAxRWVXQkgyTm1DWFBH&player_profile=hls-js", reluri: "../key.bin?authorization=eyJxc3BhY2VfaWQiOiJpc3BjM…jdpQ3hoMVAxRWVXQkgyTm1DWFBH&player_profile=hls-js", method: "AES-128", key: Uint8Array(16), …}loader: undefinedloaded: 19312__proto__: Objectid: "audio"__proto__: Object

The errors from the log:

  • "WebCrypto Error, disable WebCrypto API"
  • Error event: type: "mediaError", details: "fragParsingError", reason: "no demux matching with content found"

A side note: I don't get why the player switches variants so fast in the beginning. Shouldn't it pick one and wait for some measurements first?

@robwalch robwalch added Needs Triage If there is a suspected stream issue, apply this label to triage if it is something we should fix. and removed Stale labels Apr 9, 2020
@robwalch robwalch reopened this Apr 9, 2020
@robwalch
Copy link
Collaborator

For those of you who have participated in this issue, would you please test against https://hls-js-dev.netlify.app/demo/ and let me know if the issue persists?

If so, please provide a test stream or, at the very least complete instructions / configuration for your MediaConvert encrypted stream (TS or CMAF, audio tracks, etc...). Note that including a hosted sample stream that can be used to reproduce will help prioritize issues over those that do not. Issues without samples may not be triaged because of the level of effort required.

Recently, #3782 fixed #3772 an issue with AES-128 and AAC segments so maybe this did the trick?

@robwalch robwalch removed the Needs Triage If there is a suspected stream issue, apply this label to triage if it is something we should fix. label Aug 17, 2022
@robwalch
Copy link
Collaborator

Closing until a test stream is provided to confirm this is still reproducible.

@video-dev video-dev deleted a comment from liyuanliu1991 Feb 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants