Question

i am developing an app where the music is played via AVPlayer using songs from a cloud service. everything works fine and most of the files are playing without any issues.

i have recently been getting an error back from specific files and with the message coming from AVPlayer i can't figure out if it's a network communication issue or the encoding of the file itself:

Error Domain=AVFoundationErrorDomain Code=-11819 "Cannot Complete Action" UserInfo=0x176abd80 {NSLocalizedRecoverySuggestion=Try again later., NSLocalizedDescription=Cannot Complete Action}

looking through the documentation I found out that code 11819 means:

AVErrorMediaServicesWereReset - The operation could not be completed because media services became unavailable.

has anyone ever experienced this before?

Was it helpful?

Solution

I found the solution by using the following method before loading the AVURLAsset to AVPlayerItem

  • (void)loadValuesAsynchronouslyForKeys:(NSArray *)keys completionHandler:(void (^)(void))handler

The reason why it was crashing in specific tracks was because some of them where mp3 files and they don't have all the information about the song immediately available (e.g. duration).

OTHER TIPS

As was stated, the keys are properties on AVAsset. Apple says in its docs that you should always use this in iOS (but I doubt its needed for file based videos).

I struggled with this, in the end it didn't matter - but in any case maybe this will help someone in the future:

    asset = AVAsset(url: videoURL)
    let keys = ["duration", "playable", "preferredRate", "preferredVolume", "hasProtectedContent", "providesPreciseDurationAndTiming", "metadata"]
        asset.loadValuesAsynchronously(forKeys: keys) {
        for key in keys {
            var error: NSError? = nil
            let status = self.asset.statusOfValue(forKey: key, error: &error)
            print("KEY:", key, terminator: "")
            switch status {
            case .loading:
                print("  Loading")
            case .loaded:
                print("  Sucessfully loaded, continue processing")
            case .failed:
                print("  Failed with error \(error!)")
            case .cancelled:
                print("  CANCELLED")
            case .unknown:
                print("  Unknown")
            default:
                print("  DEFAULT")
            }
        }
        print("WAIT A BIT...")
        DispatchQueue.main.async {
            print("...RUN IT")
            self.runMovie()
        }
    }

The same solution works also for playing movies. If you experience Cannot Complete Action error using mp4 asset, just add:

asset.loadValuesAsynchronously(forKeys: ["metadata"]) {
    self.runMovie()
}

before loading AVURLAsset to AVPlayerItem

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top