问题描述
我正在关注Apple关于缓存HLS(.m3u8)视频的文档。
在文档的播放脱机资产下,指示使用 avassetdownloadtask的资产同时开始播放。
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()
}
问题是同一资产被下载了两次。
在初始化AVPlayer之后,它立即开始缓冲资产。最初,我假设必须使用缓冲区中的数据来创建缓存,但是 avassetdownloadtask 不会开始下载数据进行缓存,直到AVPlayer完成播放资产为止。缓冲的数据基本上被丢弃。
我在 currentItem.loadedTimeRanges 上使用了KVO来检查缓冲区的状态。
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)
}
}
以下检查avassetdownloadtask下载状态的方法。
/// 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)")
}
这是正确的行为还是我做错了什么? 我希望能够使用正在缓存的视频数据(正在下载avassetdownloadtask)在AVPlayer中播放。
解决方法
您的 AVAssetDownloadTask 必须配置为下载与您的 AVPlayerItem 请求不同的 HLS 变体。
如果您已经通过 AVAssetDownloadTask 下载了一些数据,您的 AVPlayerItem 将随后使用它。 但是如果你已经有一些 AVPlayerItem 下载的数据,你的 AVAssetDownloadTask 可能会忽略它,因为它需要满足你下载配置的要求。