I am using AVQueuePlayer to play the items in a queue in my app. So when there are suppose 10 items to add to queue, I simply use a for loop to add them to queue. Most of the time it works fine but sometimes it freezes the whole app. Thread always hangs here let asset = AVURLAsset(url: url), then freeze
Here is my code -
func loadAssets() {
let URLS = ["http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4","http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4","http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4","http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4"]
for urlString in URLS {
let contentURL = URL(string: urlString)!
self.createAVAsset(url: contentUrl, completion: ({ [weak self] asset in
guard let self = self else { return }
let playerItem = self.createPlayerItemForAsset(asset)
self.queuePlayer?.insert(playerItem, after: nil)
}))
}
}
func createAVAsset(url: URL, completion: @escaping ((AVURLAsset) -> Void)) {
let asset = AVURLAsset(url: url) /*THREAD HANGS ON THIS LINE*/
asset.resourceLoader.setDelegate(self, queue: self.queue)
completion(asset)
}
I have tried many different things in the method createAVAsset but nothing happened also this happens all of a sudden not reproducible each time.
Varients I tried to fix the issue are -
- Using background thread - Not working properly
func createAVAsset(url: URL, completion: @escaping ((AVURLAsset) -> Void)) {
DispatchQueue.global(qos: .background).async { [weak self] in
guard let self = self else { return }
let asset = AVURLAsset(url: url) /*THREAD HANGS ON THIS LINE*/
asset.resourceLoader.setDelegate(self, queue: self.queue)
DispatchQueue.main.async {
completion(asset)
}
}
}
- Using loadValuesAsynchronously - Not working properly
func createAVAsset(url: URL, completion: @escaping ((AVURLAsset) -> Void)) {
let asset = AVURLAsset(url: url) /*THREAD HANGS ON THIS LINE*/
let keys: [String] = ["playable"]
//Control doesn't reach below, it hangs on above line already
asset.loadValuesAsynchronously(forKeys: keys, completionHandler: {
var error: NSError? = nil
let status = asset.statusOfValue(forKey: "playable", error: &error)
switch status {
case .loaded:
DispatchQueue.main.async {
//do something, show alert, put a placeholder image etc.
completion(asset)
}
break
case .failed:
DispatchQueue.main.async {
//do something, show alert, put a placeholder image etc.
}
break
case .cancelled:
DispatchQueue.main.async {
//do something, show alert, put a placeholder image etc.
}
break
default:
break
}
})
}