How to save a movie from AVCapture

丶灬走出姿态 提交于 2019-12-13 04:34:04

问题


I've been trying to figure out AVCapture the last couple of days and am struggling to save a video. My understanding is that you call [movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self]; and then at a later time you can call [movieFileOutput stopRecording]; And it should then call the delegate method -(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error{. After that I should be able to save the movie with something like UISaveVideoAtPathToSavedPhotosAlbum([outputFileURL path] ,nil,nil,nil); But apparently I'm not doing it correctly. When I start the session and then startRecordingToOutputFile it immediately calls the delegate didFinishRecording. I can't figure out why. Here is a my code:

-(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;
}

Sorry that it's so lengthy. I hope a lot of this code can be useful to someone else.


回答1:


Disclaimer: I am not an Objective C programmer and its only been 15 days since i first started reading about the language itself.

I had to do something similar. Here is the code below which worked for me. I grabed it from different stack overflow questions and examples in developer.apple.com. I have commented out the code which i didn't need for my working prototype. You can play around with it.

-(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];
    }];
}


来源:https://stackoverflow.com/questions/21005942/how-to-save-a-movie-from-avcapture

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!