AVCaptureSession does not record audio on iPad 2 - ios

I've been making this app that includes recording a video together with audio. The videorecording works as it should, and on most devices, so does the audo recording.
Except, on an iPad 2 (iOS 6.1.3) the audio recording does not work. In the official "Camera" app, the audio recording works flawlessly, so it's not a device-dependent problem.
This is the code:
NSURL *outputFileURL = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#%#", NSTemporaryDirectory(), #"output.mov"]];
NSError *error;
AVCaptureDevice *device = [self frontCamera];
AVCaptureDeviceInput *inputVideo = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
self.session = [[AVCaptureSession alloc] init];
[self.session beginConfiguration];
if([device supportsAVCaptureSessionPreset:AVCaptureSessionPreset1280x720]){
[self.session setSessionPreset:AVCaptureSessionPreset1280x720];
} else if([device supportsAVCaptureSessionPreset:AVCaptureSessionPresetiFrame960x540]){
[self.session setSessionPreset:AVCaptureSessionPresetiFrame960x540];
} else if([device supportsAVCaptureSessionPreset:AVCaptureSessionPreset640x480]){
[self.session setSessionPreset:AVCaptureSessionPreset640x480];
}
self.recorder = [[AVCamRecorder alloc] initWithSession:self.session outputFileURL:outputFileURL];
[self.recorder setDelegate:self];
AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
NSError *audioError;
AVCaptureDeviceInput *inputAudio = [[AVCaptureDeviceInput alloc] initWithDevice:audioDevice error:&audioError];
NSLog(#"AudioError: %#", audioError);
NSLog(#"InputAudio: %#", inputAudio);
[self.session addInput:inputVideo];
[self.session addInput:inputAudio];
[self.session commitConfiguration];
[self.session startRunning];
In the log, "audioError" is null and "inputAudio“ seems to be a valid variable.
Any idea on how to fix this?

Related

AVFoundation custom video recorder audio issues

I try to learn how to create custom video recorder, everything work fine except when the audio having a lot of noisy sound. I try in the system camera, instagram or any other camera app their audio quality is very good and don't have some kind of low level sound. Beside, the recorded volume of the video also significantly lower compare to other camera app. I can't found any answer on stackoverflow which most of them having answer about AVAudioSession but not on AVCaptureSession.
Here is the code how I implement the recorder
_session = [[AVCaptureSession alloc]init];
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
AVCaptureDeviceInput *audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:[devices objectAtIndex:0] error:nil];
if ([_session canAddInput:audioInput])
[_session addInput:audioInput];
AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:nil];
if ( [_session canAddInput:deviceInput] )
[_session addInput:deviceInput];
_videoOutput = [[AVCaptureVideoDataOutput alloc] init];
_videoOutput.alwaysDiscardsLateVideoFrames = NO;
if ( [_session canAddOutput:_videoOutput] )
[_session addOutput:_videoOutput];
_audioOutput = [[AVCaptureAudioDataOutput alloc] init];
if ( [_session canAddOutput:_audioOutput] )
[_session addOutput:_audioOutput];
AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_session];
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
CALayer *rootLayer = [[self view] layer];
[rootLayer setMasksToBounds:YES];
[previewLayer setFrame:CGRectMake(0, 0, rootLayer.bounds.size.width, rootLayer.bounds.size.height)];
[rootLayer insertSublayer:previewLayer atIndex:0];
[_session setSessionPreset:AVCaptureSessionPresetHigh];
dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL);
[_videoOutput setSampleBufferDelegate:self queue:queue];
[_audioOutput setSampleBufferDelegate:self queue:queue];
AVCaptureConnection *videoConnection = [_videoOutput connectionWithMediaType:AVMediaTypeVideo];
[videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];
[_session startRunning];
The video quality is fine and the code working, just having trouble on the audio part. So
How can I improve the audio quality when recording a video?
How can I increase the recording volume of the video?
I know how to increase it when just pure recording an audio with the code below but not when recording video.
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:(AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionAllowBluetooth) error:&sessionCategoryError];
Ok I finally figure it out. After create the AVCaptureSession do the following code.
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:(AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionAllowBluetooth) error:nil];
[audioSession setActive:YES error:nil];
_session = [[AVCaptureSession alloc]init];
//the 2 line below is very important.
_session.usesApplicationAudioSession = YES;
_session.automaticallyConfiguresApplicationAudioSession = NO;
Now the ouput audio of the video is even better than the system

I am trying to switch this code to use the front camera

