A: On OS X 10.7 Lion and later, the way to make a movie of screen activity is to use AV Foundation.
Important: AV Foundation grabs the screen repeatedly. If you want to capture a static image instead of a real-time movie, a more efficient way is to call CGDisplayCreateImage
orCGDisplayCreateImageForRect
, for example:
// Create an image from the entire main display
CGImageRef image = CGDisplayCreateImage(kCGDirectMainDisplay);
See How to take an image snapshot of the screen on Mac OS X Lion for more information.
To perform a real-time screen capture and save it to a QuickTime movie file, you need minimally three AV objects:
An AVCaptureSession
object, which coordinates the flow of data from AV input sources to outputs.
An AVCaptureScreenInput
object, which is the input data source that provides video data from the given display.
An AVCaptureMovieFileOutput
object, which is the output destination for you to write captured media data to a QuickTime movie file.
Note: By default, AVCaptureScreenInput
captures the entire screen. You may set its cropRect
property to limit the capture rectangle to a subsection of the screen.
In the following example, the code creates a capture session, adds a screen input to provide video frames, adds an output destination to save captured frames, starts the flow of data from the input to the output, and stops the flow in 5 seconds. By letting the class conform to the AVCaptureFileOutputRecordingDelegate
protocol and setting the recording delegate properly, you can monitor when the recording is finished via the delegate method.
Note: To capture both a main and secondary display at the same time, use two active capture sessions, one for each display. On OS X, AVCaptureMovieFileOutput
only supports writing to a single video track.
AVCaptureFileOutputRecordingDelegate
protocol
#import <Foundation/Foundation.h> |
#import <AVFoundation/AVFoundation.h> |
@interface Recorder : NSObject <AVCaptureFileOutputRecordingDelegate> { |
@private |
AVCaptureSession *mSession; |
AVCaptureMovieFileOutput *mMovieFileOutput; |
NSTimer *mTimer; |
} |
-(void)screenRecording:(NSURL *)destPath; |
@end |
Screen recording example
-(void)screenRecording:(NSURL *)destPath |
{ |
// Create a capture session |
mSession = [[AVCaptureSession alloc] init]; |
// Set the session preset as you wish |
mSession.sessionPreset = AVCaptureSessionPresetMedium; |
// If you're on a multi-display system and you want to capture a secondary display, |
// you can call CGGetActiveDisplayList() to get the list of all active displays. |
// For this example, we just specify the main display. |
// To capture both a main and secondary display at the same time, use two active |
// capture sessions, one for each display. On Mac OS X, AVCaptureMovieFileOutput |
// only supports writing to a single video track. |
CGDirectDisplayID displayId = kCGDirectMainDisplay; |
// Create a ScreenInput with the display and add it to the session |
AVCaptureScreenInput *input = [[[AVCaptureScreenInput alloc] initWithDisplayID:displayId] autorelease]; |
if (!input) { |
[mSession release]; |
mSession = nil; |
return; |
} |
if ([mSession canAddInput:input]) |
[mSession addInput:input]; |
// Create a MovieFileOutput and add it to the session |
mMovieFileOutput = [[[AVCaptureMovieFileOutput alloc] init] autorelease]; |
if ([mSession canAddOutput:mMovieFileOutput]) |
[mSession addOutput:mMovieFileOutput]; |
// Start running the session |
[mSession startRunning]; |
// Delete any existing movie file first |
if ([[NSFileManager defaultManager] fileExistsAtPath:[destPath path]]) |
{ |
NSError *err; |
if (![[NSFileManager defaultManager] removeItemAtPath:[destPath path] error:&err]) |
{ |
NSLog(@"Error deleting existing movie %@",[err localizedDescription]); |
} |
} |
// Start recording to the destination movie file |
// The destination path is assumed to end with ".mov", for example, @"/users/master/desktop/capture.mov" |
// Set the recording delegate to self |
[mMovieFileOutput startRecordingToOutputFileURL:destPath recordingDelegate:self]; |
// Fire a timer in 5 seconds |
mTimer = [[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(finishRecord:) userInfo:nil repeats:NO] retain]; |
} |
-(void)finishRecord:(NSTimer *)timer |
{ |
// Stop recording to the destination movie file |
[mMovieFileOutput stopRecording]; |
[mTimer release]; |
mTimer = nil; |
} |
// AVCaptureFileOutputRecordingDelegate methods |
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error |
{ |
NSLog(@"Did finish recording to %@ due to error %@", [outputFileURL description], [error description]); |
// Stop running the session |
[mSession stopRunning]; |
// Release the session |
[mSession release]; |
mSession = nil; |
} |
Date | Notes |
---|---|
2015-05-20 | Added additional notes about capturing the main and secondary displays at the same time. Other miscellaneous changes. |
2011-08-10 | Corrected a link. |
2011-05-13 | New document that shows how to capture screen activity to a movie file using AV Foundation on OS X 10.7 Lion and later. |