从 AVFoundation 保存录制的视频

Posted

技术标签:

【中文标题】从 AVFoundation 保存录制的视频【英文标题】:Save recorded video from AVFoundation 【发布时间】:2014-08-04 11:29:15 【问题描述】:

我无法从 AVFoundation 保存录像机视频...在 didfinishcapture 中我检查文件是否存在于临时文件夹中,代码总是返回 NO。

此外,当我停止录制时会打印此警告: "无法保存到已保存的相册:Error Domain=NSOSStatusErrorDomain Code=2 "无法播放此电影。" UserInfo=0x1c5696c0 NSLocalizedDescription=无法播放此电影。"

#define OP_PATH [NSTemporaryDirectory() stringByAppendingPathComponent:[@"movie" stringByAppendingPathExtension:@"mov"]]


        - (IBAction) startSession:(id)sender
        
            if(! self.captureSession)
            
                //Session
                self.captureSession = [[AVCaptureSession alloc] init];

                //self.captureSession.sessionPreset = AVCaptureSessionPresetMedium;


                //Layer of own view
                CALayer *viewLayer = self.captureView.layer;


                //AVCaptureVideoPreviewLayer
                AVCaptureVideoPreviewLayer *avCaptureLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];

                avCaptureLayer.frame = self.captureView.bounds;

                [self.captureView.layer addSublayer:avCaptureLayer];


                //AVCaptureDevice
                AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

                NSError *err = nil;


                //Output - Image
                self.stillImgOutput = [[AVCaptureStillImageOutput alloc] init];

                [self.stillImgOutput setOutputSettings:[NSDictionary dictionaryWithObjectsAndKeys:

                                                   AVVideoCodecJPEG, AVVideoCodecKey,

                                                   nil]];

                [self.captureSession addOutput:self.stillImgOutput];


                //Output - Video
                self.movieOutput = [[AVCaptureMovieFileOutput alloc] init];

        //        NSString* key = (NSString*)kCVPixelBufferBytesPerRowAlignmentKey;
        //        
        //        NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
        //        
        //        NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];

                if([self.captureSession canAddOutput:self.movieOutput])
                
                    NSLog(@"Movie out put added");

                    [self.captureSession addOutput:self.movieOutput];
                

                else
                
                    NSLog(@"Cannot add movie out put");
                



                //Input
                AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&err];

                if(! input)
                
                    NSLog(@"Error no camera");

                    return;
                

                if([self.captureSession canAddInput:input])
                
                    [self.captureSession addInput:input];
                

                else
                
                    NSLog(@"Cannot add input. Check Output Settings");
                
            

            if(! [self.captureSession isRunning])
            
                [self.captureSession startRunning];
            

            else
            
                NSLog(@"Session already running");
            
        


    - (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error
    
        NSLog(@"Did stop recording to - %@ \n Any error ? - %@", outputFileURL, [error description]);

        if([[NSFileManager defaultManager] fileExistsAtPath:[outputFileURL absoluteString]])
        
            NSLog(@"YES file exists");
        

        else
        
            NSLog(@"NO File does not exist");
        

        if(UIVideoAtPathIsCompatibleWithSavedPhotosAlbum([outputFileURL absoluteString]))
        
            NSLog(@"YES file is compatible to be saved in Album");

            UISaveVideoAtPathToSavedPhotosAlbum([outputFileURL absoluteString], self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
        

        else
        
            NSLog(@"NO File is not compatible");
        
    


    - (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
    
        if(! error)
        
            NSLog(@"Video Saved to Album");
        

        else
        
            NSLog(@"Video not saved to Album - %@", [error description]);
        

        NSError *er;

        [[NSFileManager defaultManager] removeItemAtPath:OP_PATH error:&er];

        if(! er)
        
            NSLog(@"Temporary file deleted");
        

        else
        
            NSLog(@"Temporary file not deleted - %@", [er description]);
        
    

【问题讨论】:

但它仍然不会影响保存代码? 【参考方案1】:

您缺少以下代码。见下文

//Use timestamp to get new movie name everytime you capture
NSString *timeStamp = [NSString stringWithFormat:@"%0.0f",[[NSDate date] timeIntervalSince1970] * 1000];

NSString *movieOutputUrl =[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mov",timeStamp]];

NSURL *url = [NSURL URLWithString:movieOutputUrl];
[self.movieOutput startRecordingToOutputFileURL:url recordingDelegate:self];

希望对你有帮助。

干杯。

【讨论】:

naaaa。还是一样的错误!它让我发疯!【参考方案2】:
- (void)captureOutput:(AVCaptureFileOutput *)captureOutputdidFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error

    if (error)
    
        NSLog(@"%@", 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];
        
    ];

希望能提供帮助。

【讨论】:

以上是关于从 AVFoundation 保存录制的视频的主要内容,如果未能解决你的问题,请参考以下文章

Swift IOS 使用 AVFoundation 录制视频和音频

使用 AVFoundation Swift 保存视频

使用 AVFoundation / QTKit 一次录制多个视频

使用AVFoundation 自定义相机和录制视频

AVFoundation -> 用动画覆盖记录相机视频

iOS开发进阶 - 用AVFoundation自定义视频录制功能