Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to cache the intial segments of hls content to be played with AVPlayer #1

Open
Rokimkar opened this issue Jan 23, 2025 · 0 comments

Comments

@Rokimkar
Copy link
Owner

App Description:
There is an iOS App which plays video on demand(VOD), which is of hls(.m3u8) type. In each session multiple VODs can be played.
VODs urls can is retrieved and cached when accessed for the first time.
sample VOD url: http://sample.vodobox.com/planete_interdite/planete_interdite_alternate.m3u8
sequence of network calls which goes while playing this url through AVPlayer is as follows:

  1. Master playlist file request goes first.
  2. Individual playlist file for various video qualities is received in the first response which further contains individual segments urls
  3. Individual segment url requests are made and video starts playing

Scenario:
In every App session there are set of VODs urls are which are played frequently and are already known. To play any video we are initialising AVPlayer with AVUrlAsset with those urls.

Observation:
AVPlayer takes time to initialise and play the first segment based on network bandwidth due to the sequence of calls mentioned above.

Requirement:
Since we already knew that user will play this url beforehand, we want to minimise the startup time i.e. time between AVPlayer initialisation and first frame rendered.

Approach:
We wanted to cache the first few segments(let's say first 3 segments) along with the master file for a particular VOD, so that whenever user initiates a playback we already had enough resource cached at our end to render the first frame of the video. note: we only want to cache the first few segments not the complete segments, rest of the segments network call can be made while the video is being played. This will ensure the video started playing very minimal load time.
To Achieve this kind of partial cacheing, we tried to use:

  1. AVAssetDownloadURLSession
  2. created a aggregate download task aggregateAssetDownloadTask(with URLAsset: AVURLAsset ....)
  3. in the delegate func urlSession(_ session: URLSession, aggregateAssetDownloadTask: AVAggregateAssetDownloadTask, willDownloadTo location: URL) we received the download location
  4. in the delegate func urlSession(_ session: URLSession, aggregateAssetDownloadTask: AVAggregateAssetDownloadTask, didLoad timeRange: CMTimeRange, totalTimeRangesLoaded loadedTimeRanges: [NSValue], timeRangeExpectedToLoad expectedTimeRange: CMTimeRange, for mediaSelection: AVMediaSelection), we monitored the download progress and cancelled the task with 5% progress completion mark.
  5. Used this download location in AVURLAsset, to play the video and video was getting played also.

Problem With Above approach:

  • Once this partially downloaded url is provided to the AVPlayer it plays but while playing it also download the rest of the segment, this complete downloaded of the content was not required because for multiple VODs this can trigger device out of memory. Moreover the VODs sizes can be large i.e. > 4GB
  • This downloaded file location contains file of type .movpkg, the size of the file is visible in App settings for individual content. To remove that entry we tried to move this .movpkg file to documents directory but that didn't work because location of the partially downloaded video was a private directory and moving the content to different directory always failed.

Please suggest some improvements in our approach to achieve this kind of partial cacheing of hls contents. Also is there any another possible ways to cache the hls contents partially in general.

Sample project: https://github.com/Rokimkar/HLSStreamPreCache

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant