Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cache an AVPlayerItem (Video) for reuse in a UITableview

I have a number of videos that I am displaying in a UITableView. The videos are stored remotely on a server. I am able to load the videos into the tableview using some of the following code.

 NSString *urlString = [NSString stringWithFormat:[row objectForKey:@"video_uri"]];
 NSURL* url = [NSURL URLWithString:urlString];
 AVPlayerItem *pItem = [AVPlayerItem playerItemWithURL:url];
 AVPlayer *player = [AVPlayer playerWithPlayerItem:pItem];

Each time the tableview dequeues the cell then requeues again the video is loaded again from the url. I'm wondering if there is a way to download and cache or save the video so that it can be played from the phone without having to connect again. I was trying to draw opoin the technique used in the LazyTableImages example provided by Apple, but I'me a little stuck.

like image 345
user379468 Avatar asked Feb 13 '13 15:02

user379468


3 Answers

After messing around with this unsuccessfully trying to cache AVPlayerItems, I've come to theh conclusion that it works much better if you cache the AVPlayerItem's underlying AVAsset which is meant to be reused, whereas the AVPlayerItem itself is not meant to be reused.

like image 123
fisch2 Avatar answered Nov 06 '22 18:11

fisch2


There's one method to do this, but it may be taxing on older devices subsequently cause your app to be jettisoned by MediaServerD.

Upon creation, save each player into an NSMutableArray. Each index in the array should correspond to the indexPath.row of UITableView.

like image 38
ArtSabintsev Avatar answered Nov 06 '22 17:11

ArtSabintsev


Just worked on this problem with a friend yesterday. The code we used basically uses the NSURLSession built-in caching system to save the video data. Here it is:

    NSURLSession *session = [[KHURLSessionManager sharedInstance] session];
    NSURLRequest *req = [[NSURLRequest alloc] initWithURL:**YOUR_URL**];
    [[session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {


        // generate a temporary file URL

        NSString *filename = [[NSUUID UUID] UUIDString];

        NSURL *temporaryDirectoryURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
        NSURL *fileURL = [[temporaryDirectoryURL URLByAppendingPathComponent:filename] URLByAppendingPathExtension:@"mp4"];


        // save the NSData to that URL
        NSError *fileError;
        [data writeToURL:fileURL options:0 error:&fileError];


        // give player the video with that file URL
        AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:fileURL];
        AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
        _avMovieViewController.player = player;
        [_avMovieViewController.player play];



    }] resume];

Second, you will need to set the caching configuration for the NSURLSession. My KHURLSessionManager takes care of this with the following code:

    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    config.requestCachePolicy = NSURLRequestReturnCacheDataElseLoad;
    _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];

Lastly, you should make sure your cache is large enough for the files, I put the following in my AppDelegate.

     [NSURLCache sharedURLCache].diskCapacity = 1000 * 1024 * 1024; // 1000 MB

Hope this helps.

like image 1
William Franklin Katz Avatar answered Nov 06 '22 16:11

William Franklin Katz