Video Download/Disk Cache in iOS : Swift
Video is one of the most vital kind of content now a days. Every application may need to have some kind of video content to tempt their users. But problem comes when app needs to get data for same video number of times, this is not fair for our app user as we are unnecessarily consuming user network data. Specially for short videos, a user can play the same track five times a day and he can fell asleep😴🥱 while looking at loading activity if it appears every time, other case as if you are on Mars 😄 😄 or in a cave and want to enjoy your favourite videos, you may see a message like “No Internet Available” 😔😔. As an application Developer, a first question comes to your mind - Can we cache few most recent videos to improve our user experience? In this article I am going to explore couple of techniques to cache video content on disk using AVFoundation family.
- Using AVAssetExportSession
AVAssetExportSession is one of the straight forward way to download video and save it to disk. First we create AVURLAsset and compose audio and video files as shown in below code snippet :
Lets understand it step by step as shown in above code comments
- Create AVMutableComposition object to compose audio and video files.
- Compose video track.
- Compose audio track.
- Create AVAssetExportSession object with asset composition and preset quality.
- Create directory path, give this path to exporter output URL. Also set exporter output file type.
- Call exportAsynchronously to complete the process. Exporter also gives you status cases like unknown, waiting, exporting, completed, failed or cancelled. You can handle these as per your requirement.
Note : This technique is faster to implement, can be useful for short videos. For long videos this is not the best choice. Addition to this export session is not good choice if you are supposed to play and download videos at the same time.
That’s it. We are done ✅. Easy one right! lets move to second approach👀
2. Using AVAssetResourceLoadingRequests
As discussed AVAssetExportSession is not good bet for long videos. So we are going to use AVAssetResourceLoaderDelegate this time. It help us to implement similar logic as provides exporter and more. The tricky part here is to get AVAssetResourceLoaderDelegate invoked. We should not pass the original URL like https://www.varuntomar.com/demo.mp4, but a bit modified https-testloader://www.varuntomar.com/demo.mp4 to make our ResourceLoaderDelegate get invoked. After this we can assign loaderDelegate to videoAsset. I have written a sample resource delegate class, have a look below :
First method invokes when the player asks about a new batch of data. With our delegate, we intercept request and load all data our self with URLSession and provide back to the origin AVAssetResourceLoadingRequest’s data which we have.Now, providing data is your primary responsibility. Let me walk you through the code to get better understanding, please refer comments in above code snippet :
- Intercepting original video URL here, so that AVAssetResourceLoaderDelagate get invoked otherwise it would not get invoked and data loading would be handled by AVPlayedItem itself.
- Init AVUrlAsset object’s delegate with video url
- Invalidate pending request and URLSession tasks when our task has finished or blocked due to some reason.
- Resource loader delegate, where we are creating our URLSession to make data request.
- URLSession delegate to process requests.
- Appending received media data temporarily in memory. This media data would be write on disk when all pending requests get finished.
- Function to create URLSession
- Invalidating URLSession here.
- It would return true if AVAssetResourceLoadingRequest information is requested.
- Here filling the required request information.
- We are processing AVAssetResourceLoadingRequests here.
- Checking request loaded data and offset
- When task is completed, this would get called to finish off things.
- Save media data to local file in resources.
Confused 🤷♂️ 🤷♀️. Below is the sample code to initiate media download process ✌️:
You can debug above classes to get more understanding if have some doubt. In this approach we have more control on downloading, also we can have both play and download tasks together. URLSession can download data in packets and provide the same to play in runtime. Is this what you are looking for when you start to read this article?
Hope you enjoyed this article. I will explain about HLS and it’s variants downloading in my next article. So stay tuned 😄😄. Thanks for reading this🙏🙏. Any feedback in the comment section would be appreciated. If you feel , please share and give some claps.
You can follow me for fresh articles.