samedi 1 août 2015

Record MPMoviePlayerController video with sound

Im trying to implement subject. For that I was able to record the video but not the audio. That audio does not get recorded. Here is my sample code.

-(BOOL) setUpWriter {
NSError* error = nil;
videoWriter = [[AVAssetWriter alloc] initWithURL:[self tempFileURL] fileType:AVFileTypeQuickTimeMovie error:&error];
NSParameterAssert(videoWriter);

//Configure video
NSDictionary* videoCompressionProps = [NSDictionary dictionaryWithObjectsAndKeys:
                                       [NSNumber numberWithDouble:1960000], AVVideoAverageBitRateKey,
                                       [NSNumber numberWithInt:1],AVVideoMaxKeyFrameIntervalKey,
                                       nil ];

NSDictionary* videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                               AVVideoCodecH264, AVVideoCodecKey,
                               [NSNumber numberWithInt:self.frame.size.width], AVVideoWidthKey,
                               [NSNumber numberWithInt:self.frame.size.height], AVVideoHeightKey,
                               videoCompressionProps, AVVideoCompressionPropertiesKey,
                               nil];

videoWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings] retain];

NSParameterAssert(videoWriterInput);
videoWriterInput.expectsMediaDataInRealTime = YES;
NSDictionary* bufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, nil];

avAdaptor = [[AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput sourcePixelBufferAttributes:bufferAttributes] retain];



// Setup the audio input
AVCaptureDevice *audioDevice     = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeAudio];
AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error ];
// Setup the audio output
_audioOutput = [[AVCaptureAudioDataOutput alloc] init];

// Create the session
_capSession = [[AVCaptureSession alloc] init];
[_capSession addInput:audioInput];
[_capSession addOutput:_audioOutput];

_capSession.sessionPreset = AVCaptureSessionPresetMedium;

// Setup the queue
dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL);
[_audioOutput setSampleBufferDelegate:self queue:queue];
dispatch_release(queue);

// Add the audio input
AudioChannelLayout acl;
bzero( &acl, sizeof(acl));
acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;

double preferredHardwareSampleRate;

AVAudioSession* sharedAudioSession = [AVAudioSession sharedInstance];
if (![sharedAudioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error]) {
    NSLog(@"AVAudioSession setCategory failed: %@", [error localizedDescription]);
}

// Set audio session property "allow mixing" to true so audio can be recorded while it is playing
UInt32 allowMixing = true;
OSStatus status = AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(allowMixing), &allowMixing);
if (status != kAudioSessionNoError) {
    NSLog(@"AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers) failed: %ld", status);
}

// Activate the audio session
error = nil;
if (![sharedAudioSession setActive:YES error:&error]) {
    NSLog(@"AVAudioSession setActive:YES failed: %@", [error localizedDescription]);
}

if ([sharedAudioSession respondsToSelector:@selector(sampleRate)])
{
    preferredHardwareSampleRate = [sharedAudioSession sampleRate];
}
else
{
    preferredHardwareSampleRate = [[AVAudioSession sharedInstance] currentHardwareSampleRate];

}


NSDictionary* audioOutputSettings = nil;

audioOutputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                       [ NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
                       [ NSNumber numberWithInt: 1 ], AVNumberOfChannelsKey,
                       [ NSNumber numberWithFloat: preferredHardwareSampleRate ], AVSampleRateKey,
                       [ NSData dataWithBytes: &acl length: sizeof( acl ) ], AVChannelLayoutKey,
                       //[ NSNumber numberWithInt:AVAudioQualityLow], AVEncoderAudioQualityKey,
                       [ NSNumber numberWithInt: 64000 ], AVEncoderBitRateKey,
                       nil];

audioWriterInput = [[AVAssetWriterInput
                      assetWriterInputWithMediaType: AVMediaTypeAudio
                      outputSettings: audioOutputSettings ] retain];

audioWriterInput.expectsMediaDataInRealTime = YES;

[_capSession startRunning] ;

//add input
[videoWriter addInput:videoWriterInput];
[videoWriter addInput:audioWriterInput];

[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:CMTimeMake(0, 1000)];

return YES;

}

Here is my capture output method

   - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection
{

    if( !CMSampleBufferDataIsReady(sampleBuffer) )
    {
        NSLog( @"sample buffer is not ready. Skipping sample" );
        return;
    }


    if( _recording == YES )
    {

        [self newAudioSample:sampleBuffer];
    }
}

And new audio sample method

-(void) newAudioSample:(CMSampleBufferRef)sampleBuffer

{
    if( _recording )
    {
        if( ![audioWriterInput appendSampleBuffer:sampleBuffer] )
            NSLog(@"Unable to write to audio input");

    }
}

1 commentaire:

  1. i make a karaoke app. it is recording success (background mp3 and my voice mix) when headphone was not plugin. but headphone plugin and listen to record, i cant hear background music (its too low). how can i do that? please help me. Can i mix (maybe merge audio and voice on playtime ) when headphone plugin? SO i decided save youtube to iphone and after mix with voice.

    RépondreSupprimer