I am new to programming, and trying to fix this code to use the front camera instead of defaulting to the back. I'm not sure what I need to change to make this work properly.
Here is my sample code:
-(void)viewWillAppear:(BOOL)animated{
session = [[AVCaptureSession alloc] init];
[session setSessionPreset:AVCaptureSessionPresetPhoto];
AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error;
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&error];
if ([session canAddInput:deviceInput]) {
[session addInput:deviceInput];
}
AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
CALayer *rootLayer = [[self view] layer];
[rootLayer setMasksToBounds:YES];
CGRect frame = self.frameForCapture.frame;
[previewLayer setFrame:frame];
[rootLayer insertSublayer:previewLayer atIndex:0];
stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG, AVVideoCodecKey, nil];
[stillImageOutput setOutputSettings:outputSettings];
[session addOutput:stillImageOutput];
[session startRunning];
Replace this:
AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error;
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&error];
With this:
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
AVCaptureDevice *frontCamera;
for (AVCaptureDevice *dev in devices) {
if (dev.position == AVCaptureDevicePositionFront) {
frontCamera = dev;
break;
}
}
if (!frontCamera) {
NSLog(#"No front camera found!");
// Handle no front camera error
}
NSError *error;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:frontCamera error:&error];

iOS8 : Custom Keyboard - Open Camera with AVCaptureVideoPreviewLayer in the background of keyboard

It is posible to open AVCaptureVideoPreviewLayer in the background of iOS8 Custom keyboard ?
I tried with this code
AVCaptureSession *session = [[AVCaptureSession alloc] init];
AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (videoDevice)
{
NSError *error;
AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
if (!error)
{
if ([session canAddInput:videoInput])
{
[session addInput:videoInput];
AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];
previewLayer.frame = self.bounds;
NSLog(#"open %#",NSStringFromCGRect(self.bounds));
[self.camView.layer addSublayer:previewLayer];
[session startRunning];
}
}
}
It is ask for permission to use camera but not open camera in background of keyboard.
Please help me.
Thanks.

Rotating AV video preview area on iPad

I'd like to use the video preview layer on the iPhone and the iPad, but on the iPad it doesn't rotate and it has the wrong height.
Here is the code I have:
- (void)capture
{
AVCaptureSession *session = [[AVCaptureSession alloc] init];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device
error:&error];
if (!input)
{
NSLog(#"Error: %#", error);
return;
}
[session addInput:input];
//Turn on point autofocus for middle of view
[device lockForConfiguration:&error];
CGPoint point = CGPointMake(0.5,0.5);
[device setFocusPointOfInterest:point];
[device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
[device unlockForConfiguration];
//Add the metadata output device
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[session addOutput:output];
NSLog(#"%lu",output.availableMetadataObjectTypes.count);
for (NSString *s in output.availableMetadataObjectTypes)
NSLog(#"%#",s);
//You should check here to see if the session supports these types, if they aren't support you'll get an exception
output.metadataObjectTypes = #[AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeQRCode];
output.rectOfInterest = self.livevideo.bounds;
AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
newCaptureVideoPreviewLayer.frame = self.view.layer.bounds;
newCaptureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.livevideo.layer insertSublayer:newCaptureVideoPreviewLayer above:self.livevideo.layer];
[session startRunning];
}
And:
- (void)captureFront
{
AVCaptureSession *session = [[AVCaptureSession alloc] init];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device
error:&error];
if (!input)
{
NSLog(#"Error: %#", error);
return;
}
[session addInput:input];
//Turn on point autofocus for middle of view
[device lockForConfiguration:&error];
CGPoint point = CGPointMake(0.5,0.5);
[device setFocusPointOfInterest:point];
[device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
[device unlockForConfiguration];
//Add the metadata output device
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[session addOutput:output];
NSLog(#"%lu",output.availableMetadataObjectTypes.count);
for (NSString *s in output.availableMetadataObjectTypes)
NSLog(#"%#",s);
//You should check here to see if the session supports these types, if they aren't support you'll get an exception
output.metadataObjectTypes = #[AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeQRCode];
output.rectOfInterest = self.livevideo.bounds;
AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
newCaptureVideoPreviewLayer.frame = self.view.layer.bounds;
newCaptureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[session startRunning];
}
Image

AVFoundation allows to easily spy you?

I recently discovered this: http://openradar.appspot.com/15880263
Correct me if I'm wrong, but those lines allows a Developer to spy the user without the user even noticing, right?
AVCaptureDevice *frontDevice = nil;
for (AVCaptureDevice *device in [AVCaptureDevice devices]) {
if (device.position == AVCaptureDevicePositionFront) {
frontDevice = device;
}
}
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:frontDevice error:nil];
AVCaptureMovieFileOutput *output = [[AVCaptureMovieFileOutput alloc] init];
session = [[AVCaptureSession alloc] init];
[session beginConfiguration];
[session addInput:input];
[session addOutput:output];
[session commitConfiguration];
[session startRunning];
// Wait X seconds
NSString *path = [DOCUMENTS_DIRECTORY stringByAppendingPathComponent:#"output.mov"];
NSURL *url = [NSURL fileURLWithPath:path];
[output startRecordingToOutputFileURL:url recordingDelegate:self];
and boom, I could send that output.mov to my own server, for example. This is terrible, unless I'm missing something.......

Resources