使用AVAssetWriter录制视频 [英] Record video with AVAssetWriter

查看:181
本文介绍了使用AVAssetWriter录制视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用AVAssetwriter录制视频,但是在添加数据之前检查AVAssetWriterInput属性readyForMoreMediaData时却一直显示NO.

I'm trying to record video with AVAssetwriter but I keep getting NO when checking AVAssetWriterInput property readyForMoreMediaData before appending data.

我看到相关的帖子在尝试录制音频和视频时提到了类似的问题,所以我取出了音频录制部分,但问题仍然存在(readyForMoreMediaData始终为否).

I saw related posts that mentioned similar problem when trying to record audio + video so I took out the audio recording part but the problem still occurs (readyForMoreMediaData is always NO).

我的代码:

- (void)startRecordingWithAssetWriter {
    NSLog(@"Setting up capture session");
    captureSession = [[AVCaptureSession alloc] init];

    //----- ADD INPUTS -----
    NSLog(@"Adding video input");

    //ADD VIDEO INPUT
    AVCaptureDevice *videoCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if (videoCaptureDevice) {
        NSError *error;
        videoInputDevice = [AVCaptureDeviceInput deviceInputWithDevice:videoCaptureDevice error:&error];
        if (!error) {
            if ([captureSession canAddInput:videoInputDevice]) {

                [captureSession addInput:videoInputDevice];
            } else {
                NSLog(@"Couldn't add video input");
            }
        } else {
            NSLog(@"Couldn't create video input");
        }
    } else {
        NSLog(@"Couldn't create video capture device");
    }

    //ADD AUDIO INPUT
    NSLog(@"Adding audio input");
    AVCaptureDevice *audioCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
    NSError *error = nil;
    AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioCaptureDevice error:&error];
    NSLog(@"Added audio input: %@", error.description);
    if (audioInput) {
        [captureSession addInput:audioInput];
    }


    //----- ADD OUTPUTS -----

    captureQueue = dispatch_queue_create("com.recordingtest", DISPATCH_QUEUE_SERIAL);


    //-- Create the output for the capture session.
    videoOutput = [[AVCaptureVideoDataOutput alloc] init];
    [videoOutput setAlwaysDiscardsLateVideoFrames:YES];

    [videoOutput setVideoSettings:
     [NSDictionary dictionaryWithObject:
      [NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange]
                                 forKey:(id)kCVPixelBufferPixelFormatTypeKey]];

    [videoOutput setSampleBufferDelegate:self queue:captureQueue];

    if ([captureSession canAddOutput:videoOutput]) {
        NSLog(@"Added video Output");
        [captureSession addOutput:videoOutput];
    }

//    audioOutput = [[AVCaptureAudioDataOutput alloc] init];
//    [audioOutput setSampleBufferDelegate:self queue:captureQueue];
//    
//    if ([captureSession canAddOutput:audioOutput]) {
//        NSLog(@"Added audio Output");
//        [captureSession addOutput:audioOutput];
//    }

    //Create temporary URL to record to
    NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mp4"];
    NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:outputPath])
    {
        NSError *error;
        if ([fileManager removeItemAtPath:outputPath error:&error] == NO)
        {
            //Error - handle if requried
        }
    }
    NSError *assetWriterError;
    assetWriter = [AVAssetWriter assetWriterWithURL:outputURL fileType:AVFileTypeMPEG4 error:&assetWriterError];
    if (assetWriterError) {

        NSLog(@"Error Setting assetWriter: %@", assetWriterError);
    }
    if (assetWriter != nil) {

    } else {

        NSLog(@"Error Setting assetWriter: %@", assetWriterError);
    }
    assetWriterVideoIn = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:nil];
    assetWriterVideoIn.expectsMediaDataInRealTime = YES;
//    assetWriterAudioIn = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:nil];
//    assetWriterAudioIn.expectsMediaDataInRealTime = YES;
    isRecording = YES;


    if ([assetWriter canAddInput:assetWriterVideoIn]) {
        [assetWriter addInput:assetWriterVideoIn];
    }
//    if ([assetWriter canAddInput:assetWriterAudioIn]) {
//        [assetWriter addInput:assetWriterAudioIn];
//    }



    [captureSession commitConfiguration];

    [captureSession startRunning];

}



- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection {
    NSLog(@"didOutputSampleBuffer");


    CFRetain(sampleBuffer);

    dispatch_async(captureQueue, ^{

        if (assetWriter) {

            if (isRecording) {
                if (captureOutput == videoOutput) {
                    [self writeSampleBuffer:sampleBuffer ofType:AVMediaTypeVideo];
                }
//                else if (captureOutput == audioOutput) {
//                    [self writeSampleBuffer:sampleBuffer ofType:AVMediaTypeAudio];
//                }
            }


        }

        CFRelease(sampleBuffer);
    });

}

- (void)writeSampleBuffer:(CMSampleBufferRef)sampleBuffer ofType:(NSString *)mediaType {
    NSLog(@"writeSampleBuffer: %ld", (long) assetWriter.status);
    CMTime presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);

    if (assetWriter.status == AVAssetWriterStatusUnknown) {

        if ([assetWriter startWriting]) {
            NSLog(@"startSessionAtSourceTime");
            [assetWriter startSessionAtSourceTime:presentationTime];
        } else {
            NSLog(@"Error writing initial buffer");
        }
    }

    if (assetWriter.status == AVAssetWriterStatusWriting) {

        if (mediaType == AVMediaTypeVideo) {
            NSLog(@"assetWriterVideoIn.readyForMoreMediaData: %d", assetWriterVideoIn.readyForMoreMediaData);

            if (assetWriterVideoIn.readyForMoreMediaData) {
                NSLog(@"appendSampleBuffer");

                if (![assetWriterVideoIn appendSampleBuffer:sampleBuffer]) {
                    NSLog(@"Error writing video buffer");
                }
            }
        }
//        else if (mediaType == AVMediaTypeAudio) {
//            if (assetWriterAudioIn.readyForMoreMediaData) {
//
//                if (![assetWriterAudioIn appendSampleBuffer:sampleBuffer]) {
//                    NSLog(@"Error writing audio buffer");
//                }
//            }
//        }
    }
}

推荐答案

设置了assetWriterVideoIn = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:nil];后,它终于可以工作了 以获得一些实际设置,而不是零.

It finally worked after I set assetWriterVideoIn = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:nil]; to get some actual settings instead of nil.

更改为:

NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey,
                          [NSNumber numberWithInt:480], AVVideoWidthKey,[NSNumber numberWithInt:640], AVVideoHeightKey, nil];

assetWriterVideoIn = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:settings];

这篇关于使用AVAssetWriter录制视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