Orange-OpenSource / hasplayer.js

Http Adaptive Streaming javascript player based on HTML5 premium extensions (MSE/EME)
Other
197 stars 67 forks source link

Chrome with widevine DRM Error: Media is encrypted and no valid key is available #190

Closed ivocarminati closed 6 years ago

ivocarminati commented 7 years ago

Hi all,

I have a problem streaming protected content using widevine DRM on the latest version of Chrome (61.0.3163.79), while with all the other browsers all is working fine. When I try to stream any content, randomly I receive an error: "Media is encrypted and no valid key is available". After some stream attempts the player starts streaming correctly but I cannot understand why it has this behavior. I've notice that all the time the player raises this error in the code it passes through a "waitingforkey" event in the ProtectionModel_21Jan2015.js file, but I don't know why. I've just checked and the DRM is correctly sending to the player the license key, but it seems that something is going wrong with decryption keys. Can anyone help me solving this issue please?

Thanks.

bbert commented 7 years ago

Hi, This error is raised if "waitingforkey" event is raised once the license has been successfully received and attached to the MediaKey session and once the "usable" state for this license has been raised. Then that means the received decryption key in the license is not the good to decrypt the content.

ivocarminati commented 7 years ago

Hi @bbert ,

could you please help me with more details? How can I solve? What can I check in order to be sure that I'm doing all right and fix this issue?

Thanks a lot and best regards

bbert commented 7 years ago

Hi @ivocarminati, Can you provide access to any stream so that we can test and confirm the behavior?

ivocarminati commented 7 years ago

Hi @bbert,

unfortunately I cannot provide you any stream content for policy reasons. What I see is that the player, after the load() function, many times go in waitingForKey event, but not always. I can't understand why sometimes all is working fine and sometimes not with the same stream content. I checked and the widevine DRM is correctly sending the license also when I get the error. It seems to be an error related to timeout. In fact, if I receive the error and I reinitialize all the player flow, all works correctly after 1 or 2 attempts. For this reason I think the logic that drive me in error is contained in hasplayer library, but I cannot understand what.

bbert commented 7 years ago

Hi @ivocarminati, What you can do is to install "EME Call and Event Logger" plugin in chrome, and then send us all the logs you get in this plugin.

ivocarminati commented 7 years ago

Hi @bbert ,

thanks for your fast answers. I'll provide you the log as soon as possible.

In the meantime I need to advise you about a change I made in the hasplayer code into the CommonEncryption.js module in order to store the device id into the CDM.

I've changed the line (CommonEncryption.js module) audioCapabilities, videoCapabilities, "optional", (sessionType === "temporary") ? "optional" : "required", [sessionType])];

into this: audioCapabilities, videoCapabilities, "optional", "required", [sessionType])];

forcing the persistentState set to required.

Could the problem be caused by this change? Thanks a lot for your help.

ivocarminati commented 7 years ago

Hi @bbert ,

in attach you can see the EME log thanks to your suggestion. I hope with this log you can help me to resolve the issue.

Thanks EMELogFile.txt

dsilhavy commented 7 years ago

@ivocarminati We encountered something similar related to persistentState = required. Please see our bug report here https://bugs.chromium.org/p/chromium/issues/detail?id=690389#c4 Does your playback starts if you seek forward?

ivocarminati commented 7 years ago

Hi @bbert ,

I've tried but also seeking forward the problem appears. So, isn't there a solution to this problem with persistenState = required?

ivocarminati commented 7 years ago

Hi @dsilhavy, @bbert

do you know a solution / workaround that solve the issue?

Thanks in advance and best regards.

claudiotrameri commented 7 years ago

Hi,

I've the same issue when I set the persistentState to required Did you have any idea how to resolve it?

Thanks in advance, Regards, Claudio

ivocarminati commented 6 years ago

Hi @bbert, @dsilhavy,

I've also another problem during the stream of linear content: sometimes I get an error:

MEDIA_KEYSYSERR_ACCESS_DENIED = "No KeySystem/CDM available"

Why? Which is the possible cause? Could you help me with this problem? I cannot find a solution and I fear it is caused by the same root cause of the previous problem.

Thanks and best regards.

bbert commented 6 years ago

Which browser? It can be due to insecure origin. Can you provide conditions (browser, http/s, ...) and logs?

ivocarminati commented 6 years ago

Hi @bbert ,

the browser affected are always the same: Chrome and Mozilla Firefox. The "Access-Control-Allow-Origin" in the response headers of widevine calls is correctly set to the right domain. In attachment you can find some EME logs. I hope you can help me finding a solution.

Thanks in advance @bbert EMELogFile.txt

dsilhavy commented 6 years ago

@ivocarminati Be aware of recent changes to Chrome which require you to run your application in a secure context (https). Calling EME functions in an application from http context (despite localhost I think) will lead to problems.

ivocarminati commented 6 years ago

Hi @dsilhavy ,

I'm already running my application in a secure context https :-( For this reason I cannot undestand the root cause of these problems. The DRM is correctly sending me the right license but hasplayer seems to has some problems with sessionType = "persistent-license" and I need to solve this issue as soon as possible :(

ivocarminati commented 6 years ago

Hi @dsilhavy and @bbert,

