18

I am trying to record video in my iPhone app using AVFoundation. But whenever I click the Record button app crashes with this message

-[AVCaptureMovieFileOutput startRecordingToOutputFileURL:recordingDelegate:] - no active/enabled connections.

I know same question asked in SO, but none of its answers helped me. My problem is the same code works with another application perfectly, and when I try using exactly same code in this app - crashes. But still photo capture is working fine.

Adding my codes here - please help me, Thanks in advance

  -(void)viewDidLoad
  {
 [super viewDidLoad];
 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 addInput:self.videoInput];
  [self.captureSession addOutput:self.stillImageOutput];




   previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
   UIView *aView = self.view;
   previewLayer.frame = CGRectMake(70, 190, 270, 270);
   [aView.layer addSublayer:previewLayer];


     }




  -(NSURL *) tempFileURL
  {
    NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mov"];
    NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
   NSFileManager *manager = [[NSFileManager alloc] init];
   if ([manager fileExistsAtPath:outputPath])
    {
    [manager removeItemAtPath:outputPath error:nil];
    }


    return outputURL;
  }

  -(IBAction)capture:(id)sender
  {

    if (self.movieOutput.isRecording == YES)
    {
         [self.movieOutput stopRecording];
    }
    else
    {
         [self.movieOutput startRecordingToOutputFileURL:[self tempFileURL] recordingDelegate:self];
    }

      }





   -(void)captureOutput:(AVCaptureFileOutput *)captureOutput  didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
  fromConnections:(NSArray *)connections
            error:(NSError *)error
  {


   BOOL recordedSuccessfully = YES;
  if ([error code] != noErr)
    {
    id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey];
    if (value)
        recordedSuccessfully = [value boolValue];
    NSLog(@"A problem occurred while recording: %@", error);
   }
  if (recordedSuccessfully) {
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

    [library writeVideoAtPathToSavedPhotosAlbum:outputFileURL
                                completionBlock:^(NSURL *assetURL, NSError *error)
     {
         UIAlertView *alert;
         if (!error)
         {
             alert = [[UIAlertView alloc] initWithTitle:@"Video Saved"
                                                message:@"The movie was successfully saved to you photos library"
                                               delegate:nil
                                      cancelButtonTitle:@"OK"
                                      otherButtonTitles:nil, nil];
         }
         else
         {
             alert = [[UIAlertView alloc] initWithTitle:@"Error Saving Video"
                                                message:@"The movie was not saved to you photos library"
                                               delegate:nil
                                      cancelButtonTitle:@"OK"

                                      otherButtonTitles:nil, nil];
         }

         [alert show];
     }
     ];
    }

  }
CodeBender
  • 35,668
  • 12
  • 125
  • 132

4 Answers4

11

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! :)

zvjerka24
  • 1,772
  • 1
  • 21
  • 27
  • I am trying somewhat similar, could you take a look at my question: [https://stackoverflow.com/questions/44860899/how-to-record-timelapse-video-from-iphone-using-avcapturedeviceformat] – nr5 Jul 01 '17 at 12:51
  • I tried that, and it didn't work. Do you know a way to do it without setting a preset? Sometimes you need to directly set the activeFormat, as Apple suggests. – Kartick Vaddadi Sep 11 '17 at 04:03
  • This can very much be the issue when you're trying to capture the front-facing camera for example. Thanks, worked for me! – Kevin Nov 08 '17 at 15:20
10

Several things are missing in your code :

  1. You forgot to add movieOutput to your captureSession
  2. Same for your audioInput
  3. All your session configuration needs to be encapsulated by [_captureSession beginConfiguration] and [_captureSession commitConfiguration]
  4. 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

iGranDav
  • 2,450
  • 1
  • 21
  • 25
10

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.

Cao Huu Loc
  • 1,569
  • 15
  • 18
  • Changing the `sessionPreset` property fixed it for. I had it set to `AVCaptureSessionPresetPhoto` instead of `AVCaptureSessionPresetHigh`. Thanks. – Anthony Persaud Jul 22 '17 at 22:45
  • Do you know a way to do it without setting a preset? Sometimes you need to directly set the activeFormat, as Apple suggests. – Kartick Vaddadi Sep 11 '17 at 04:02
3

I find the reason of this error. check your session's "setSessionPreset" setting, photo's resolution setting is different from video, for iPhone5, video resolution of the back camera is 1920*1080, the front camere is 1280*720, and photo's max resolution is 3264*2488, so if you set error resolution to video, the connect will not be actived.

honestsky
  • 31
  • 1