AVContentKeySessionDelegate not called (offline)

I've implemented the AVContentKeySession APIs in my app.

This app downloads FairPlay protected streams, and plays them later.


In a particular session of the app:

  1. The user downloads a FairPlay stream
  2. The app calls contentKeySession.processContentKeyRequest(withIdentifier: skdURL, initializationData: nil, options: nil) to initiate the license acquisition process
  3. The relevant AVContentKeySessionDelegate methods are called and the license acquisition completes
  4. The user can play offline.


For testing purposes, we set the rental duration (on the KSM) to 5 minutes. After 5 minutes playback fails (as expected).

  1. The app tries to renew the license by calling contentKeySession.processContentKeyRequest(...) again
  2. The contentKeySession(_ session: AVContentKeySession, didProvide keyRequest: AVContentKeyRequest) delegate is not called.


The AVContentKeySession object is used as a singleton, as in the HLSCatalog app, so the renew is using the same session as the initial acquisition -- not sure if it's relevant.

Replies

To renew a previously loaded key, you should use the renewExpiringResponseData(for:) method.


processContentKeyRequest(withIdentifier:initializationData:options:) is only to initiate new key loading. It is a no-op if the key was already loaded using that AVContentKeySession instance.

Hi noamtk

I have offtopic question. Can you advise me from where I can get identifier to use in processContentKeyRequest method? This should starts with "skd" and master playlist contains it but I have no idea how to get it.


Thanks

Hi BSG,


The identifiers need to be gathered out of band. There is not currently an API mechanism of retrieving those URLs.

HI TidBits

thank you for reply. Whan I was using AVAssetResourceLoadingRequest to download drm license for offline playback I was able to get identifier directly from AVAssetResourceLoadingRequest. I was doing like that:

resourceLoadingRequest.request.url.host

and it was working fine.


"To be gathered out of band" you mean to get it using AVAssetResourceLoadingRequest or read it directy from playlist?

Hi BSG,


Because AVContentKeySession is designed to decouple the timing of license requests from the actual playback itself, many apps are performing the retrieval of license key URLs via a server API so that those key requests can be done long before even requesting the playlist.


By out of band, I mean via a separte API call to the back end, as opposed to from the playlist itself.


But you could parse them out of the playlist as well, if you prefer. Or, at playback time, you can use the delegate callbacks.

In my implementation, I make sure that the key is specified in the master playlist (as recommended by Apple anyway). Then I read that playlist myself, just looking for EXT-X-SESSION-KEY tags. It looks something like this:


#EXT-X-SESSION-KEY:METHOD=...,URI="...",KEYFORMAT="...",KEYFORMATVERSIONS="..."


The URI attribute contains "skd://abc123", and abc123 is what you're looking for.

Hi @TidBits, I have another question for the offline license renewal. how to renew the stored offline license?

renewExpiringResponseData(for:) is for current playing content but for offline content we don't need play it.

is the makeSecureTokenForExpirationDate designed for that? as mentioned in the document it will create a Sync SPC. what's the sync SPC for?

The case is that I have dowloaded a content for 30 days start to play. but after 29 days I haven't started. then I want to renew the license to start in another 30 days.

Hi TidBits, another case for this question too:

If the application use license pre-delivery with processContentKeyRequest for online playback. after user playback the stream then user wants to download the same stream, how can we handle this case if processContentKeyRequest won't callback again? as this time we would request a offline persistence contentKey.