I am following Apple's documentation on caching HLS (.m3u8) video.
https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MediaPlaybackGuide/Contents/Resources/en.lproj/HTTPLiveStreaming/HTTPLiveStreaming.html
Under Playing Offline Assets in the documentation, it is instructed to use AVAssetDownloadTask's asset to simultaneously start playing.
The issue is that the same asset is downloaded twice.
Right after AVPlayer is initialized it starts to buffer the asset. Initially, I assumed that the data from the buffer must be used to create cache but AVAssetDownloadTask doesn't start to download the data for caching until AVPlayer finishes playing the asset. The buffered data is basically discarded.
I used KVO on currentItem.loadedTimeRanges to check state of buffer.
Below method to check the downloading status of AVAssetDownloadTask.
Is this the right behaviour or am I doing something wrong? I want to be able to use the video data that is being cached (AVAssetDownloadTask downloading is in progress) to play in AVPlayer.
https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MediaPlaybackGuide/Contents/Resources/en.lproj/HTTPLiveStreaming/HTTPLiveStreaming.html
Under Playing Offline Assets in the documentation, it is instructed to use AVAssetDownloadTask's asset to simultaneously start playing.
Code Block func downloadAndPlayAsset(_ asset: AVURLAsset) { let downloadTask = downloadSession.makeAssetDownloadTask(asset: asset, assetTitle: assetTitle, assetArtworkData: nil, options: nil)! downloadTask.resume() let playerItem = AVPlayerItem(asset: downloadTask.urlAsset). player = AVPlayer(playerItem: playerItem) player.play() }
The issue is that the same asset is downloaded twice.
Right after AVPlayer is initialized it starts to buffer the asset. Initially, I assumed that the data from the buffer must be used to create cache but AVAssetDownloadTask doesn't start to download the data for caching until AVPlayer finishes playing the asset. The buffered data is basically discarded.
I used KVO on currentItem.loadedTimeRanges to check state of buffer.
Code Block playerTimeRangesObserver = currentPlayer.observe(\.currentItem?.loadedTimeRanges, options: [.new, .old]) { (player, change) in let time = self.currentPlayer.currentItem?.loadedTimeRanges.firs. if let t = time { print(t.timeRangeValue.duration.seconds) } }
Below method to check the downloading status of AVAssetDownloadTask.
Code Block // Method to adopt to subscribe to progress updates of an AVAssetDownloadTask. func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didLoad timeRange: CMTimeRange, totalTimeRangesLoaded loadedTimeRanges: [NSValue], timeRangeExpectedToLoad: CMTimeRange) { // This delegate callback should be used to provide download progress for your AVAssetDownloadTask. guard let asset = activeDownloadsMap[assetDownloadTask] else { return } var percentComplete = 0.0 for value in loadedTimeRanges { let loadedTimeRange: CMTimeRange = value.timeRangeValue percentComplete += loadedTimeRange.duration.seconds / timeRangeExpectedToLoad.duration.seconds } print("PercentComplete for \(asset.stream.name) = \(percentComplete)") }
Is this the right behaviour or am I doing something wrong? I want to be able to use the video data that is being cached (AVAssetDownloadTask downloading is in progress) to play in AVPlayer.