如何在录制时修改帧并保存更改,然后将视频保存为mp4文件?

时间:2015-10-28 04:07:50

标签: ios objective-c avfoundation avassetwriter

在我的项目中,我需要在视频开始时捕获帧。我从代理中捕获它

"- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection",并使用"appendPixelBuffer:newPixBuffer withPresentationTime:tmpTime"保存修改后的帧。这些都没关系!但是,当我完成一次录制时,avassetwriter的状态可以更改为已完成,但mp4文件无法保存。

这是我的一些代码:

  1. configueration:

    -(void)configRecording:(NSURL*)fileUrl
    

    {     NSError *错误;

    _recordingFilePath = fileUrl;
    
    NSDictionary *videoCleanApertureSettings = @{
                                                 AVVideoCleanApertureWidthKey: [NSNumber numberWithFloat:SCREEN_WIDTH],
                                                 AVVideoCleanApertureHeightKey: [NSNumber numberWithFloat:SCREEN_WIDTH],
                                                 AVVideoCleanApertureHorizontalOffsetKey: [NSNumber numberWithInt:10],
                                                 AVVideoCleanApertureVerticalOffsetKey: [NSNumber numberWithInt:10],
                                                 };
    
    NSDictionary *videoCompressionSettings = @{
                                               AVVideoAverageBitRateKey: [NSNumber numberWithFloat:2000000.0],
                                               AVVideoMaxKeyFrameIntervalKey: [NSNumber numberWithInteger:1],
                                               AVVideoProfileLevelKey: AVVideoProfileLevelH264Baseline30,
                                               AVVideoCleanApertureKey: videoCleanApertureSettings,
                                               };
    
    NSDictionary* videoSetting = [NSDictionary dictionaryWithObjectsAndKeys:
                                  AVVideoCodecH264, AVVideoCodecKey,
                                  [NSNumber numberWithInt:SCREEN_WIDTH],AVVideoWidthKey,
                                  [NSNumber numberWithInt:SCREEN_WIDTH],AVVideoHeightKey,
                                  videoCompressionSettings,AVVideoCompressionPropertiesKey,
                                  AVVideoScalingModeResizeAspectFill,AVVideoScalingModeKey,
                                  nil];
    
    _avassetWriter = [AVAssetWriter assetWriterWithURL:fileUrl fileType:AVFileTypeMPEG4 error:&error];
    
    // Add the audio input
    AudioChannelLayout acl;
    bzero( &acl, sizeof(acl));
    acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
    NSDictionary* audioOutputSettings = [ NSDictionary dictionaryWithObjectsAndKeys:
                           [ NSNumber numberWithInt: kAudioFormatAppleLossless ], AVFormatIDKey,
                           [ NSNumber numberWithInt: 16 ], AVEncoderBitDepthHintKey,
                           [ NSNumber numberWithFloat: 44100.0 ], AVSampleRateKey,
                           [ NSNumber numberWithInt: 1 ], AVNumberOfChannelsKey,
                           [ NSData dataWithBytes: &acl length: sizeof( acl ) ], AVChannelLayoutKey,
                           nil ];
    
    _avassetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSetting];
    _avassetWriterInput.expectsMediaDataInRealTime = YES;
    _audioWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:audioOutputSettings];
    _audioWriterInput.expectsMediaDataInRealTime = YES;
    _avassetAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:_avassetWriterInput sourcePixelBufferAttributes:videoSetting];
    
    
    if ([_avassetWriter canAddInput:_avassetWriterInput] ) {
    
        [_avassetWriter addInput:_avassetWriterInput];
    
    }
    
    if ([_avassetWriter canAddInput:_audioWriterInput]) {
        [_avassetWriter addInput:_audioWriterInput];
    }
    
    BOOL canOutput = [_avassetWriter canApplyOutputSettings:videoSetting forMediaType:AVFileTypeMPEG4];
    NSLog(@"can out put := %d", canOutput);
    

    }

  2. 这是我的开始录音功能:

    [_ avassetWriter startWriting];
      [_avassetWriter startSessionAtSourceTime:kCMTimeZero];

  3. 3.这是修改框架的方法:

     - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
        {
            CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    
            int faceTrackResult = [faceTracker startFacialTracking:pixelBuffer
                                                 startFaceTracking:YES
                                                 withFaceRectangle:_faceRect
                                                     withRollAngle:_rollAngle];
    
            CVPixelBufferRetain(pixelBuffer);
            dispatch_async(dispatch_get_main_queue(), ^{
                [_trackerView drawSceneWithBackground:pixelBuffer];
                CVPixelBufferRelease(pixelBuffer);
            });
    
            if (cameraView.isRecording == YES) {
                CMTime tmpTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
                [cameraView getLastRecordingTime:tmpTime];
                //开始捕捉视频帧
                    CGImageRef curFrameRef = [cameraView getImageRef:self.trackerView.frame];
                    CVPixelBufferRef newPixBuffer = [self pixelBufferFromCGImage:curFrameRef];
    
    
                    if (cameraView.avassetWriter.status == AVAssetWriterStatusWriting && cameraView.isRecording == YES) {
    
                        BOOL result = [cameraView.avassetAdaptor appendPixelBuffer:newPixBuffer withPresentationTime:tmpTime];
                        NSLog(@"result := %d; status := %ld", result, (long)cameraView.avassetWriter.status);
                    }
            }
        }
    
    1. 这是我的停止录制功能:

      - (无效)stopRecording     {         WS(weakSelf);

          [_avassetWriterInput markAsFinished];
          [_avassetWriter endSessionAtSourceTime: lastSimple_Time];
          if (_avassetWriter.status != AVAssetWriterStatusCompleted) {
              NSLog(@"error := %@", _avassetWriter.error);
          }
      
          self.isRecording = NO;
      
          [_avassetWriter finishWritingWithCompletionHandler:^{
      
              if (_avassetWriter.status == AVAssetWriterStatusFailed) {
                  NSLog(@"error := %@", _avassetWriter.error);
              }
      
              if (weakSelf.recordDelegate && [weakSelf.recordDelegate respondsToSelector:@selector(finishRecording:)]) {
                  [weakSelf.recordDelegate finishRecording:weakSelf.recordingFilePath];
              }
          }];
      }
      

0 个答案:

没有答案