1

I am trying to create an application for the Mac that would create live video streaming. I know about VLC and other solutions, but still.

To that end i am trying to record video from iSight using QTKit, and save it continuously as a series of tiny video files. However, the recording turns out not quite continuous, with gaps between the files.

Basically, I am just setting up a timer, that starts recording to a new file at certain time intervals, thus stopping the old recording. I also tried setting the max recorded length, and using a delegate method ...didFinishRecording... and ...willFinishRecording..., but with the same result (i can't really estimate the difference between the gaps in these cases).

Please, help me, if you know how these things should be done.

Here is my current code:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    QTCaptureSession *session = [[QTCaptureSession alloc] init];
    QTCaptureDevice *iSight = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo];
    [iSight open:nil];
    QTCaptureDeviceInput *myInput = [QTCaptureDeviceInput deviceInputWithDevice:iSight];
    output = [[QTCaptureMovieFileOutput alloc] init] ; //ivar, QTCaptureFileOutput
    [output setDelegate:self];
    a = 0; //ivar, int
    fileName = @"/Users/dtv/filerecording_"; //ivar, NSString
    [session addOutput:output error:nil];
    [session addInput:myInput error:nil];
    [capview setCaptureSession:session]; //IBOutlet
    [session startRunning]; 
    [output setCompressionOptions:[QTCompressionOptions compressionOptionsWithIdentifier:@"QTCompressionOptionsSD480SizeH264Video"] forConnection:[[output connections] objectAtIndex:0]];
    [output recordToOutputFileURL:[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@%i.mov", fileName, a]] bufferDestination:QTCaptureFileOutputBufferDestinationOldFile];
    NSTimer *tmr = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(getMovieLength:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:tmr forMode:NSDefaultRunLoopMode];
}

‐ (void) getMovieLength:(NSTimer *) t { a++; [output recordToOutputFileURL:[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@%i.mov", fileName, a]] bufferDestination:QTCaptureFileOutputBufferDestinationOldFile]; }

Ibolit
  • 9,218
  • 7
  • 52
  • 96

1 Answers1

2

There is a native mechanism to brake the captured movie into pieces. Use

[QTCaptureFileOutput setMaximumRecordedDuration:]

to specify the duration of the piece or

[QTCaptureFileOutput setMaximumRecordedFileSize:]

to specify the file size limit.

When the limit is reached the delegate method will be called:

[QTCaptureFileOutput_Delegate captureOutput: shouldChangeOutputFileAtURL: forConnections: dueToError:]

In the this method you can set the new file name:

[QTCaptureFileOutput recordToOutputFileURL:]

This will allow you to cut the pieces of the recorded movie pretty precisely.

Note, that [QTCaptureFileOutput_Delegate captureOutput: didFinishRecordingToOutputFileAtURL: forConnections: dueToError:] will be called a bit later after the recoding into the file has been actually finished. If you use this method to set the new file you will have gaps in the final video. It does not mean you do not need to use this method though. This method will indicated when the piece of the movie is ready to be used.

If you need even more precise cutting you can use

[QTCaptureFileOutput captureOutput: didOutputSampleBuffer: fromConnection:]

to specify the exact movie frame when to start recording into a new piece. However, you will need more specific knowledge to work with the method.

Davyd Geyl
  • 4,578
  • 1
  • 28
  • 35
  • Thank you. Unfortunately, can't check it yet. Will accept as soon as i can check it. – Ibolit Oct 18 '11 at 06:12
  • Thank you. It does work much smoother than it used to. But still, not entirely smooth. What is that "more specific knowledge" you mentioned? Could you tell me where i can find it? Best regards, Timofey. – Ibolit Oct 18 '11 at 06:43
  • What do you mean not entirely smooth? It should work very well. When I said you need more specific knowledge I just did not know how deep you needed to dig into quicktime stuff. Most of the time the method I describers it enough to break the captured movie into pieces. However, if you need more precise cutting up to a single frame you can use `[QTCaptureFileOutput captureOutput: didOutputSampleBuffer: fromConnection:]` method. In this case you need to get the data from the buffer and analyse it. Nothing special, you can get almost everything from the documentation. – Davyd Geyl Oct 18 '11 at 11:21
  • I meant, when i view them all one after the other in VLC (and I do play them in the correct order), you can tell where one file ends and the next one begins. It may be due to the way VLC works, though, i agree, so i shall try to view that in, say, iMovie. – Ibolit Oct 20 '11 at 14:39
  • This is another problem. A new movie cannot be played immediately, some time is required to decode the frames. To play the pieces smoothly you need to add them one by one to a new QTMovie file by using [QTMovie appendSelectionFromMovie:] method and play that movie. In this case there will be no gap, because the movie will decode the frames in advance. Do not worry about the size, the actual data will not be copied, but referenced. If you save this movie to the disk you will see the movie file is small unless you use QTMovieFlatten attribute of course. – Davyd Geyl Oct 21 '11 at 03:13