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

FairPlay KeySessionError #80

Closed
Dardaxe opened this issue Apr 11, 2019 · 29 comments
Closed

FairPlay KeySessionError #80

Dardaxe opened this issue Apr 11, 2019 · 29 comments

Comments

@Dardaxe
Copy link

Dardaxe commented Apr 11, 2019

Hi,
I'm trying to setup HLS streaming on Safari with Fairplay DRM.
Using :
Videojs 7.5.3
Videojs-contrib-eme 3.5.0
AWS MediaConvert as packager
DRMToday as DRM Provider

I can see that I'm correctly retrieving the FairPlay certificate but the request to the license server never seems to be fired.
I can see two errors in the console :
VIDEOJS: – "ERROR:" – "(CODE:5 MEDIA_ERR_ENCRYPTED)" – "The operation is not supported."
and
VIDEOJS: – "ERROR:" – "(CODE:5 MEDIA_ERR_ENCRYPTED)" – "KeySession error: code 6, systemCode 4294924646

image

Here's my implementation of GetLicense and GetCertificate :

"com.apple.fps.1_0": {
   getCertificate: function(emeOptions, callback) {
      videojs.xhr({
         url: certificateServerUrl,
         method: 'GET',
         responseType: 'arraybuffer',
         headers: {'x-dt-custom-data': some-data}
      }, (err, response, responseBody) => {
         if (err) {
            callback(err)
            return
         }
         callback(null, responseBody)
      })
  },
  getLicense: function(emeOptions, contentId, keyMessage, callback) {
     videojs.xhr({
        url: licenseServerUrl,
        method: 'POST',
        responseType: 'arraybuffer',
        body: keyMessage,
        headers: {
           'Content-type': 'application/octet-stream',
           'x-dt-custom-data': some-data
        }
     }, (err, response, responseBody) => {
         if (err) {
            callback(err)
            return
         }
         callback(null, responseBody)
       })
   }
}

Does anybody know what could be wrong or if something is missing in my implementation

@zhulduz
Copy link

zhulduz commented Apr 12, 2019

Hi, I get the same error
"ERROR:" – "(CODE:5 MEDIA_ERR_ENCRYPTED)" – "The operation is not supported."

the player correctly retrieves the FairPlay certificate, the license, segments, but this gets this error.

@bansalvks
Copy link

I am getting the same error, on production, please help
VIDEOJS: – "ERROR:" – "(CODE:5 MEDIA_ERR_ENCRYPTED)" – "The operation is not supported."

@ILanor
Copy link

ILanor commented Apr 24, 2019

Hello! When we can get fix about this issue?

@vksbansal
Copy link

is anyone reading this?

@cjveldkamp
Copy link

We have got the same issue:
With EME 3.4.1 the error is shown only in the console and playback works.
With EME 3.5 the error is shown on the screen

@misteroneill
Copy link
Member

It's hard to know exactly what's going wrong with the original reported issue, but it's not likely to be a bug with contrib-eme. That said, we have successfully implemented DRMtoday as our provider. I can't share our implementation as it's proprietary, but, looking at the original report, I noticed a few things that may be incorrect:

In getCertificate:

  1. The x-dt-auth-token header appears to be missing.
  2. You may need to disable caching via Pragma and Cache-Control headers.
  3. The callback should receive a Uint8Array not the raw responseBody (i.e. new Uint8Array(responseBody)).

In getLicense:

  1. The x-dt-auth-token header appears to be missing.
  2. We are sending Content-Type as application/x-www-form-urlencoded
  3. We are setting responseType to 'text'.
  4. We are setting the body to spc=${spcMessage}&${contentId} where the spcMessage is a URI-encoded base64 conversion of the keyMessage.
  5. It looks like we expect to see a responseBody that looks like this: <ckc>base64encoded</ckc> where we extract the base64encoded value and decode it to a Uint8Array.

I hope this helps others figure out why their integrations aren't working, but, ultimately, it's up to integration authors to understand how to communicate with their DRM vendor.

@Dardaxe
Copy link
Author

Dardaxe commented May 2, 2019

