3

I'm creating an app where the user is supposed to video record himself while another video is playing on the screen next to the camera view. The result will be two video files, one source, and one recording. Using AVCaptureSession etc., I have successfully managed to record a video at the same time as another video is playing on the screen. The problem is that It's not completely in sync.

This is how I have set it up right now:

-(void)playAndRecordInSync //Session is already set etc.
{
        player = [AVPlayer playerWithURL:url];
        playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
        [playerLayer setFrame:leftCameraView.bounds];
        [playerLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
        [leftCameraView.layer addSublayer:playerLayer];

        //Will stop recording camera when source video reaches end(notification):
        player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
        [[NSNotificationCenter defaultCenter] addObserver:self
                              selector:@selector(playerItemDidReachEnd:)
                               name:AVPlayerItemDidPlayToEndTimeNotification
                                                   object:[player currentItem]];
        //Start playback:
        [player play]; 
        //Start recording:
        [movieOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
}
- (void)playerItemDidReachEnd:(NSNotification *)notification {
    [movieOutput stopRecording];
}

The result of this, is two videos, but the second (recorded) video is slightly longer than the source/original video. When playing them on top of each other (at the same time), then video nr. 2 has a delay of almost half a second. It feels like video2 has started recording way too soon, because of the "extra" time. It could probably also be that the playback started too late. Either way, I don't know how to make any consistency here based on this. I could probably play around a lot with sleep etc, but that would only work for my phone, as this has something to do with how fast the phone is. Even if there is a delegate method like -(void)willStartPlaying for the AVPlayer, which I don't think there is, there would still be a problem with sync, as there's a minor wait till the return. Is there a way to fire two commands at once? Or is there another solution for this?

EDIT

I've been reading this (AVSynchronizedLayer), but I'm not sure if this is applicable to my situation, and I don't understand how to proceed.

Sti
  • 8,275
  • 9
  • 62
  • 124

1 Answers1

1

I found out the delay was always caused by the playback starting too late, but both the recording and the playback were stopped at the same time, so I resolved this by finding v2.duration - v1.duration, and subtract the result from the beginning of v2, using AVAssetExportSession. When playing back both videos at once now, in different layers, there's still some delay from starting both, but by exporting the videos, I've confirmed that they're the same length and in sync now.

Sti
  • 8,275
  • 9
  • 62
  • 124