Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loop a segment of a video with AVPlayer

I am trying to loop a segment of video, given two frame markers (markIn and markOut). When the option to loop is selected, the player will loop this segment of the video. I currently have a loop for the whole video set up using Apple's suggestion of sending the AVPlayerItemDidPlayToEndTimeNotification once the end is reached.

What I think will be a clean way to implement this will be to send a notification when the markOut point is reached, if looping is activated it will move the player back to the markIn point. So is there are way to create a notification along of the lines of playerItemDidReachMarkOut?

I'm fairly new to notifications and AVPlayer, so forgive me if I'm missing something.

like image 535
timgcarlson Avatar asked Jul 19 '13 18:07

timgcarlson


1 Answers

What you're looking for is called a boundary time observer. You give your AVPlayer a list of CMTimes, and it will notify you when the player's currentTime is approximately any of those times.

It works like this:

//Use an unretained reference in the block to break the retain cycle of the player retaining the block retaining the player retaining…
__unsafe_unretained AVPlayer *weakPlayer = _myPlayer;

_myObserver = [_myPlayer addBoundaryTimeObserverForTimes:@[ [NSValue valueWithCMTime:markOutTime] ]
    queue:dispatch_get_main_queue()
    usingBlock:^{
        [weakPlayer seekToTime:markInTime
            /*optional:
            toleranceBefore:kCMTimeZero
            toleranceAfter:kCMTimeZero
            */
            ];
    }
];

Later, of course, you must use removeTimeObserver: to tell the AVPlayer to stop this observation. You give it the object you got from addBoundaryTimeObserver…:::.

Notes/Caveats/Warnings

  • Despite the name, they do not have to be “boundary” times. You can have exactly one time, and even when you don't, AVPlayer makes no inferences about whether any of the times is a start time, end time, midpoint, or whatever.
  • The same block may be called multiple times for the same “boundary”. Make sure you handle this appropriately (in my case, I had to make sure not to show the same subtitle twice).
  • Boundary time observers are not called when seeking (again, the times are not really interpreted as “boundaries” in the sense of start and end). If you seek straight to a boundary time (more or less—see next point), you should get notified for that, but seeking to a point in between two boundaries, or among many boundaries, will not cause an observation.
  • I said approximately, and I mean it. The main case in which I've seen AVPlayer notify multiple times is when AVPlayer notifies a little early, and then notifies again at (or at least closer to) the exact time. Don't assume that currentTime will be exactly equal to any time you supplied.
like image 161
Peter Hosey Avatar answered Oct 17 '22 07:10

Peter Hosey