Abdiel Soto
Abdiel Soto

Reputation: 11

Offline HLS Fairplay playback error when the app is closed, code 16227

I'm implementing Offline Playback with HLS Fairplay following the demo in the FairPlay Streaming Server SDK v4.0.1 that uses AVContentSessionKey. I download three contents, each content is downloaded and persisted correctly, both the .movpkg and its content key on the documents directory, when I turn off the WIFI these three contents downloaded plays correctly without any problems, before playing Im using this code:

let urlAsset = element.urlAsset!
ContentKeyManager.shared.contentKeySession.addContentKeyRecipient(urlAsset)
if !urlAsset.resourceLoader.preloadsEligibleContentKeys {
  urlAsset.resourceLoader.preloadsEligibleContentKeys = true
}

self.present(playerViewController, animated: true, completion: {
  AssetPlaybackManager.sharedManager.setAssetForPlayback(urlAsset)
})

So far so good. But the problem is when I close the application (Home button to close applications) and then play the downloaded contents, only the last content downloaded plays correctly, the other ones (first and second) send these error on the console.

Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed"
UserInfo={NSUnderlyingError=0x1c065d760 {Error Domain=NSOSStatusErrorDomain Code=-16227 "(null)"},
NSLocalizedFailureReason=An unknown error occurred (-16227),
NSURL=file:///private/var/mobile/Containers/Data/Application/A950D8DB-B711-47E3-AAF5-C95CC9682430/Library/com.apple.UserManagedAssets.kkG8Ih/644986_7798B8476A473F68.movpkg/, NSLocalizedDescription=The operation could not be completed}

I double check the .movpkg with the keys in the documents directory and appears correctly

/Documents/.keys/one-key
/Documents/.keys/two-key
/Documents/.keys/three-key

Before the error occurs the ContentKeyDelegate is called and the key is loaded and passed to the request correctly.

if persistableContentKeyExistsOnDisk(withContentKeyIdentifier: assetIDString) {

    let urlToPersistableKey = urlForPersistableContentKey(withContentKeyIdentifier: assetIDString)

    guard let contentKey = FileManager.default.contents(atPath: urlToPersistableKey.path) else {
        /

        pendingPersistableContentKeyIdentifiers.remove(assetIDString)
        return
    }

    /
    Create an AVContentKeyResponse from the persistent key data to use for requesting a key for
    decrypting content.
    */
    let keyResponse = AVContentKeyResponse(fairPlayStreamingKeyResponseData: contentKey)

    /
    keyRequest.processContentKeyResponse(keyResponse)

    return
}

If I print the contentKeyRecipients the three contents appears correctly

 - (lldb) po
   ContentKeyManager.shared.contentKeySession.contentKeyRecipients ▿ 3
   elements
   - 0 : AVURLAsset: 0x1c0234d40, URL = file:///private/var/mobile/Containers/Data/Application/E791A4DE-4261-46B7-A84D-D10B27035FAE/Library/com.apple.UserManagedAssets.kkG8Ih/539628_20469336224AA388.movpkg
   - 1 : AVURLAsset: 0x1c0234fa0, URL = file:///private/var/mobile/Containers/Data/Application/E791A4DE-4261-46B7-A84D-D10B27035FAE/Library/com.apple.UserManagedAssets.kkG8Ih/644986_7798B8476A473F68.movpkg
   - 2 : AVURLAsset: 0x1c42391c0, URL = file:///private/var/mobile/Containers/Data/Application/E791A4DE-4261-46B7-A84D-D10B27035FAE/Library/com.apple.UserManagedAssets.kkG8Ih/573744_62377F9549C45B93.movpkg

My tests are in iOS 11.1.2 and iOS 11.2 beta 2

I'm not sure what is happening, but seems to be a problem with the persisted key, I don't how if each content needs to be associated with one AVContentKeySession at time.

If someone faced a similar problem, any help would be appreciated.

Thanks in advance

Upvotes: 1

Views: 2892

Answers (4)

Yaroslav L'vov
Yaroslav L'vov

Reputation: 31

Make sure you set correct offline content identifier on a serverside. The identifier you set should be associated with the specific rendition/stream allowed by the license. This helped me.

Upvotes: 0

Hsiao-Ting
Hsiao-Ting

Reputation: 3526

We had encounter this error message, too. It will happen when content exceed over expiration date which set in server side.

For example :

  1. We give 10 minutes of expiration date for Video A

  2. Download this Video A, and verify CKC delivery correctly (print log)

  3. Play Video A without connection

  4. Take a break (after 11 minutes), close App, and launch App again, select Video A to Play

Show below error message from AVPlayerItem.error.description:

Error Domain=AVFoundationErrorDomain Code=-11800 
"The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-16227), 
NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x1d4257310 
{Error Domain=NSOSStatusErrorDomain Code=-16227 "(null)"}}

You can refresh encrypted data again by

  1. AVAssetResourceLoaderDelegate
  2. or use AVContentSessionKey

Reference : https://developer.apple.com/videos/play/wwdc2018/507/

Upvotes: 0

Jay M
Jay M

Reputation: 11

Which TLLV you used on the server side to specify Rental Duration of the downloaded content? Did you use Content key duration TLLV or Offline Key TLLV? If you used Offline Key TLLV you need to double check that "Content ID" field is different for every downloaded movie.

Upvotes: 1

noc
noc

Reputation: 86

I'm having similar issue.

however, since I need to support iOS 10, I'm not using the new AVContentKeyResponse class. Instead, I'm loading the persistent content key myself, and pass it to the loading request.

Anyway, I'm getting exact the same error as you and same behavior. One thing to note is that if I remove the code that loads persistent content key from disk, and always fetch the key from server, then everything works. But this defeats the purpose of "offline" playback...

So it seems like the system thinks the persistent content key is invalid...

Upvotes: 1

Related Questions