AVCaptureSession record audio from bluetooth microphone - ios

From searching today I think it is still not possible to use a Bluetooth headset microphone as the audio input for an AVCaptureSession (video recording) on an iOS device even with the audio changes made in iOS7. However in case I just haven't looked hard enough has anyone found a way to achieve this?
According to the apple docs kAudioSessionProperty_OverrideCategoryEnableBluetoothInput can be set for the kAudioSessionCategory_RecordAudio or kAudioSessionCategory_PlayAndRecord categories. However the AudioSessionSetProperty method required to do this has been depreciated. Ignoring that and just using it I still can't find a way to utilize this to get the bluetooth audio passed to a video recording.

I was able to get this to work in iOS7+ by configuring the audio session associated with my AVCapture session:
AVCaptureSession *cs = [[AVCaptureSession alloc] init];
self.captureSession = cs;
self.captureSession.usesApplicationAudioSession = true;
self.captureSession.automaticallyConfiguresApplicationAudioSession = true;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
Good Luck.

I solved same problem by setting 'automaticallyConfiguresApplicationAudioSession' to 'NO'.
But it would cause background music very low without airpods. And i fixed it by adding 'AVAudioSessionCategoryOptionDefaultToSpeaker' to options.
This is my code:
self.captureSession = [[AVCaptureSession alloc] init];
self.captureSession.usesApplicationAudioSession = YES;
self.captureSession.automaticallyConfiguresApplicationAudioSession = NO;
BOOL success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker
|AVAudioSessionCategoryOptionAllowBluetooth
error:&error];
if (!success) {
NSLog(#"setCategory error:%#", error);
return NO;
}

Related

Preventing no-audio AVPlayer from pausing background audio

I understand that based on AVAudioSession category AVPlayer will pause background audio currently played by other app when starting its playback. I wonder if this is the expected behavior regardless of the type item/content being played?
I'm asking as in my case showing video with no sound. The video files contain no audio track. AVPlayer itself is also set to muted. It just a little weird to me that I still have to change to AVAudioSession category even though I do not produce audio. So I want to know if that is by design or if there is something that I miss. For example, could I set up AVPlayer with no audio session so that it knows not to worry about audio or something like that.
No. Just set the audio category to "Ambient" so that it doesn't step on any other audio:
AVAudioSession *session = [AVAudioSession sharedInstance];
if (session) {
NSError *setCategoryError = nil;
BOOL success = [session setCategory:AVAudioSessionCategoryAmbient error:&setCategoryError];
if (success) {
NSError *activationError = nil;
[session setActive:YES error:&activationError];
} else {
NSLog(#"Failed to set music category to ambient. May interrupt other audio.");
}
}

In iOS created application to force audio output via speaker, but doesn't work when application is in background

I want to implement, when i plugged in headset/headphone in iPhone and play any music, music should play from speaker instead of headphone.
So using this below code that working fine when my application is in foreground. But when my application goes in background that time this code is not working.
I want to implement this functionality in 3 case
When application is in foreground.
When application is in background.
When application remove from backgound.
Please give me solution for that.
I have used this below code,
+ (void) initAudioSessionRouting{
// Called once to route all audio through speakers, even if something's plugged into the headphone jack
static BOOL audioSessionSetup = NO;
if (audioSessionSetup == NO) {
// set category to accept properties assigned below
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error: &sessionError];
// Doubly force audio to come out of speaker
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);
// fix issue with audio interrupting video recording - allow audio to mix on top of other media
UInt32 doSetProperty = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(doSetProperty), &doSetProperty);
// set active
[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
// add listener for audio input changes
AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, onAudioRouteChange, nil );
AudioSessionAddPropertyListener (kAudioSessionProperty_AudioInputAvailable, onAudioRouteChange, nil );
}
// Force audio to come out of speaker
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
// set flag
audioSessionSetup = YES;}
Thanks in advance

AVCaptureSession addInput causing glitch in background audio

