Cache HLS video while playing with AVAssetDownloadTask

1.5k views Asked by At

I am trying cache an HLS stream while I am playing it. I was following the Apple documentation on this (the section Playing Offline Assets):

https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MediaPlaybackGuide/Contents/Resources/en.lproj/HTTPLiveStreaming/HTTPLiveStreaming.html#//apple_ref/doc/uid/TP40016757-CH11-SW1

I've implemented the following method - which should make my HLS streams download while playing:

func downloadAndPlayAsset(_ asset: AVURLAsset) {
    // Create new AVAssetDownloadTask for the desired asset
    // Passing a nil options value indicates the highest available bitrate should be downloaded
    let downloadTask = downloadSession.makeAssetDownloadTask(asset: asset,
                                                             assetTitle: assetTitle,
                                                             assetArtworkData: nil,
                                                             options: nil)!
    // Start task
    downloadTask.resume()

    // Create standard playback items and begin playback
    let playerItem = AVPlayerItem(asset: downloadTask.urlAsset)
    player = AVPlayer(playerItem: playerItem)
    player.play()
}

The problem is it just doesn't download the video, only plays the stream. I've also implemented the delegates, but then none of them get called:

func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didLoad timeRange: CMTimeRange, totalTimeRangesLoaded loadedTimeRanges: [NSValue], timeRangeExpectedToLoad: CMTimeRange)

func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didFinishDownloadingTo location: URL)

func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)

Rather strangely, I noticed that the next time I open the app, the assetDownloadURLSession.getAllTasks returns pending tasks for my downloads from the last session. So it doesn't download the streams but it does add them to a pending queue. Do you know what would be the rationale behind that? I had a theory that the stream being downloaded and the live stream use different quality so it does need to be redownloaded in the right quality. So I created an HLS stream for testing with just one quality but the result is still the same.

If I remove the lines assigning the AVPlayerItem to AVPlayer the download starts and all the delegates gets called. So the download on its own work, but anytime I try to play it just stops.

Thanks for help!

Tomas

2

There are 2 answers

4
Chan Gu On

Did that happened on iOS13 or newer? https://forums.developer.apple.com/thread/121097 If so, we met the same problem maybe, and Apple just hasn't given us any hits

3
M. LeRouge On

I had a theory that the stream being downloaded and the live stream use different quality so it does need to be redownloaded in the right quality.

Your theory is correct.

So the download on its own work, but anytime I try to play it just stops.

The download will be deferred until the AVPlayerItem is terminated. Try calling player.replaceCurrentItem(nil).