AVAudioSession deactivate while another session is running - ios

I have one audio session running in playAndRecord category and mixWithOthers option for a audio recorder. Let's call it recordAudioSession.
let recordAudioSession = AudioSession()
recordAudioSession.setCategory(.playAndRecord, options: [.mixWithOthers])
Also I have another audio session running in playback category and mixWithOthers option for playing audio stream. Let's call it playAudioSession.
let playAudioSession= AudioSession()
playAudioSession.setCategory(.playback, options: [.mixWithOthers])
I have one audio is playing through my playAudioSession using an AVAudioPlayer, at the same time there is a recorder is running through my recordAudioSession trying to record the audio.
Now, once audio finishes playing, I try to deactivate playAudioSession, but leave recordAudioSession alive:
audioPlayer.stop()
playAudioSession.setActive(false, options: .notifyOthersOnDeactivation)
So basically, One session finishes its task and I want to deactivate, the other one is still in use, so I want to keep it working.
But I'm getting an error log, and my recorder getting closed by system:
AVAudioSession.mm:692: -[AVAudioSession setActive:withOptions:error:]: Deactivating an audio session that has running i/o. all i/o should be stopped or paused prior to deactivating the audio session.
Is this error means any audio session cannot be running I/O while deactivating an audio session, or I'm doing it in an incorrect way?
Is there any way that I can keep that recorder reading and deactivate the playAudioSession?

Related

Swift Stop System Audio

I'm developing a Sleep Timer App. As soon as the timer is done, I want to stop the audio on the device. Is there any way to stop the system Sound or do I have to play a silent audio file?
I already tried this Code:
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
try AVAudioSession.sharedInstance().setActive(true)
} catch { print(error.localizedDescription) }
.playback will only pause non-mixable sessions. If the other app has a mixable session, then it will continue. The only mode that will pause mixable sessions is .record (which will require that you request recording permission, even though you're not going to use it).

Audio ducking stops when AVAssetWriter.startWriting is called

We have an app where we play some audio while ducking any sounds from other apps that might be playing (music, spotify, etc).
This works most of the time and external audio is ducked properly. However whenever we call on an AVAssetWriter instance to startWriting, the ducking stops entirely and never resumes. The only way to resume it seems to be stopping the session and restarting it, setting the category again doesn't do anything. Has anyone run into similar problems with ducking and have any solutions? Thanks!
...
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .spokenAudio, options: [.duckOthers, .interruptSpokenAudioAndMixWithOthers])
try AVAudioSession.sharedInstance().setActive(true)
...
self.assetWriter.startWriting()
...

Error: Deactivating an audio session that has running I/O

My app uses device's microphone and manages AVAudioSession.
I want to check if there is other app playing audio, if so, I want my app to stop using microphone & stop my audio session, this is what I tried (the following code is periodically triggered to check is there other app playing audio):
BOOL isPlayingWithOthers = [[AVAudioSession sharedInstance] isOtherAudioPlaying];
if (isPlayingWithOthers) {
[[AVAudioSession sharedInstance] setActive:NO error:error];
}
I run my app, then, I open "My music" app, and playing a music, the above code is executed but I get the following error:
Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.
Why I get this error? How to solve it in my case? (My app is running on iOS7 and above)

Stop audio recording and continue audio playback

My application plays music and records from mic at the same time. Recording can be started after playback is started or before playback is started
And now I want to stop recording but keep playback running at the same time.
How can I do this?
I can stop recording and playback by using
[[AVAudioSession sharedInstance] setActive:NO error:nil];
But the issue is: I want to stop recording only.
I tried to change category to AVAudioSessionCategoryPlayback using the following code
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error]
but that doesn't stop recording.
I solved the issue by explicitly stopping all recording activity without touching AVAudioSession at all.
The following warning
AVAudioSession.mm:623: -[AVAudioSession setActive:withOptions:error:]:
Deactivating an audio session that has running I/O. All I/O should be
stopped or paused prior to deactivating the audio session.
helped me to identify the issue.
Initially I forgot to call the AudioOutputUnitStop method of AudioUnit framework. Because of this recording process was still running and audio session were indicating that.

How to get SpeechKit and AVCaptureDevice to work with each other

I am using SpeechKit from Nuance to transcribe text from video as I record it. However, when SpeechKit is active, AVAudioSession generates the following error:
AVAudioSession.mm:646: -[AVAudioSession setActive:withOptions:error:]: Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.
Disabling SpeechKit lets me record and preview the video. Enabling it generates the transcribed text, but doesn't record the video.
I have put a sample project online at:
https://github.com/jeffreality/iOSVideoTranscriber
My goal is to save the video with audio, as well as have a transcription.
You can move the following line to viewDidLoad:
#if ENABLE_TRANSCRIPTION
[SpeechKit setupWithID:#"Your ID"
host:#"dfo.nmdp.nuancemobility.net"
port:443
useSSL:NO
delegate:nil];
#endif
This ensures that speechKit has already been set up when you create your own capture session in viewDidAppear.
SpeechKit delegate method recognizerDidFinishRecording is called when the recognizer stops recording audio. It is automatically called when a silence is detected, or manually called when you do [voiceSearch stopRecording]. When this happens, your own recording has not finished, it needs time to save the audio file to disk, and the error message says all i/o should stop prior to deactivating an audio session. You can see a log by the sdk release audio session 1, which I think is deactivating a session and release it. So I think you should add this in the above method.
[[self.session.outputs[1] connectionWithMediaType:AVMediaTypeAudio] setEnabled:NO];
The output is AVCaptureMovieFileOutput you set up earlier, and connection is an audio connection, doing this seems to make the error disappear.

Resources