could the problem be related to the warning I see in browser console "It is recommended that a robustness level be specified. Not specifying the robustness level could result in unexpected behavior, potentially including failure to play"??? In any case, how can I solve this warning, too?

bbert commented 6 years ago

Hi @ivocarminati, I had a look to your logs but it was huge, so difficult to locate the issue. Can you send only part of the logs when it fails? Also can you send the logs of the player? On my side I am not able to test with sessionType = "persistent-license" since I do not have access to a CDM with persistence. For robustness levels, you can try by specifying them in protData (see README and jsdoc).

ivocarminati commented 6 years ago

Hi @bbert, @dsilhavy ,

here attached the log of hasplayer in case of error. I hope this helps you find a solution for us. I do not know what to do more.

hasplayer.log

EnricoFincons commented 6 years ago

Hello, @bbert do you have any update on this topic? I'm experiencing the same issue.

bbert commented 6 years ago

Hello, If we take a look at the last logs we got from @ivocarminati, we can notice this:

[11:53:02.886][DRM] Key statuses changed. statuses = [object Object] 
[11:53:02.886][DRM][PM_21Jan2015] status = usable for KID [0x3d,0x22,0x5b,0x93,0x48,0x18,0x49,0x8f,0x9d,0x54,0x12,0xc6,0x30,0x9f,0x9c,0xee] 
[11:53:02.889][DRM][PM_21Jan2015] 'waitingforkey' event 
[11:53:02.890][Error] Code: MEDIA_ERR_ENCRYPTED, Message: Media is encrypted and no valid key is available, Data: null 

As I previously said, the player receives a license for the content (based on KID extracted from ProtectionHeader, but the received decryption key seems not to be valid/appropriate for the current content, since the CDM raises afterwards a 'waitingforkey' event after.

bbert commented 6 years ago

Question: If you disable the 'waitingforkey' event listener (comment line 216 in ProtectionModel_21Jan2015.js), is the content decrypted and played?

// videoElement.addEventListener("waitingforkey", eventHandler);

EnricoFincons commented 6 years ago

Hello. yes, we tried but the outcome is that no playback is possible (player stay as it is) We verified vs DRM and everything seems fine on their side, we are receiving the right license, so most probably it's something that is happening before the waitingforKey event is raised.

bbert commented 6 years ago

Hello If you notice no playback then it confirms that the content can not be decrypted with the received key. That's why the 'waitingforkey' event is rightly raised.

As far as I know, the only thing I can accuse is the licenser.

Have/can you check if KID indicated by CDM (status = usable for KID [...]) is the same as the KID included in ProtectionHeader, after conversion from little-endian to big-endian.

EnricoFincons commented 6 years ago

Hello Bert, we checked and they are exactly the same. We made further analysis. Accoriding to what depicted in https://www.html5rocks.com/en/tutorials/eme/basics/ "The recommended flow is to negotiate MediaKeys first, using MediaKeysSystemAccess.getConfiguration() to find out the negotiated configuration" in Hasplayer code such call is performed any time that the mediaElement identify an encrypted item and raises the event EncryptedEvent. In other players (i.e shaka) this action is performed only once. could you tell us why this is happening? We noticed that something goes wrong in here (at least from EME perspective) because I have eme log to demonstrate this. UpdateCall 14:49:20:856 target:
MediaKeySession { sessionId: 521464AA3640B2CAEE45ED23E40ADA5F expiration: null keyStatuses: Array{} } returned: Promise{}

such promise is not returned when we are getting such error and this is what we have later:

KeyStatusesChangeEvent 1:8:53:886 event:
Event { isTrusted: true } target:
MediaKeySession { sessionId: 521464AA3640B2CAEE45ED23E40ADA5F expiration: null keyStatuses: [ keyId:
80,135,228,48,221,35,69,10,189,78,248,63,6,249,219,132 status: usable] }

keyID is the same in both ok / ko status but the expiration param in case of KO si null, instead it has value for the OK scenario. If you want I can share with you the full log.

bbert commented 6 years ago

Yes please send me the full EME log

EnricoFincons commented 6 years ago

Ok, I'm going to send you the full eme log in private email (your@orange.com). is it fine?

bbert commented 6 years ago

yes, bertrand.berthelot@orange.com

ivocarminati commented 6 years ago

Hi @bbert ,

I've just tried to update the hasplayer in my project to the latest version available (v. 1.14) and I have problems to communicating with the DRM server (widevine). I need to know how to insert custom data into the request payload, because now the DRM responds with an http 500 error code (hasplayer error: "License request failed"). Is there an API in order to add this custom data?

Thanks in advance and best regards. Ivo

ivocarminati commented 6 years ago

Hi @bbert ,

I add some details to my last question. In my project I need to pass the customData below into the request payload to Widevine:

kid=guid2Str(KID) deviceAppVersion=1.1 lang=spa

Attached you can find the function I am using for building the stream object that is passed to the mediaPlayer.load(stream) function. I hope you can help me to understand how to pass those data correctly with the latest version of hasplayer.

Thanks in advance. Ivo

stream_object.txt

bbert commented 6 years ago

Hi, Since version 1.4.0 you don't need anymore to provide pssh in input protectionData. A default pssh for Widevine is automatically generated with KID extracted from smooth manifest's protection header field.

Also I am not convinced you can safely modify the license request payload since you will then corrupt it.