shaka-player icon indicating copy to clipboard operation
shaka-player copied to clipboard

Changes in Apple FairPlay integration in 4.1.1?

Open jakubkrolikowski opened this issue 2 years ago • 19 comments

Have you read the Tutorials? yes

Have you read the FAQ and checked for duplicate open issues? yes

What version of Shaka Player are you using? 4.1.1

Please ask your question

I'm trying to upgrade from 3.3.7 to 4.1.1 and cannot make the player work with FairPlay DRM encrypted content. I get this error message after video manifest is loaded:

  "message": "Shaka Error DRM.FAILED_TO_GENERATE_LICENSE_REQUEST (The operation is not supported.,NotSupportedError: The operation is not supported.,)",
  "stack": "@https://ajax.googleapis.com/ajax/libs/shaka-player/4.1.1/shaka-player.ui.debug.js:181:806
@https://ajax.googleapis.com/ajax/libs/shaka-player/4.1.1/shaka-player.ui.debug.js:508:395
promiseReactionJob@[native code]"

My code looks like this, and it works great till 3.3.7.


const req = await fetch('https://lic.**********/license-server-fairplay/cert/*****');
      const cert = await req.arrayBuffer();

      player.configure('drm.advanced.com\\.apple\\.fps\\.1_0.serverCertificate',
                       new Uint8Array(cert));


      player.configure('drm.initDataTransform', function(initData) {
            const skdUri = shaka.util.StringUtils.fromBytesAutoDetect(initData);
            const contentId = skdUri;
            const cert = player.drmInfo().serverCertificate;
            return shaka.util.FairPlayUtils.initDataTransform(initData, contentId, cert);
        });
      
      player.getNetworkingEngine().registerResponseFilter((type, response) => {
          if (type != shaka.net.NetworkingEngine.RequestType.LICENSE) {
          return;
        }
          let responseText = shaka.util.StringUtils.fromUTF8(response.data);
          responseText = responseText.trim();
          // Look for <ckc> wrapper and remove it.
          if (responseText.substr(0, 5) === '<ckc>' &&  responseText.substr(-6) === '</ckc>' ) {
            responseText = responseText.slice(5, -6);
          }
          // Decode the base64-encoded data into the format the browser expects.
          response.data = shaka.util.Uint8ArrayUtils.fromBase64(responseText).buffer;
          }
      );
 player.getNetworkingEngine().registerRequestFilter(function(type, request) {
        if (type == shaka.net.NetworkingEngine.RequestType.LICENSE) {
          request.headers['x-dt-custom-data'] = b64;
        }
      });

I've noticed a lack of PatchedMediaKeysApple debug infos in the console, so I guess there is a significant change from 4.1. With 4.1.1 the browser console looks like this: screenshotshaka

What I'm doing wrong?

jakubkrolikowski avatar Jul 14 '22 21:07 jakubkrolikowski

I believe some code that was removed in an earlier release was restored in v4.1.2 by @avelad. We apologize for the inconvenience. Can you please try with v4.1.2 (released yesterday)?

joeyparrish avatar Jul 15 '22 17:07 joeyparrish

I tested 4.1.2 immediately early morning, unfortunately, it's not fixed, 6006 error still:

{
  "severity": 2,
  "category": 6,
  "code": 6006,
  "data": ["The operation is not supported.", {
    "name": "NotSupportedError",
    "message": "The operation is not supported.",
    "stack": ""
  }, undefined],
  "handled": false,
  "message": "Shaka Error DRM.FAILED_TO_GENERATE_LICENSE_REQUEST (The operation is not supported.,NotSupportedError: The operation is not supported.,)",
  "stack": "@https://cdn.jsdelivr.net/npm/[email protected]/dist/shaka-player.ui.debug.js:181:806
@https://cdn.jsdelivr.net/npm/[email protected]/dist/shaka-player.ui.debug.js:510:395
promiseReactionJob@[native code]"

jakubkrolikowski avatar Jul 15 '22 18:07 jakubkrolikowski

I made a mistake. It looks like that was not cherry-picked to v4.1. Can you please try with the latest nightly build?

https://nightly-dot-shaka-player-demo.appspot.com/

Or to load into your own app:

https://nightly-dot-shaka-player-demo.appspot.com/dist/shaka-player.compiled.js

joeyparrish avatar Jul 22 '22 21:07 joeyparrish

Similar issue. FairPlay does not load license server after 3.3. Have updated to 4 to trial some fixes and now not seeing any license requests and result in 7000 error. Reverting ShakaPlayer version to 3.2 returns FairPlay support.

stuartflanagan avatar Jul 23 '22 23:07 stuartflanagan

@avelad, can you take a look at this? I am not very familiar with FairPlay.

joeyparrish avatar Jul 28 '22 20:07 joeyparrish

@joeyparrish I’m on holidays until 9 August… sorry

avelad avatar Jul 28 '22 23:07 avelad

No worries! Enjoy your holiday.

joeyparrish avatar Jul 29 '22 04:07 joeyparrish

@stuartflanagan, error code 7000 is LOAD_INTERRUPTED. This should only be possible with conflicting inputs from the application (calling load, unload, detach, or destroy during an in-progress load). It's possible that some internal timing has changed and some part of your application that happened to work with v3 just happens not to work with v4. Are you awaiting the result of load() calls, or do you ignore the result?

The changes made to restore some missing FairPlay functionality are in the main branch and nightly demo build, and will be in the upcoming v4.2 release. Is anyone able to confirm that whether or not they still have issues with the main branch or nightly demo build?

joeyparrish avatar Jul 29 '22 04:07 joeyparrish

Hi @joeyparrish I will need to build the code to run it in our application. I will give it a go next week. I think you are right regarding the 7000 I will look into any un mounting of components while loading is occurring.

stuartflanagan avatar Jul 29 '22 06:07 stuartflanagan

Hello there! We recently faced the same problem with shaka v4.1.2. DRM module fails to make a request and crushes with 6006 error

NoChance777 avatar Aug 01 '22 09:08 NoChance777

I had similar issues and ended up setting useNativeHlsOnSafari: false in the shaka config object (under streaming: { )

as well as changing all instances of "com.apple.fps.1_0" to "com.apple.fps" for the drm config object.

It might not be an option for you to set useNativeHlsOnSafari to false, but if you can, it might work.

fredrik-telia avatar Aug 01 '22 11:08 fredrik-telia

Thank you @fredrik-telia. I will give it a try and let you know if your suggestion helps

NoChance777 avatar Aug 01 '22 15:08 NoChance777

So, unfortunately, the suggested solution doesn't work for me. Here is my config image

BTW, what is the difference between "com.apple.fps.1_0" and "com.apple.fps"?

NoChance777 avatar Aug 02 '22 12:08 NoChance777

BTW, what is the difference between "com.apple.fps.1_0" and "com.apple.fps"?

I believe it was from this change: https://github.com/shaka-project/shaka-player/commit/5441f932fd3da20f26da162cc0d49d0470689b41

So make sure you're running that code, I think it will be included in the upcoming 4.2.0 release, I probably should have mentioned that I had to build shaka from master in order to get drm working in Safari, sorry about that.

fredrik-telia avatar Aug 02 '22 13:08 fredrik-telia

Actually, I tried a built from the master branch as well and got another error 6007 (LICENSE_REQUEST_FAILED), but it could be related to out DRM server. Thanks again!

NoChance777 avatar Aug 02 '22 13:08 NoChance777

Guys,

FYI I had the same issue (error 6006) : after shaka-player update from 3.2.9 to 4.1.2, video playback got broken with Fairplay in Safari MacOS v15.5.

I fixed it by using key system com.apple.fps instead of com.apple.fps.1_0 AND by removing our initDataTransform function that is apparently not needed anymore.

My DRM provider is EZDRM and our legacy initDataTransform was the following :

import { util, extern } from 'shaka-player';

function assert(condition: boolean, message?: string): asserts condition {
    if (!condition) {
        // eslint-disable-next-line no-console
        console.trace();
        throw new Error(message);
    }
}

function assertIsDefined<T>(val: T, message?: string): asserts val is NonNullable<T> {
    assert(val !== undefined && val !== null, message ?? `Expected 'val' to be defined, but received ${val}`);
}

const APPLE_FAIRPLAY_KEY_SYSTEM = 'com.apple.fps.1_0';

function initDataTransform(initData: Uint8Array, initDataType: string, drmInfo: extern.DrmInfo | null): Uint8Array {
    if (drmInfo?.keySystem !== APPLE_FAIRPLAY_KEY_SYSTEM || initDataType !== 'skd') {
        return initData;
    }

    const certificate = drmInfo?.serverCertificate;
    assertIsDefined(certificate);
    const initDataAsString = util.StringUtils.fromBytesAutoDetect(initData);
    const contentId = initDataAsString.split(';').pop();
    assertIsDefined(contentId);
    return util.FairPlayUtils.initDataTransform(initData, contentId, certificate);
}

Now everything is working fine w/ version 4.1.2 on Safari MacOS v15.5 and also iOS Safari v15.4

====

A couple of off-topic sidenotes to shaka-player contributors/maintainers :

  • the DRM vendor-specific FairPlay utils/snippets that are landing into the upcoming v4.2.0 should go into documentation (or built contrib folder?) imho instead of into a separate Fairplay module that can be excluded at buildtime. Because if you need only one of the utils for your specific DRM vendor, you would still get all the other utils for other vendors, that you don't care about. Also because DRM vendor specific logic has nothing to do in shaka-player codebase in my opinion.
  • Greater modularity using ESM modules would be welcome, yes. Especially when you pull shaka-player from a NPM dependency and you'd like to include less parts from it in your own bundle. When your tooling is webpack/typescript/npm, shaka-player feels a bit exotic :) with the python build, no TS typings, ... E.g. to include an unminified/formatted debug version of shaka-player in my development bundle, today I have a webpack alias for resolution of 'shaka-player' that points to a temporary file that is the formatted version of node_modules/shaka-player/dist/shaka-player.compiled.debug.js using prettier formatter (only created if SHA checksum of node_modules/shaka-player/dist/shaka-player.compiled.debug.js has changed). It works but a bit convoluted :) I guess I could spawn a python build from the webpack script but this also requires all the python/closure tooling to be installed ...

These were my two cents :) ... Otherwise thank you for the great work !...

loicraux avatar Aug 04 '22 11:08 loicraux

We are aware of the modularity problem, and it's a problem in some cases for us at Google, too. Expect to see some work on that in Q1 or Q2 2023. We've been building on this structure for over six years now, so it's not trivial to undo that. The results will likely spawn a Shaka v5, since I don't think it's feasible to do it in a backward compatible way.

As for the inclusion of FairPlayUtils vs moving to docs/contrib, we debated that in https://github.com/shaka-project/shaka-player/pull/4309#discussion_r904176052, and this was the conclusion that @avelad, @littlespex and I ended up at. If you want to exclude them, you may do that at build time in a custom build. We understand that's not ideal for everyone. The good news is that the compiled version of FairPlayUtils currently only adds 1998 bytes to the build.

Thanks @loicraux for the pointers:

  • use key system com.apple.fps instead of com.apple.fps.1_0
  • remove initDataTransform

@jakubkrolikowski, do these tips help?

joeyparrish avatar Aug 05 '22 21:08 joeyparrish

Hi @joeyparrish! I followed suggested hints, and Shaka's behavior become even stranger. In most cases the player gives 3016 error, but occasionally it plays a live stream. The only working solution for us at the moment is using PatchedMediaKeysApple polyfill.

NoChance777 avatar Aug 09 '22 07:08 NoChance777

All this, in 4.2 will be solved since it is allowed to use the modern API and the legacy. We have to see if we can speed up 4.2 to avoid these issues. As soon as I get some time, I'll talk to @joeyparrish about this.

avelad avatar Aug 09 '22 08:08 avelad

I'll start preparing for bugfix releases and also v4.2. Sorry for the delay!

joeyparrish avatar Aug 11 '22 18:08 joeyparrish

@joeyparrish I think it would be good to include https://github.com/shaka-project/shaka-player/pull/4386 as well.

avelad avatar Aug 11 '22 19:08 avelad

I agree, but I'll need to check in with @theodab to see when that will be ready to merge. Hopefully it will be ready soon and we won't have to delay v4.2 to include it.

joeyparrish avatar Aug 12 '22 00:08 joeyparrish

@jakubkrolikowski Does this answer all your questions? If so, would you please close the issue?

github-actions[bot] avatar Aug 16 '22 00:08 github-actions[bot]

v4.2.0 is out now.

If you need to reopen this issue, just put @shaka-bot reopen in a comment. Thanks!

joeyparrish avatar Aug 17 '22 01:08 joeyparrish

Please see https://shaka-player-demo.appspot.com/docs/api/tutorial-fairplay.html

avelad avatar Aug 17 '22 10:08 avelad

@joeyparrish I just checked version 4.2.0 and applied these two changes:

  • use key system com.apple.fps instead of com.apple.fps.1_0
  • remove initDataTransform

and everything works very well, the problem is solved! Thank you!

jakubkrolikowski avatar Aug 17 '22 21:08 jakubkrolikowski

Awesome, I'm so glad to hear it! Thanks to @avelad for working on this!

joeyparrish avatar Aug 17 '22 21:08 joeyparrish