AVCaptureMovieFileOutput - no active/enabled connections
I had the same problem while changing videoDevice activeFormat and later wanted to record video. Because I was using best quality video I had to set sessionPreset to high, like following
_session.sessionPreset = AVCaptureSessionPresetHigh;
and it worked for me! :)
Because currently you don't have an active connection to record video to file.
Check connection active status before recording to output file:
AVCaptureConnection *c = [self.movieOutput connectionWithMediaType:AVMediaTypeVideo];if (c.active) { //connection is active} else { //connection is not active //try to change self.captureSession.sessionPreset, //or change videoDevice.activeFormat}
If connection is not active, try to change captureSession.sessionPreset or videoDevice.activeFormat.
Repeat until you have set a valid format (that means c.active == YES). Then you can record video to output file.
Several things are missing in your code :
- You forgot to add
movieOutput
to yourcaptureSession
- Same for your
audioInput
- All your session configuration needs to be encapsulated by
[_captureSession beginConfiguration]
and[_captureSession commitConfiguration]
- For audio recording you need to set the
AVAudioSession
to the correct category.
Here is your code updated :
- (void)viewDidLoad{ [super viewDidLoad]; NSError *error = nil; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:&error]; if(!error) { [[AVAudioSession sharedInstance] setActive:YES error:&error]; if(error) NSLog(@"Error while activating AudioSession : %@", error); } else { NSLog(@"Error while setting category of AudioSession : %@", error); } self.captureSession = [[AVCaptureSession alloc] init]; AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; self.videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:nil]; self.audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:audioDevice error:nil]; self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; NSDictionary *stillImageOutputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil]; [self.stillImageOutput setOutputSettings:stillImageOutputSettings]; self.movieOutput = [[AVCaptureMovieFileOutput alloc] init]; [self.captureSession beginConfiguration]; [self.captureSession addInput:self.videoInput]; [self.captureSession addInput:self.audioInput]; [self.captureSession addOutput:self.movieOutput]; [self.captureSession addOutput:self.stillImageOutput]; [self.captureSession commitConfiguration]; AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession]; previewLayer.frame = CGRectMake(0, 0, 320, 500); [self.view.layer addSublayer:previewLayer]; [self.captureSession startRunning];}- (IBAction)toggleRecording:(id)sender{ if(!self.movieOutput.isRecording) { [self.recordButton setTitle:@"Stop" forState:UIControlStateNormal]; NSString *outputPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"output.mp4"]; NSFileManager *manager = [[NSFileManager alloc] init]; if ([manager fileExistsAtPath:outputPath]) { [manager removeItemAtPath:outputPath error:nil]; } [self.movieOutput startRecordingToOutputFileURL:[NSURL fileURLWithPath:outputPath] recordingDelegate:self]; } else { [self.recordButton setTitle:@"Start recording" forState:UIControlStateNormal]; [self.movieOutput stopRecording]; }}- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error{ NSLog(@"Did finish recording, error %@ | path %@ | connections %@", error, [outputFileURL absoluteString], connections);}
Hope this helps