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).
Related
When a video is played during a webRTC call it causes the local stream to go mute without muting the track (audio track still has the enabled prop set to true). It does not happen when the 'muted' prop of the Video component is set to true or when the video stats playing before the call is started, but after muting or unmuting the video during the call, the microphone still disconnects. The Video component must be accessing the microphone. Do you know how to fix it? Happens on IOS 14, Xcode 12.2
I fixed it thanks to this post. It was a problem with AVAudioSession in ios/Video/RTCVideo.m. It turns out that the default settings in AVFoundation allow for the use of either Microphone or the Speaker (one at a time), so mounting Video component, or performing any actions that establish AVAudioSession interferes with other components using the microphone.
I changed this part of the code:
- (void)setPaused:(BOOL)paused
{
if (paused) {
[_player pause];
[_player setRate:0.0];
} else {
if([_ignoreSilentSwitch isEqualToString:#"ignore"]) {
// [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; OLD
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayAndRecord error:nil]; //NEW
} else if([_ignoreSilentSwitch isEqualToString:#"obey"]) {
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
}
[_player play];
[_player setRate:_rate];
}
_paused = paused;
}
This fix will work only if the ignoreSilentSwitch in Video component is set to 'ignore'
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.");
}
}
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.
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;
}
I have to give audio feedback when my app is in foreground and also in background. But when the app enters background audio feedback is not heard. In info.plist I have set background mode to App plays audio or streams audio/video using AirPlay and used the following but the audioPlayerDidFinishPlaying delegate is not called when app enters background and audio is not heard.
AVAudioPlayer *sound = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&err];
sound.delegate = self;
///Fixed the issue No audible feedback when main audio is silent
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
// This is necessary if you want to play a sequence of songs, otherwise your app will be
// killed after the first one finishes.
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[soundQueue addObject:sound];
You need to make couple of changes in plist file.
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 in background.
It works fine for me. :)
for more please refer to Playing Audio in background mode and Audio Session Programming Guide