Note that there are some explanatory texts on larger screens.

plurals
  1. POThis code to write video+audio through AVAssetWriter and AVAssetWriterInputs is not working. Why?
    text
    copied!<p>I've been trying to write a video+audio using AVAssetWriter and AVAssetWriterInputs.</p> <p>I read multiple posts in this forum of people saying they were able to accomplish that, but it is not working for me. If I just write video then the code is doing its job very well. When I add audio the output file is corrupted and cannot be reproduced.</p> <p>Here is part of my code:</p> <p>Setting up AVCaptureVideoDataOutput and AVCaptureAudioDataOutput:</p> <pre><code>NSError *error = nil; // Setup the video input AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; // Create a device input with the device and add it to the session. AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&amp;error]; // Setup the video output _videoOutput = [[AVCaptureVideoDataOutput alloc] init]; _videoOutput.alwaysDiscardsLateVideoFrames = NO; _videoOutput.videoSettings = [NSDictionary dictionaryWithObject: [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]; // Setup the audio input AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeAudio]; AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&amp;error ]; // Setup the audio output _audioOutput = [[AVCaptureAudioDataOutput alloc] init]; // Create the session _capSession = [[AVCaptureSession alloc] init]; [_capSession addInput:videoInput]; [_capSession addInput:audioInput]; [_capSession addOutput:_videoOutput]; [_capSession addOutput:_audioOutput]; _capSession.sessionPreset = AVCaptureSessionPresetLow; // Setup the queue dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL); [_videoOutput setSampleBufferDelegate:self queue:queue]; [_audioOutput setSampleBufferDelegate:self queue:queue]; dispatch_release(queue); </code></pre> <p>Setting up AVAssetWriter and associating both audio and video AVAssetWriterInputs to it:</p> <pre><code>- (BOOL)setupWriter { NSError *error = nil; _videoWriter = [[AVAssetWriter alloc] initWithURL:videoURL fileType:AVFileTypeQuickTimeMovie error:&amp;error]; NSParameterAssert(_videoWriter); // Add video input NSDictionary *videoCompressionProps = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithDouble:128.0*1024.0], AVVideoAverageBitRateKey, nil ]; NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoCodecH264, AVVideoCodecKey, [NSNumber numberWithInt:192], AVVideoWidthKey, [NSNumber numberWithInt:144], AVVideoHeightKey, videoCompressionProps, AVVideoCompressionPropertiesKey, nil]; _videoWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings] retain]; NSParameterAssert(_videoWriterInput); _videoWriterInput.expectsMediaDataInRealTime = YES; // Add the audio input AudioChannelLayout acl; bzero( &amp;acl, sizeof(acl)); acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; NSDictionary* audioOutputSettings = nil; // Both type of audio inputs causes output video file to be corrupted. if (NO) { // should work from iphone 3GS on and from ipod 3rd generation audioOutputSettings = [NSDictionary dictionaryWithObjectsAndKeys: [ NSNumber numberWithInt: kAudioFormatMPEG4AAC ], AVFormatIDKey, [ NSNumber numberWithInt: 1 ], AVNumberOfChannelsKey, [ NSNumber numberWithFloat: 44100.0 ], AVSampleRateKey, [ NSNumber numberWithInt: 64000 ], AVEncoderBitRateKey, [ NSData dataWithBytes: &amp;acl length: sizeof( acl ) ], AVChannelLayoutKey, nil]; } else { // should work on any device requires more space audioOutputSettings = [ NSDictionary dictionaryWithObjectsAndKeys: [ NSNumber numberWithInt: kAudioFormatAppleLossless ], AVFormatIDKey, [ NSNumber numberWithInt: 16 ], AVEncoderBitDepthHintKey, [ NSNumber numberWithFloat: 44100.0 ], AVSampleRateKey, [ NSNumber numberWithInt: 1 ], AVNumberOfChannelsKey, [ NSData dataWithBytes: &amp;acl length: sizeof( acl ) ], AVChannelLayoutKey, nil ]; } _audioWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType: AVMediaTypeAudio outputSettings: audioOutputSettings ] retain]; _audioWriterInput.expectsMediaDataInRealTime = YES; // add input [_videoWriter addInput:_videoWriterInput]; [_videoWriter addInput:_audioWriterInput]; return YES; } </code></pre> <p>here are functions to start/stop video recording</p> <pre><code>- (void)startVideoRecording { if (!_isRecording) { NSLog(@"start video recording..."); if (![self setupWriter]) { return; } _isRecording = YES; } } - (void)stopVideoRecording { if (_isRecording) { _isRecording = NO; [_videoWriterInput markAsFinished]; [_videoWriter endSessionAtSourceTime:lastSampleTime]; [_videoWriter finishWriting]; NSLog(@"video recording stopped"); } } </code></pre> <p>And finally the CaptureOutput code</p> <pre><code>- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { if (!CMSampleBufferDataIsReady(sampleBuffer)) { NSLog( @"sample buffer is not ready. Skipping sample" ); return; } if (_isRecording == YES) { lastSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); if (_videoWriter.status != AVAssetWriterStatusWriting ) { [_videoWriter startWriting]; [_videoWriter startSessionAtSourceTime:lastSampleTime]; } if (captureOutput == _videoOutput) { [self newVideoSample:sampleBuffer]; } /* // If I add audio to the video, then the output file gets corrupted and it cannot be reproduced } else { [self newAudioSample:sampleBuffer]; } */ } } - (void)newVideoSample:(CMSampleBufferRef)sampleBuffer { if (_isRecording) { if (_videoWriter.status &gt; AVAssetWriterStatusWriting) { NSLog(@"Warning: writer status is %d", _videoWriter.status); if (_videoWriter.status == AVAssetWriterStatusFailed) NSLog(@"Error: %@", _videoWriter.error); return; } if (![_videoWriterInput appendSampleBuffer:sampleBuffer]) { NSLog(@"Unable to write to video input"); } } } - (void)newAudioSample:(CMSampleBufferRef)sampleBuffer { if (_isRecording) { if (_videoWriter.status &gt; AVAssetWriterStatusWriting) { NSLog(@"Warning: writer status is %d", _videoWriter.status); if (_videoWriter.status == AVAssetWriterStatusFailed) NSLog(@"Error: %@", _videoWriter.error); return; } if (![_audioWriterInput appendSampleBuffer:sampleBuffer]) { NSLog(@"Unable to write to audio input"); } } } </code></pre> <p>I would be very glad if someone could find which is the problem in this code.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload