iOS Frame by Frame video playback forward/backward

5.1k views Asked by At

I'd like to show a video on an iOS device in slow motion.

My view contains a video (~2 seconds long) and a slider.

The user can move the slider and step (forwards and backwards) through the movie frame by frame.

MPMoviePlayerController lacks the ability to step frame by frame.

I read about MVAssetReader, but I have no concrete idea how to use this.

I don't have a fixed framerate, so it should take this information out of the metadata of the video. I really need to show every frame.

Can someone give me a clue?

2

There are 2 answers

0
Dinesh Kaushik On

AV Player Demo Sample code of WWDC 2010 Sample Code can be helpful in your task

Cutting Thumbnails from Video is Explained in WWDC 2010 AV Editing with AV Foundation Framework and lots of other things regarding editing audio and video with sample codes

If you have Developer account(paid) then you can watch video on iTunes

1
Ray Fix On

AVFoundation is a very powerful framework but requires a little more typing and understanding to use than MPMoviePlayerController. I highly recommend Dinesh's recommendation to watch the WWDC videos, look at the sample code, and read the documentation. The documentation is quite good for getting a conceptual understanding, but it lacks some of the details when it comes to the particulars of actual video formats. For that, sample code and experimentation is good.

If you want to go frame by frame then I think AVPlayerItem stepByCount: is the way to go.

// Setup a PlayerItem and a Player
NSURL* movieURL = [NSBundle URLForResource:@"movie" withExtension:@"mov" subdirectory:@"" inBundleWithURL:[NSBundle mainBundle].bundleURL];
AVURLAsset* movieAsset = [AVURLAsset assetWithURL:movieURL];
AVPlayerItem* playerItem = [AVPlayerItem playerItemWithAsset:movieAsset];
AVPlayer* player = [AVPlayer playerWithPlayerItem:playerItem];

// setup the layer so you can see it
AVPlayerLayer* playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
playerLayer.frame = self.view.bounds;
[self.view.layer addSublayer:playerLayer];

// Verify our assumptions, in production code you should do something better
NSAsset(player.currentItem.canStepForward, @"Assume this format can step forward");    
NSAsset(player.currentItem.canStepBackward, @"Assume this format can step backward");


[player.currentItem stepByCount:1];  // step forward a frame

[player.currentItem stepByCount:-1];  // step backward a frame