Custom video loader caching technique
This commit brings significant improvements to the video cache feature. Previously, the cache would merely download the video when requested, in parallel with AVPlayer which also triggers a video download. The video cache has been updated to tap into the AVPlayer loading process, removing the download duplication. Here is how that works: 1. The player requests an AVAsset from the cache. 2. The cache will return a cached asset if possible, or a special AVURLAsset with a custom `AVAssetResourceLoaderDelegate`. 3. The video player will start sending loading requests to this loader delegate. 4. Upon receiving the first request, the loader delegate begins to download the video data on the background. 5. Upon receiving these requests, the loader delegate will also record the requests, so that it can serve them once possible 6. The loader delegate keeps track of all video data chunks as it receives them from the download task, through the `URLSessionDataDelegate` and `URLSessionTaskDelegate` protocols 7. As it receives data, it checks all pending loading requests from the AVPlayer, and fulfills them as soon as possible 8. If the download fails (e.g. timeout errors, loss of connection), it attempts to restart the download. 9. If the download succeeds, it saves the video to the cache on disk. Closes: https://github.com/damus-io/damus/issues/1717 Changelog-Added: Add video cache to save network bandwidth Signed-off-by: Daniel D’Aquino <daniel@daquino.me> Link: 20240411004129.84436-4-daniel@daquino.me Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
committed by
William Casarin
parent
26d2627a1c
commit
ba494f94ab
@@ -26,6 +26,7 @@ func video_has_audio(player: AVPlayer) async -> Bool {
|
||||
final class DamusVideoPlayerViewModel: ObservableObject {
|
||||
|
||||
private let url: URL
|
||||
private let maybe_cached_av_asset: VideoCache.MaybeCachedAVAsset?
|
||||
private let player_item: AVPlayerItem
|
||||
let player: AVPlayer
|
||||
fileprivate let controller: VideoController
|
||||
@@ -65,8 +66,14 @@ final class DamusVideoPlayerViewModel: ObservableObject {
|
||||
|
||||
init(url: URL, video_size: Binding<CGSize?>, controller: VideoController, mute: Bool? = nil) {
|
||||
self.url = url
|
||||
player_item = AVPlayerItem(url: url)
|
||||
let maybe_cached_av_asset = try? VideoCache.standard?.maybe_cached_asset_for(video_url: url)
|
||||
if maybe_cached_av_asset == nil {
|
||||
Log.info("Something went wrong when trying to load the video with the video cache. Gracefully downgrading to non-cache video loading", for: .storage)
|
||||
}
|
||||
self.maybe_cached_av_asset = maybe_cached_av_asset // Save this wrapped asset to avoid having the loader delegate garbage collected while we still need it.
|
||||
player_item = AVPlayerItem(asset: self.maybe_cached_av_asset?.av_asset ?? AVURLAsset(url: url))
|
||||
player = AVPlayer(playerItem: player_item)
|
||||
player.automaticallyWaitsToMinimizeStalling = true
|
||||
self.controller = controller
|
||||
_video_size = video_size
|
||||
|
||||
|
||||
Reference in New Issue
Block a user