Microphone usage bug in VisionOS - showstopper

Ran into this in a more elaborate setup, reproduced with a minimal example:

    void Start()
    {
        AudioSource audioSource = GetComponent<AudioSource>();
        audioSource.clip = Microphone.Start("", true, 10, 44100);
        audioSource.Play();
    }

Will work on the build / install, then fail on every subsequent run and/or app update. Once uninstalled and reinstalled, permissions have to be given again, then it works once. Any further re-runs or app updates fail with the following generic error:

           AURemoteIO.cpp:1702  AUIOClient_StartIO failed (561145187)
Starting microphone failed: "An error occured trying to initialize the recording device. " (70)
MicTest:Start()

561145187 corresponds to AVAudioSessionErrorCodeCannotStartRecording, which notes:

This error type usually occurs when an app starts a mixable recording from the background and it isn’t configured as an Inter-App Audio app.

Maybe you’re trying to start the microphone too early, when the app is still starting up? Have you tried starting the microphone a frame later?

The reason why it works once could be related to the permission prompt, which delays the actual start of the recording session. Only when the permission is already granted is the session started immediately.

ah, good catch, thank you! I found that definition but didn’t have that intuition. Throwing a 2 second delay at it solves it most of the time, albeit not fully, which is interesting. I’ll keep debugging, but I think you nailed the root cause. Thank you!

I also have the similar problem microphone works on the build / install, then fail on every subsequent run and/or app update .

And I put the logic into the button click callback. so app is running for a while. then press the button.

Envirnment:
Unity 2022.3.24f1
PolySpatial XR 1.2.3
in bounded also in unbounded volume MR

using UnityEngine;

public class DemoMic : MonoBehaviour
{
    public void OnOkButtonClick()
    {
        Debug.Log("OnOkButtonClick");
        
        var clip = Microphone.Start("", true, 10, 44100);
// Starting microphone failed: "An error occured trying to initialize the recording device. " (70)
        
        Debug.Log("clip is null? " + (clip == null));
    }
    
    public void OnStopButtonClick()
    {
        Debug.Log("OnStopButtonClick");
        
        Microphone.End("");
        
        Debug.Log("Microphone.End");
    }
}

I am definitely not initializing the mic before app gets loaded but I get the same error:

AURemoteIO.cpp:1702 AUIOClient_StartIO failed (561145187)
Starting microphone failed: "An error occured trying to initialize the recording device. " (70)

Environment:
Polyspatial 1.1.6
Unity 2022.3.28
Unbounded MR

UPDATE: I found a fix! In UnityAppController.mm, the audio category was set to ambient. I changed it to AVAudioSessionCategoryPlayAndRecord. I also took out if statement, so from line 133, it looks like this:

    [audioSession setCategory: AVAudioSessionCategoryPlayAndRecord error: nil];
    [audioSession setActive: YES error: nil];
    [audioSession setIntendedSpatialExperience:AVAudioSessionSpatialExperienceBypassed options:@{} error:nil];
    [audioSession addObserver: self forKeyPath: @"outputVolume" options: 0 context: nil];
    UnityUpdateMuteState([audioSession outputVolume] < 0.01f ? 1 : 0);

Thanks oliran for the suggestion. That makes it work after a fresh install now but not in subsequent runs :frowning: Did you also find a way to “persist” the modified mm-file?

Yes! You can edit the file in /Applications/Unity/Hub/Editor/2022.3.21f1/PlaybackEngines/VisionOSPlayer/Trampoline/Classes/UnityAppController.mm

It will get reverted if you install a new version of Unity, but otherwise it’s persistent.

Thanks for the suggestion. For now we reverted back to x.20f1, where most of the features work. :slight_smile:

I’ve had this problem and noticed that the time that I need to wait for the microphone to be safe-to-initialize is very unpredictable.

I ended up resorting to creating a coroutine that opens the microphone and looks for non-zero samples in the recorded audioclip. Sometimes it takes only a frame or two, sometimes it takes 10 seconds or more! But it does eventually initialize every time.

you are a god!!

hi @oliran , according to the processing you described, the recording still cannot be recorded, and there will be the following warning:

AVAudioSession_iOS.mm:2223  Server returned an error from destroySession:. Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service with pid 39 named com.apple.audio.AudioSession was invalidated from this process." UserInfo={NSDebugDescription=The connection to service with pid 39 named com.apple.audio.AudioSession was invalidated from this process.}

But after playing an audio video, it can be recorded normally. What is the reason for this?

I know a bit about AVAudioSession, but I’m not very familiar with it. Can you explain it in detail?
Thank you.

Reviving this thread: This seems to be an issue specific to immersive spaces, and we’ve reported it to Apple with a non-Unity repro project. In addition to needing to delay enabling the microphone on startup, you may find that you also need to disable it when your immersive space loses focus (and then reenable it after a delay on regaining focus). There’s some sample code in a more recent related thread here.

The mic start problem definitely persists with visionos xr plugin 1.3.1 on VisionOS 2.0.1, where immersive mode is now “Metal” mode. Using Unity 2022.3.47.

Has there been any update from Apple on this? Would updating the visionos xr plugin to 1.3.9 help here?

We were already delaying microphone start for upwards of 10+seconds from app launch due to splash screen and other account login type things that happen before allowing user interaction. We’ll try some of the other suggestions such as coroutine monitoring for sample data.

I have the same question.