Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the size of an AVAssetDownloadTask before downloading

I'm currently implementing offline streaming with FairPlay streaming. Therefor I'm downloading streams using an AVAssetDownloadTask.

I want to give the users feedback about the size of the download which starts to begin:

Are you sure you want to download this stream? It will take 2.4GB to download and you currently have 14GB of space left

I've checking properties like countOfBytesReceived and countOfBytesExpectedToReceive but these wont give back correct values.

let headRequest = NSMutableURLRequest(URL: asset.streamURL)
headRequest.HTTPMethod = "HEAD"
let sizeTask = NSURLSession.sharedSession().dataTaskWithRequest(headRequest) { (data, response, error) in
    print("Expected size is \(response?.expectedContentLength)")
}.resume()

prints a size of 2464, where at the end the size is 3GB.

During the download I logged above properties:

func URLSession(session: NSURLSession, assetDownloadTask: AVAssetDownloadTask, didLoadTimeRange timeRange: CMTimeRange, totalTimeRangesLoaded loadedTimeRanges: [NSValue], timeRangeExpectedToLoad: CMTimeRange) {
    print("Downloaded \( convertFileSizeToMegabyte(Float(assetDownloadTask.countOfBytesReceived)))/\(convertFileSizeToMegabyte(Float(assetDownloadTask.countOfBytesExpectedToReceive))) MB")
}

But these stay at zero:

Downloaded 0.0/0.0 MB

like image 829
Antoine Avatar asked Sep 19 '16 10:09

Antoine


1 Answers

HLS streams are actually a collection of files known as manifests and transport streams. Manifests usually contain a text listing of sub-manifests (each one corresponding to a different bitrate), and these sub-manifests contains a list of transport streams that contain the actual movie data.

In your code, when you download the HLS URL, you're actually downloading just the master manifest, and that's typically a few thousand bytes. If you want to copy the entire stream, you'll need to parse all the manifests, replicate the folder structure of the original stream, and grab the transport segments too (these are usually in 10-second segments, so there can be hundreds of these). You may need to rewrite URLs if the manifests are specified with absolute URLs as well.

To compute the size of each stream, you could multiply the bitrate (listed in the master manifest) by the duration of the stream; that might be a good enough estimate for download purposes.

A better answer here, since you're using the AVAssetDownloadTask in the context of offline FairPlay, is to implement the AVAssetDownloadDelegate. One of the methods in that protocol gives you the progress you're looking for:

URLSession:assetDownloadTask:didLoadTimeRange:totalTimeRangesLoaded:timeRangeExpectedToLoad:

Here's WWDC 2016 Session 504 showing this delegate in action.

There are a lot of details related to offline playback with FairPlay, so it's a good idea to go through that video very carefully.

like image 200
pixbug Avatar answered Oct 31 '22 03:10

pixbug