0

Я пытаюсь выяснить, AVCapture последние пару дней и изо всех сил пытаюсь сохранить видео. Я понимаю, что вы вызываете [movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];, а затем позже вы можете позвонить [movieFileOutput stopRecording]; И затем он должен вызвать метод делегата -(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error{. После этого я смогу сохранить фильм с чем-то вроде UISaveVideoAtPathToSavedPhotosAlbum([outputFileURL path] ,nil,nil,nil); Но, видимо, я делаю это неправильно. Когда я запускаю сеанс, а затем startRecordingToOutputFile, он немедленно вызывает делегата didFinishRecording. Я не могу понять, почему. Вот мой код:Как сохранить фильм из AVCapture

-(void)viewDidAppear:(BOOL)animated{ 
     [super viewDidAppear:animated]; 
     session = [[AVCaptureSession alloc] init]; 
     [session beginConfiguration]; 
     session.sessionPreset = AVCaptureSessionPresetMedium; 

     AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; 
    captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 
    captureVideoPreviewLayer.frame = self.imagePreview.bounds; //UIView *imagePreview 
    [self.imagePreview.layer addSublayer:captureVideoPreviewLayer]; 

    AVCaptureDevice *device = [self getCamera]; 
    NSError *error = nil; 
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; 
    if (!input) { 
     // Handle the error appropriately. 
     NSLog(@"ERROR: trying to open camera: %@", error); 
    } 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectoryPath = [paths objectAtIndex:0]; 

    movieFileOutput = [[AVCaptureMovieFileOutput alloc] init]; 

    NSString *archives = [documentsDirectoryPath stringByAppendingPathComponent:@"archives"]; 
    NSString *outputpathofmovie = [[archives stringByAppendingPathComponent:@"Test"] stringByAppendingString:@".mp4"]; 
    NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputpathofmovie]; 

    [session addInput:input]; 
    [session addOutput:movieFileOutput]; 
    [session commitConfiguration]; 
    [session startRunning]; 
    [movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self]; 
    [NSTimer timerWithTimeInterval:7 target:self selector:@selector(stopRun) userInfo:nil repeats:NO]; 
    /* 
    [self initializeCamera]; 
    */ 
} 
-(void)stopRun{ 
     [movieFileOutput stopRecording]; 
    } 

-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error{ 
    NSLog(@"capture done url: %@",outputFileURL); 
    UISaveVideoAtPathToSavedPhotosAlbum([outputFileURL path] ,nil,nil,nil); 
} 

-(AVCaptureDevice*)getCamera{ 
    NSArray *devices = [AVCaptureDevice devices]; 
    AVCaptureDevice *frontCamera; 
    AVCaptureDevice *backCamera; 
    for (AVCaptureDevice *device in devices) { 
     NSLog(@"Device name: %@", [device localizedName]); 
     if ([device hasMediaType:AVMediaTypeVideo]) { 
      if ([device position] == AVCaptureDevicePositionBack) { 
       NSLog(@"Device position : back"); 
       backCamera = device; 
      } 
      else { 
       NSLog(@"Device position : front"); 
       frontCamera = device; 
      } 
     } 
    } 
    return frontCamera; 
} 

Извините, что это так долго. Надеюсь, что этот код может быть полезен кому-то другому.

ответ

2

Отказ от ответственности: Я не программист Objective C, и только 15 дней назад я начал читать о самом языке.

Мне нужно было сделать что-то подобное. Ниже приведен код, который работал для меня. Я взял его из разных вопросов переполнения стека и примеров на developer.apple.com. Я прокомментировал код, который мне не нужен для моего рабочего прототипа. Вы можете поиграть с ним.

-(void) saveRecordingLocally 
{ 
    dispatch_async([self sessionQueue], ^{ 
     if (![[self movieFileOutput] isRecording]) 
     { 
      if ([[UIDevice currentDevice] isMultitaskingSupported]) 
      { 
       // Setup background task. This is needed because the captureOutput:didFinishRecordingToOutputFileAtURL: callback is not received until AVCam returns to the foreground unless you request background execution time. This also ensures that there will be time to write the file to the assets library when AVCam is backgrounded. To conclude this background execution, -endBackgroundTask is called in -recorder:recordingDidFinishToOutputFileURL:error: after the recorded file has been saved. 
       [self setBackgroundRecordingID:[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil]]; 
      } 

      // Update the orientation on the movie file output video connection before starting recording. 
//   [[[self movieFileOutput] connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:[[(AVCaptureVideoPreviewLayer *)[[self previewView] layer] connection] videoOrientation]]; 

      // Turning OFF flash for video recording 
      //[AVCamViewController setFlashMode:AVCaptureFlashModeOff forDevice:[[self videoDeviceInput] device]]; 

      // Start recording to a temporary file. 
      NSString *outputFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[@"movie" stringByAppendingPathExtension:@"mov"]]; 
      [[self movieFileOutput] startRecordingToOutputFileURL:[NSURL fileURLWithPath:outputFilePath] recordingDelegate:self]; 
     } 
    }); 
} 

//delegate 
-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error 
{ 
    NSLog(@"OutputFileUrl %@", outputFileURL); 
    if(error){ 
     NSLog(@"ERROR : %@", error); 
    } 
    UIBackgroundTaskIdentifier backgroundRecordingID = [self backgroundRecordingID]; 
    [self setBackgroundRecordingID:UIBackgroundTaskInvalid]; 
    [[[ALAssetsLibrary alloc] init] writeVideoAtPathToSavedPhotosAlbum:outputFileURL completionBlock:^(NSURL *assetURL, NSError *error) { 
     if (error) 
      NSLog(@"%@", error); 

     [[NSFileManager defaultManager] removeItemAtURL:outputFileURL error:nil]; 

     if (backgroundRecordingID != UIBackgroundTaskInvalid) 
      [[UIApplication sharedApplication] endBackgroundTask:backgroundRecordingID]; 
    }]; 
} 
Смежные вопросы