I'm making a video capturing iOS app and I want to be able to record audio from the microphone while allowing background music to play. I can do all of this but the background audio skips (pauses briefly) whenever the view with the camera enters and exits the foreground. I have isolated the bug to AVCaptureSession addInput:
AVCaptureSession session = [[AVCaptureSession alloc] init];
session.automaticallyConfiguresApplicationAudioSession = NO;
AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
AVCaptureDeviceInput *audioDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil];
// this line causes the background music to skip
[session addInput:audioDeviceInput];
How can I prevent adding microphone input from affecting the background audio?
fyi - in didFinishLaunchingWithOptions I set the AVAudioSession Category:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDefaultToSpeaker
error:nil];
Apparently there is no workaround.
https://forums.developer.apple.com/message/74778#74778

Play MPMoviePlayerController audio stream in background

So I have this app where I play videos and when you exit the app I would like the user to continue to listen to the audio of the video. I use MPMoviePlayerController to play the video and it works in the app perfectly fine. I also setup AVAudioSession up before I play the video and I get no error.
NSError *audioSessionError;
NSError *activationError;
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:&audioSessionError];
[audioSession setActive:YES error:&activationError];
I also set in plist background modes audio. But the video with the audio both stop playing when you close the app. I've also imported the AVFoundation framework.
Simply set Application does not run in background to NO in .plsit file
You need to make couple of changes in plist file.i.e.
1) Set Required background mode to App plays audio
2) set Application does not run in background to YES.
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
Then, you need to write these much code in AppDelegate
Now, you can easily run audio while phone screen locks or goes in background.
This code worked for me, first you must to give your app permissions to keep playing music in the background (In your .plis), after that go to the wished class and implement this code, first the imports and the the method to play the music.
#import <MediaPlayer/MPNowPlayingInfoCenter.h>
#import <MediaPlayer/MPMediaItem.h>
#import <AVFoundation/AVFoundation.h>
---- o ----
-(void) playMusic{
[[AVAudioSession sharedInstance] setDelegate: self];
NSError *myErr;
// Initialize the AVAudioSession here.
if (![[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&myErr]) {
// Handle the error here.
NSLog(#"Audio Session error %#, %#", myErr, [myErr userInfo]);
}else{
// Since there were no errors initializing the session, we'll allow begin receiving remote control events
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}
//initialize our audio player
audioPlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:#"http://www.cocoanetics.com/files/Cocoanetics_031.mp3"]];
[audioPlayer setShouldAutoplay:NO];
[audioPlayer setControlStyle: MPMovieControlStyleEmbedded];
audioPlayer.view.hidden = YES;
[audioPlayer prepareToPlay];
[audioPlayer play];
}//end playmusic
You need to turn on Background Modes in capabilities.

AVAudioSession record while playing weird issue

For part of an app that I'm making I need to record audio from the user. I have chosen to use AVAudioRecorder to do this.
The problem is that when I start to record audio, all audio playing on the device is paused. I then looked in the Apple docs for AVAudioSession and set the recording options to be: AVAudioSessionCategoryOptionMixWithOthers.
The problem is that whenever I start recording, any audio playing on the device switches from the main external speaker to the small phone (call) speaker.
My goal is to record audio while still allowing all other audio from the device to be outputted through the main speaker.
How can I achieve this?
Here's my code currently:
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
[audioSession setActive:YES error:&error];
recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
if(recorder != nil){
[recorder prepareToRecord];
recorder.meteringEnabled = YES;
[recorder record];
levelTimer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:#selector(levelTimerCallback:) userInfo:nil repeats:YES];
}else{
NSLog(#"Error: %#",[error description]);
}//end if
Thanks!
Maybe you can try using AVAudioSessionCategoryOptionDefaultToSpeaker. According to the AVAudioSession reference:
When using this option and no other audio route (such as a headset) is available, session audio will play through the device’s built-in speaker. When not using this option, and no other audio output is available or selected, audio will play through the receiver (a speaker intended to be held to the ear).

Resources