Thank you for all those information @misteroneill !

The x-dt-auth-token is only used in Upfront Authorization Method. We're using User authorization Callback and I don't think I need to provide this header (Correct me if I'm wrong).

The fact that I think it's a problem from the plugin and not from my implementation is that the second call to the DRMProvider (GetLicense) is never fired, whatever headers or body I try to provide.
However GetCertificate is correctly called and return the correct information.

When you say that you successfully managed to implement DRMtoday, are you talking about Fairplay DRM ? Because I've managed to setup VideoJS and DRMToday for Widevine easily, but Fairplay seems to be a bit more complicated.

Can I ask you which version of VideoJS and contrib-eme you're using on you're working implementation of DRMToday ?

@misteroneill
Copy link
Member

misteroneill commented May 2, 2019

The x-dt-auth-token is only used in Upfront Authorization Method. We're using User authorization Callback and I don't think I need to provide this header (Correct me if I'm wrong).

You're probably right! :)

When you say that you successfully managed to implement DRMtoday, are you talking about Fairplay DRM?

Yeah, we are using FairPlay and it is working. Our setup could be different, though. We are using the latest versions of both Video.js and contrib-eme.

@misteroneill
Copy link
Member

One thing you might consider is looking at the Dash.js source. It works seamlessly with DRMtoday out of the box.

@vksbansal
Copy link

@misteroneill
I am getting the same issue, In my case
I get
code: 5
message: "The operation is not supported."

However, playback works fine.. but I have to make a check in my error handling to ignore this error

Screenshot 2019-05-03 at 11 56 32 AM

If you could provide me with your email, then I could post you the credentials to check.

Many thanks, need your help.

@squarebracket
Copy link
Contributor

This is because of the in-spec EME support introduced by Safari 12.1 on macOS 10.14.4 and iOS 12.2.

@misteroneill
Copy link
Member

@Dardaxe @vksbansal Please try again with v3.5.4 (it is not latest on npm, but if you do npm install videojs-contrib-eme@next you'll get it).

@vksbansal
Copy link

@misteroneill yes, it's fixed in the v3.5.4
can I use this on production

@Dardaxe
Copy link
Author

Dardaxe commented May 17, 2019

@misteroneill Sorry for the late answer. Unfortunately I'm still getting the exact same error with videojs-contrib-eme v3.5.4 on Safari 12.1.
I've added logs and override getContentId method; my Fairplay configuration now looks like that :

            "com.apple.fps.1_0": {
                getCertificate: function(emeOptions, callback) {
                    console.log('Fairplay: getCertificate')

                    videojs.xhr({
                        url: DRM_PROVIDER_CERTIFICATE_URL,
                        method: 'GET',
                        responseType: 'arraybuffer',
                        headers: {
                            'x-dt-custom-data': btoa(JSON.stringify(MY_CUSTOM_DATA)),
                            'Pragma': 'no-cache',
                            'Cache-Control': 'no-cache',
                            'Content-Type': 'text/xml; charset=utf-8'
                        }
                    }, (err, response, responseBody) => {
                        if (err) {
                            callback(err)
                            return
                        }
                        console.log('Fairplay: certificate acquired')

                        callback(null, new Uint8Array(responseBody))
                    })
                },

                getContentId: function(emeOptions, initData) {
                    console.log('Fairplay: getContentId')

                    const hostname = getHostnameFromUri(uint8ArrayToString(initData))

                    console.log('Fairplay: getContentId acquired')
                    return hostname
                },

                getLicense: function(emeOptions, contentId, keyMessage, callback) {
                    console.log('Fairplay: getLicense')

                    let spcMessage = encodeURI(btoa(keyMessage))
                    videojs.xhr({
                        url: DRM_PROVIDER_LICENSE_URL,
                        method: 'POST',
                        responseType: 'text',
                        body: `spc=${spcMessage}&${contentId}`,
                        headers: {
                            'Content-type': 'application/x-www-form-urlencoded',
                            'x-dt-custom-data': btoa(JSON.stringify(MY_CUSTOM_DATA))
                        }
                    }, (err, response, responseBody) => {
                        if (err) {
                            callback(err)
                            return
                        }
                        console.log('Fairplay: License Acquired')
                        callback(null, responseBody)
                    })
                }
            }

As I said I'm still getting the same error :
image

@vksbansal Would you mindsharing your implementation of the videojs-contrib-eme plugin if it's working for you, or provide information about what could be wrong or missing on what I posted ?

@vksbansal
Copy link

@Dardaxe

I am attaching a zip which is working for me

I installed videojs-contrib-eme using below command which installed "videojs-contrib-eme": "^3.5.4",
npm i videojs-contrib-eme@next

fairplay-eme.zip

@vksbansal
Copy link

@Dardaxe @misteroneill
I am doing npm I videojs-contrib-eme@next then I am not getting the error however if I am doing a simple npm I videojs-contrib-eme then I am getting the error

@Dardaxe
Copy link
Author

Dardaxe commented May 21, 2019

Thanks for those information @vksbansal, I've created a reduced test case from the zip you provided with credentials and file from a test account :

I've got the same error on this example, getLicense is never called.

Is this example working on your side ?

  • If so can you tell me your MacOS/iOS and Safari Version as it could be a compatibility problem on my side (I'm using MacOS Mojave with Safari 12.0 and 12.1)

If this example is not working for you either :

  • My source file or integration with my DRM provider could be the problem (I'll check this again).
  • Header customization may cause troubles (very unlikely IMO)
  • getContentId might be the problem, I'm not sure about what this method have to return ...
  • ... Something I'm missing ?

@squarebracket
Copy link
Contributor

squarebracket commented May 21, 2019

@Dardaxe Unfortunately, it likely is a problem with integrating with your DRM provider. For instance, for my provider, I have to cast the keyMessage provided to getLicense to a Uint8Array.

I tried your jsbin and it didn't work with either Safari (prefix-only or prefix+spec). Even when trying with contrib-eme 3.5.0. So, unfortunately, it looks like #86 / #87 won't fix this issue.

@squarebracket
Copy link
Contributor

Because of the "The operation is not supported." error, I assumed this was due to Safari 12.1 on macOS 10.14.4 / iOS 12.2. However, since you're still getting the keySession error with eme 3.5.4, it looks like @misteroneill was right to close the issue.

Feel free to join us in the #playback channel on our slack if you'd like some more assistance with troubleshooting.

@Dardaxe
Copy link
Author

Dardaxe commented May 22, 2019

Thanks for your tests @squarebracket !

In my opinion (and I might be wrong) if the error I have is an implementation problem, either getCertificate or getLicense should throw an error during their process (as they are the only methods that interacts with my drm provider).
In my case, getCertificate is correctly called without any error but getLicense is never called.

I've made a reduced test case with logs showing that :
https://jsbin.com/ruwidurule/edit?html,console,output

Notice that in my DRM Provider Back office I can see the certificate being requested and correctly delivered :
image

The error is triggered between the getCertificate and getLicense methods.
I don't know what's being processed between those 2 methods that could potentially throw this error.

@alexanderturinske
Copy link

For anyone coming here with KeySession error: code: X, systemCode: Ys, like myself, here is some helpful information:

@alexanderturinske
Copy link

alexanderturinske commented Aug 9, 2019

@Dardaxe Did you ever solve your issue? Getting something similar, though mine switches between KeySession error: code 6, systemCode: XXXXXXXX and KeySession error: code 1, systemCode 0

On 3.5.4

@vksbansal
Copy link

This error is happening again on the latest version "videojs-contrib-eme": "3.5.0"

please resolve this issue

@alexanderturinske
Copy link

I have been working on this for awhile and the only semi-solution I have found is to hide the error with CSS in the case where a key session error will appear, but the video will still play.

Not ideal, but something.
selector: .vjs-error-display.vjs-modal-dialog style: display: none

@gkatsev
Copy link
Member

gkatsev commented Sep 11, 2019

You can pass null to player.error() to hide the error disalog.

@molten-firescar96
Copy link

I encountered this error after upgrading my MacOS 10.13 computer to MacOS 10.14. Upgrading videojs-contrib-eme to videojs-contrib-eme@3.5.4 resolved the error.

Note: I also had to set the overrideNative flag to true. This same flag broke playback on OSX 10.13.

@HankBrown
Copy link

Upgrading to 3.5.4 fails to resolve for me (mac 10.13.6) . We see this for certain films only. I am not able to determine what the difference is on the inputs, but many other films are playing without this issue. The video with the error plays, we may just need to remove the error message, as alexanderturinske and ** gkatsev** suggested. But that kind of fix is not a happy one.

@alenzalex
Copy link

I am facing this issue.

Safari Version : 13.1

When I play DRM content in safari, I get error as
KeySession error: code 6, systemCode 4294924646
with error code as : (CODE:5 MEDIA_ERR_ENCRYPTED)

Then, it displays error as
The media playback was aborted due to a corruption problem or because the media used features your browser did not support
with error code : (CODE:3 MEDIA_ERR_DECODE)

@misteroneill Sorry for the late answer. Unfortunately I'm still getting the exact same error with videojs-contrib-eme v3.5.4 on Safari 12.1.
I've added logs and override getContentId method; my Fairplay configuration now looks like that :

            "com.apple.fps.1_0": {
                getCertificate: function(emeOptions, callback) {
                    console.log('Fairplay: getCertificate')

                    videojs.xhr({
                        url: DRM_PROVIDER_CERTIFICATE_URL,
                        method: 'GET',
                        responseType: 'arraybuffer',
                        headers: {
                            'x-dt-custom-data': btoa(JSON.stringify(MY_CUSTOM_DATA)),
                            'Pragma': 'no-cache',
                            'Cache-Control': 'no-cache',
                            'Content-Type': 'text/xml; charset=utf-8'
                        }
                    }, (err, response, responseBody) => {
                        if (err) {
                            callback(err)
                            return
                        }
                        console.log('Fairplay: certificate acquired')

                        callback(null, new Uint8Array(responseBody))
                    })
                },

                getContentId: function(emeOptions, initData) {
                    console.log('Fairplay: getContentId')

                    const hostname = getHostnameFromUri(uint8ArrayToString(initData))

                    console.log('Fairplay: getContentId acquired')
                    return hostname
                },

                getLicense: function(emeOptions, contentId, keyMessage, callback) {
                    console.log('Fairplay: getLicense')

                    let spcMessage = encodeURI(btoa(keyMessage))
                    videojs.xhr({
                        url: DRM_PROVIDER_LICENSE_URL,
                        method: 'POST',
                        responseType: 'text',
                        body: `spc=${spcMessage}&${contentId}`,
                        headers: {
                            'Content-type': 'application/x-www-form-urlencoded',
                            'x-dt-custom-data': btoa(JSON.stringify(MY_CUSTOM_DATA))
                        }
                    }, (err, response, responseBody) => {
                        if (err) {
                            callback(err)
                            return
                        }
                        console.log('Fairplay: License Acquired')
                        callback(null, responseBody)
                    })
                }
            }

As I said I'm still getting the same error :
image

@vksbansal Would you mindsharing your implementation of the videojs-contrib-eme plugin if it's working for you, or provide information about what could be wrong or missing on what I posted ?

I am facing this exact issue.

@alenzalex
Copy link

alenzalex commented Jun 25, 2020

Hi @Dardaxe

In the response handler, I tried as :

     var responseData = new Uint8Array(responseBody)
     callback(null, responseData);

Also, left the header section as empty.
Now, the getLicense() call is getting invoked properly.

Attaching the code snippet :

getCertificate: function(emeOptions, callback) {
            videojs.xhr({
                uri: '<url>',
                method: 'GET',
                responseType: 'arraybuffer',
                headers: {
                }
              	}, function (err, response, responseBody) {
                      if (err) {
                         console.log('error in getCertificate')
                         callback(err);
                         return;
                  }
                  var responseData = new Uint8Array(responseBody)
                  callback(null, responseData);
              	});
      	}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests