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

Changes in Apple FairPlay integration in 4.1.1? #4349

Closed
jakubkrolikowski opened this issue Jul 14, 2022 · 27 comments
Closed

Changes in Apple FairPlay integration in 4.1.1? #4349

jakubkrolikowski opened this issue Jul 14, 2022 · 27 comments
Assignees
Labels
flag: bot ignore Asks CI bots that maintain issues to ignore this issue type: question A question from the community

Comments

@jakubkrolikowski
Copy link

jakubkrolikowski commented Jul 14, 2022

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 jakubkrolikowski added the type: question A question from the community label Jul 14, 2022
@joeyparrish
Copy link
Member

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)?

@jakubkrolikowski
Copy link
Author

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]"

@joeyparrish
Copy link
Member

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

@stuartflanagan
Copy link

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.

@joeyparrish
Copy link
Member

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

@avelad
Copy link
Member

avelad commented Jul 28, 2022

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

@joeyparrish
Copy link
Member

No worries! Enjoy your holiday.

@joeyparrish
Copy link
Member

@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?

@stuartflanagan
Copy link

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.

@NoChance777
Copy link
Contributor

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

@fredrik-telia
Copy link
Contributor

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.

@NoChance777
Copy link
Contributor

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

@NoChance777
Copy link
Contributor

NoChance777 commented Aug 2, 2022

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"?

@fredrik-telia
Copy link
Contributor

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

I believe it was from this change: 5441f93

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.

@NoChance777
Copy link
Contributor

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!

@loicraux
Copy link
Contributor

loicraux commented Aug 4, 2022

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 !...

@joeyparrish
Copy link
Member

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 #4309 (comment), 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?

@NoChance777
Copy link
Contributor

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.

@avelad
Copy link
Member

avelad commented Aug 9, 2022

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.

@joeyparrish
Copy link
Member

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

@avelad
Copy link
Member

avelad commented Aug 11, 2022

@joeyparrish I think it would be good to include #4386 as well.

@joeyparrish
Copy link
Member

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.

@github-actions
Copy link
Contributor

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

@github-actions github-actions bot added the status: waiting on response Waiting on a response from the reporter(s) of the issue label Aug 16, 2022
@joeyparrish joeyparrish added flag: bot ignore Asks CI bots that maintain issues to ignore this issue and removed status: waiting on response Waiting on a response from the reporter(s) of the issue labels Aug 16, 2022
@joeyparrish
Copy link
Member

v4.2.0 is out now.

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

@avelad
Copy link
Member

avelad commented Aug 17, 2022

@jakubkrolikowski
Copy link
Author

@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!

@joeyparrish
Copy link
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flag: bot ignore Asks CI bots that maintain issues to ignore this issue type: question A question from the community
Projects
None yet
Development

No branches or pull requests

7 participants