I'm working on an iOS app which creates a feed of all the videos submitted by the pool of users, enabling users to browse and view the videos that others have created. As you can imagine, I need to be able to support an arbitrary number of videos in the feed.
Currently, I am creating and retaining an AVPlayer instance for each video like so:
//inside the init method of a UIView
//create the AVPlayer and store it in a strong property
NSString * urlString = @"aRemoteURL.mov";
NSURL * movURL = [NSURL URLWithString:urlString];
_videoPlayer = [[AVPlayer alloc]initWithURL:movURL];
//register callbacks for handling buffering
[_videoPlayer.currentItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[_videoPlayer.currentItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
//add the AVPlayerLayer to the view so you can see the video
AVPlayerLayer * playerLayer = [AVPlayerLayer playerLayerWithPlayer:_videoPlayer];
playerLayer.frame = self.frame;
[self.layer addSublayer:playerLayer];
I call play
on _videoPlayer
when the user taps on the UIView
, and everything works perfectly. That is, until enough videos are submitted to the feed...
Once more than 18 videos exist in the feed, the new instances of AVPlayer
will not play, and _videoPlayer.currentItem.status
will be AVPlayerItemStatusFailed
with an ambiguous error Code=-11800 "The operation could not be completed"
. Interestingly, it is always the 19th video which is the first to break, regardless of the length and quality of the first 18 videos.
I take it I'm not supposed to be creating all these AVPlayer instances. I tried using an AVPlayer singleton wrapper, where I handed a shared AVPlayer instance around to the relevant UIView when a user wanted to play a video. This eliminated the AVPlayerItemStatusFailed
error, but made playback unusably laggy.
I haven't been able to find any other accounts of this problem. If anyone can offer some insight into a better approach to this situation, or even so much as point me in the direction of a good AVPlayer tutorial, I will be very grateful. Thanks!
If anyone comes across this same problem, I ended up creating a work around. Turns out that the number of AVPlayer instances is limited by iPhone hardware, I wish Apple made this more clear. This question touches on that.
In order to get around this limitation, I create and retain an AVURLAsset
as well as an AVPlayerItem
for each video I wish to play. When it's time to play the video, I create an AVPlayer
instance on the fly (not a shared instance), add the AVPlayerItem
to it, and play the video. After the video is done playing, I destroy the AVPlayer
instance to free up the hardware. This is working well for me and my specialized situation, but some variation of this should help you too if you're experiencing the problem outlined above.
small rant:
I have been working fairly extensively with AVFoundation over the last couple of months, manipulating different types of media in lots of different ways. I frequently find myself cursing Apple's skeletal documentation and examples related to the AVFoundation framework. I wish they would bolster their docs for this as a lot of the framework is convoluted and unintuitive. This tiny rant in a dusty corner of the internet won't change anything but I guess I'm just venting.
end rant
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With