I am dealing with an M3U8 video file where I’m trying to play it after storing such remote videos in my SwiftUI app.
The main approach I found so far is the accepted answer in this thread: Is it possible to cache Videos? IOS – Swift
Problem:
However, when I try to implement it, the M3U8 video does not load.
If I was to play directly from the videoURL
, then there would be no issues and the video plays. But I would also like to play it from the cache.
VideoPlayer(player: player)
.onAppear {
CacheManager.shared.getFileWith(stringUrl: videoURL) { result in
switch result {
case .success(let url):
self.player = AVPlayer(url: url)
self.player?.play()
case .failure:
print("Error")
}
}
}
For context, printing the URL from CacheManager gives file:///var/mobile/Containers/Data/Application/2F12CCE9-1D0C-447B-9B96-9EC6F6BE1413/Library/Caches/filename
(where filename is the actual filename).
And this is what the video player looks like when running the app.
So is there an issue with my implementation of the code? Is the accepted answer from the old thread actually invalid/outdated and no longer works with current iOS versions? Does anyone have an alternative method for caching videos?
2
Answers
I ended up mainly implementing the approach in: https://developer.apple.com/documentation/avfoundation/offline_playback_and_storage/using_avfoundation_to_play_and_persist_http_live_streams.
The sample code demonstrated a method for downloading HLS content however the videos were being saved in a public folder users could access from Settings, as well as using UserDefaults to store the locations, which were both features I did not want as I wanted to implement a cache that downloads videos when they load to remove later.
So I modified and simplified the code as such:
Most notably, I changed the delegate for handling the completion of the download to move the file to a
/tmp
directory afterwards so it no longer appears in Settings. This now lets me asynchronously download HTTP Streams and cache them in a temporary directory for later fetching.To make the playback work, you can try these steps:
(1) Download both the
.m3u8
and the related.ts
file(s) as listed within the M3U8 file.(2) Inside the M3U8, change the text of the path by removing any sub-folders.
eg: if your M3U8 path is:
/cdn_url/video720/filename.ts
just remove the/cdn_url/video720/
text.Then your M3U8 should look something like this (where only its own file path is changed):
It is a good idea also to rename both the M3U8 and TS with a matching file "name" to identify playlist videos.
eg: Make it as
Batman_ep_01.m3u8
andBatman_ep_01.ts
(3) Save and test in AVPlayer.
What about multiple TS files in one M3U8?
It works the same as Step (2) but you simply put the M3U8 and its related TS files into a unique sub-folder. Something like below where the m3u8 and ts files are stored.
eg:
/Library/Caches/some_Show_multi/