Closed ghost closed 9 months ago
After some more digging I can confirm that HLS with AES-128 encryption appears to be broken, even if I directly provide the key as a file the hls.js player will fall into fatal error state. Can please somebody validate this.
The demo page AES-128 assets are playing back fine without any exceptions.
What is the internalException you are experiencing (what code is throwing, where)?
The stack trace should be printed out in the dev console. You can find the exception by enabling "pause on caught exceptions" in the debugger. Or, disable debugging for it to not be caught (assuming it's thrown in an event callback or your xhrSetup callback).
Can you share a page or codepen that reproduces the issue?
@robwalch, that's good to hear ^^ Well, I already pasted the debug output, or what did you mean? Sadly, this is all I've got. If I skip through the exception using "Pause on caught exceptions" in my Chrome browser, it stops at several places, but I'm not sure where to look at. Putting this at CodePen isn't possible due to several reasons, especially because of using licensed software components. But I can share my video-player-component.ts setup, please see this paste:
Thanks in advance
I now checked my stream against the demo page of hls.js -> https://hlsjs.video-dev.org/demo
But also here the stream won't play, despite that I disabled all JWT authentication, the segments getting pulled, the key also but no playback, it basically stops with the following error:
Error event:
Object { type: "otherError", details: "internalException", err: RangeError, error: RangeError, fatal: true }
details: "internalException"
err: RangeError: offset is outside the bounds of the DataView
error: RangeError: offset is outside the bounds of the DataView
columnNumber: 28
fileName: "https://hlsjs.video-dev.org/dist/hls.js"
lineNumber: 9019
message: "offset is outside the bounds of the DataView"
stack: "uint8ArrayToUint32Array_@https://hlsjs.video-dev.org/dist/hls.js:9019:28\ndecrypt@https://hlsjs.video-dev.org/dist/hls.js:9163:29\nsoftwareDecrypt@https://hlsjs.video-dev.org/dist/hls.js:9340:46\npush@https://hlsjs.video-dev.org/dist/hls.js:15065:41\npush@https://hlsjs.video-dev.org/dist/hls.js:16035:42\n_handleFragmentLoadProgress@https://hlsjs.video-dev.org/dist/hls.js:27717:18\nprogressCallback@https://hlsjs.video-dev.org/dist/hls.js:9641:16\n_doFragLoad/result<@https://hlsjs.video-dev.org/dist/hls.js:9948:29\npromise callback*_doFragLoad@https://hlsjs.video-dev.org/dist/hls.js:9945:130\n_loadFragForPlayback@https://hlsjs.video-dev.org/dist/hls.js:9643:12\nloadFragment@https://hlsjs.video-dev.org/dist/hls.js:9630:12\nloadFragment@https://hlsjs.video-dev.org/dist/hls.js:27444:56\ndoTickIdle@https://hlsjs.video-dev.org/dist/hls.js:27430:12\ndoTick@https://hlsjs.video-dev.org/dist/hls.js:27320:14\ntick@https://hlsjs.video-dev.org/dist/hls.js:7870:14\nsetInterval handler*setInterval@https://hlsjs.video-dev.org/dist/hls.js:7832:35\nstartLoad@https://hlsjs.video-dev.org/dist/hls.js:27247:14\nstartLoad/<@https://hlsjs.video-dev.org/dist/hls.js:28577:20\nstartLoad@https://hlsjs.video-dev.org/dist/hls.js:28576:31\nfilterAndSortMediaOptions@https://hlsjs.video-dev.org/dist/hls.js:26308:18\nonManifestLoaded@https://hlsjs.video-dev.org/dist/hls.js:26168:12\nemit@https://hlsjs.video-dev.org/dist/hls.js:15542:36\nemit@https://hlsjs.video-dev.org/dist/hls.js:28464:28\ntrigger@https://hlsjs.video-dev.org/dist/hls.js:28468:21\nhandleMasterPlaylist@https://hlsjs.video-dev.org/dist/hls.js:4264:11\nonSuccess@https://hlsjs.video-dev.org/dist/hls.js:4202:19\nreadystatechange@https://hlsjs.video-dev.org/dist/hls.js:25267:28\nEventHandlerNonNull*openAndSendXhr@https://hlsjs.video-dev.org/dist/hls.js:25204:54\nloadInternal@https://hlsjs.video-dev.org/dist/hls.js:25185:14\nload@https://hlsjs.video-dev.org/dist/hls.js:25151:12\nload@https://hlsjs.video-dev.org/dist/hls.js:4215:14\nonManifestLoading@https://hlsjs.video-dev.org/dist/hls.js:4068:12\nemit@https://hlsjs.video-dev.org/dist/hls.js:15542:36\nemit@https://hlsjs.video-dev.org/dist/hls.js:28464:28\ntrigger@https://hlsjs.video-dev.org/dist/hls.js:28468:21\nloadSource@https://hlsjs.video-dev.org/dist/hls.js:28558:12\nloadSelectedStream@https://hlsjs.video-dev.org/dist/hls-demo.js:24456:8\napplyConfigEditorValue@https://hlsjs.video-dev.org/dist/hls-demo.js:25492:4\nonclick@https://hlsjs.video-dev.org/demo/?src=https%3A%2F%2Fpath_to_my_m3u8_file&demoConfig=eyJlbmFibGVTdHJlYW1pbmciOnRydWUsImF1dG9SZWNvdmVyRXJyb3IiOnRydWUsInN0b3BPblN0YWxsIjp0cnVlLCJkdW1wZk1QNCI6ZmFsc2UsImxldmVsQ2FwcGluZyI6LTEsImxpbWl0TWV0cmljcyI6LTF9:1:1\n"
<prototype>: RangeError.prototype { stack: "", … }
constructor: function RangeError()
length: 1
name: "RangeError"
prototype: RangeError.prototype { stack: "", … }
constructor: function RangeError()
message: ""
name: "RangeError"
stack: ""
<prototype>: Error.prototype { stack: "", … }
<prototype>: function Error()
message: ""
name: "RangeError"
stack: ""
<prototype>: Error.prototype { stack: "", … }
fatal: true
type: "otherError"
<prototype>: Object { … }
main.js:734:12
This is how I encrypt my segments using python:
exec_command(
f'openssl aes-128-cbc '
f'-e -in "{old_full_segment_path}" -out "{new_full_segment_path}" '
f'-nosalt -iv {enc_iv} -K {enc_key}'
)
I do this for all segments except the init-segment, this will stay unencrypted
I also noticed the following at the hls.js demo page, if I check out the m3u8 playlists here:
Why do some of these streams have an Initialization vector and others don't ???
Tried with the test: "AES-128 encrypted, ABR"
Maybe I should also notice that I only use fmp4 (.m4s segments), not .ts segments.
Have you tried setting enableSoftwareAES
to false
?
Why do some of these streams have an Initialization vector and others don't ???
Those fall back to using the segments' media sequence number as the IV. (It's an older convention of the HLS spec.)
@robwalch Yes, I also tried that, but I'm currently onto something:
Take a look at this:
the stream is not mine, but I was able to detect a difference at the EXT-X-KEY line of the playlist, as you can see here:
https://d12zt1n3pd4xhr.cloudfront.net/dev/aes128m4s/360p.m3u8
Could it be that hlsjs expects the IV to be a hex string ? because in my playlist its not a hex string, but this is fixable, what do you think ?
What's also kinda funny, is that fact when switching these two lines:
over to :
If I first reference the key, I get a segment decryption error, but not :
HLS.js error: otherError - fatal: true - internalException
as before ...
Could it be that hlsjs expects the IV to be a hex string ?
Yes.
In m3u8-parser:
const decryptiv = keyAttrs.hexadecimalInteger('IV');
From the HLS spec:
IV The value is a hexadecimal-sequence that specifies a 128-bit unsigned integer Initialization Vector to be used with the key.
because in my playlist its not a hex string, bit this is fix able
What is it?
Huraaaaaaaaaaa! Exactly that was the issue :D ... hls.js expect the IV to be in this format:
0x593b93926b1085cab158c02f69e5c9db
Woow, that was a ride of a bug search now xD
@robwalch Thanks for your interest in my problem ❤️ !!!
*previously it was a hex string but without the 0x indicator ...
Closed, as issue is resolved for me
What do you want to do with Hls.js?
Hello,
I would like to be able to intercept the key retrieval process.
Previously in videojs 7.21.5 I did this:
Now since I switched over to hls.js I dropped the function above in favor of this:
I can see that the Key is getting received at my browser tab and that the content is fine, but hls.js returns the following error:
HLS.js error: otherError - fatal: true - internalException
So what's the problem here? I basically have the following at my m3u8 playlists:
The reason why I have it setup using "kms://" is that it simply should act as a placeholder. In case I want to change my Domain or so. Hard-coding the URL into the playlist is kinda ugly in my opinion.
Can somebody tell me why I don't have any issue with that setup using VideoJS, but hls.js isn't working this way? I mean the xhr replace step, is basically the same, and I also get back the key from my backend as a 16 bit binary representation of the key.
This is what I get at my debug log:
At my Network tab I don't see any loading issue, not for the decryption key and also not for the segments, everything gets answered with either http200 (GET) or http204 (OPTIONS)
Thanks in advance