user1752054
user1752054

Reputation: 382

iOS 14 AVCaptureSession capturing stereo audio with video recording

I was wondering is there's a way to capture stereo audio using an AVCaptureSession. iOS 14 adds support for stereo audio for AVAudioRecorder, but so far I have been unsuccessful is capturing stereo audio through an AVCaptureSession.

AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
[audioSession setActive:YES error:NULL];
     
NSArray *portDescriptions = audioSession.availableInputs;
AVAudioSessionPortDescription *builtInMicPort = nil;

for (AVAudioSessionPortDescription *port in portDescriptions) {
    if ([port.portType isEqualToString:AVAudioSessionPortBuiltInMic]) {
        builtInMicPort = port;
        break;
    }
} // end input iteration
     
[audioSession setPreferredInput:builtInMicPort error:nil];
     
NSArray *supportedPolarPatterns = audioSession.preferredInput.dataSources.firstObject.supportedPolarPatterns;
         
[audioSession.preferredInput.dataSources.firstObject setPreferredPolarPattern:AVAudioSessionPolarPatternStereo error:nil];


[audioSession.preferredInput setPreferredDataSource:audioSession.preferredInput.dataSources.firstObject error:nil];
[audioSession setPreferredInputOrientation:AVAudioStereoOrientationPortrait error:nil];

device = [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionBack];
deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];

if([videoSession canAddInput:deviceInput]){
    [videoSession addInput:deviceInput];
}

AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
AVCaptureDeviceInput *audioDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error];
        
if([videoSession canAddInput:audioDeviceInput]){
    [videoSession addInput:audioDeviceInput];
}

Upvotes: 0

Views: 1162

Answers (3)

Michael N
Michael N

Reputation: 563

Here is the Swift 5 version. The device must support stereo. The older iPhones only support Omnidirectional or Cardioid, so it won't work.

// STEREO AUDIO RECORDING

do {
    
    let audioSession : AVAudioSession = AVAudioSession.sharedInstance()
    try audioSession.setCategory(.playAndRecord, options: .defaultToSpeaker)
    try audioSession.setActive(true)
    
    // select the built-in Back mic if available
    
    let portDescriptions : [AVAudioSessionPortDescription] = audioSession.availableInputs ?? []
    var builtInMicPort : AVAudioSessionPortDescription?
    
    for port in portDescriptions {
        
        if port.portType == AVAudioSession.Port.builtInMic {
            
            print("builtInMic")
            
            builtInMicPort = port
            
        }
        
    }
    
    try audioSession.setPreferredInput(builtInMicPort)
    
    var frontDataSource : AVAudioSessionDataSourceDescription?

    print("builtInMicPort: \(builtInMicPort)")
    
    for source in builtInMicPort?.dataSources ?? [] {
        
        print("source: \(source)")
        
        if source.orientation == AVAudioSession.Orientation.front {
            
            print("front")
            
            frontDataSource = source

        }
        
    }
    
    var supportedPolarPatterns = frontDataSource?.supportedPolarPatterns
    
    print("SUPPORTED POLAR PATTERNS: \(String(describing: supportedPolarPatterns))")
    
    var isStereoSupported : Bool = supportedPolarPatterns?.contains(AVAudioSession.PolarPattern.stereo) ?? false
    
    print("isStereoSupported: \(isStereoSupported)")
    
    if (isStereoSupported == true) {
        
        if #available(iOS 14.0, *) {

            try frontDataSource?.setPreferredPolarPattern(AVAudioSession.PolarPattern.stereo)

            try audioSession.preferredInput?.setPreferredDataSource(frontDataSource)
            
            if #available(iOS 14.0, *) {

                try audioSession.setPreferredInputOrientation(AVAudioSession.StereoOrientation.portrait)

            }
            
            // video
            
            self.captureSession?.usesApplicationAudioSession = true
            self.captureSession?.automaticallyConfiguresApplicationAudioSession = false
            
        } else {

            // default to capture device audio
                                    
            let audioInput = AVCaptureDevice.default(for: .audio)
            
            if captureSession.canAddInput(try AVCaptureDeviceInput(device: audioInput!)) {
                
                try captureSession.addInput(AVCaptureDeviceInput(device: audioInput!))
                
            }

        }

    } else {
        
        // default to capture device audio
                                
        let audioInput = AVCaptureDevice.default(for: .audio)
        
        if captureSession.canAddInput(try AVCaptureDeviceInput(device: audioInput!)) {
            
            try captureSession.addInput(AVCaptureDeviceInput(device: audioInput!))
            
        }

    }
                    
} catch {
    
    // default to capture device audio
    
    print("No audio")
    
    let audioInput = AVCaptureDevice.default(for: .audio)
    
    if captureSession.canAddInput(try AVCaptureDeviceInput(device: audioInput!)) {
        
        try captureSession.addInput(AVCaptureDeviceInput(device: audioInput!))
        
    }

}

Upvotes: 1

user1752054
user1752054

Reputation: 382

Here's the working code:

//STEREO AUDIO RECORDING

 AVAudioSession *audioSession = [AVAudioSession sharedInstance];
 [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
 [audioSession setActive:YES error:NULL];
 
 // select the built-in Back mic if available
 NSArray *portDescriptions = audioSession.availableInputs;
 AVAudioSessionPortDescription *builtInMicPort = nil;

 for (AVAudioSessionPortDescription *port in portDescriptions) {
     if ([port.portType isEqualToString:AVAudioSessionPortBuiltInMic]) {
         builtInMicPort = port;
         break;
     }
 } // end input iteration
 
 [audioSession setPreferredInput:builtInMicPort error:nil];

AVAudioSessionDataSourceDescription* frontDataSource = nil;
    for (AVAudioSessionDataSourceDescription* source in builtInMicPort.dataSources)
    {
        if ([source.orientation isEqual:AVAudioSessionOrientationFront])
        {
            frontDataSource = source;
            break;
        }
    } // end data source iteration

 
 NSArray *supportedPolarPatterns = frontDataSource.supportedPolarPatterns;
 
 NSLog(@"SUPPORTED POLAR PATTERNS : %@", supportedPolarPatterns);
 
 BOOL isStereoSupported = [supportedPolarPatterns containsObject:@"Stereo"];
 
 if(isStereoSupported == YES){
     if(@available(iOS 14.0, *)) {
         [frontDataSource setPreferredPolarPattern:AVAudioSessionPolarPatternStereo error:nil];
     } else {
         // Fallback on earlier versions
     }
 }
 
 [audioSession.preferredInput setPreferredDataSource:frontDataSource error:nil];

if(@available(iOS 14.0, *)) {
    [audioSession setPreferredInputOrientation:AVAudioStereoOrientationPortrait error:nil];
}

videoSession = [[AVCaptureSession alloc] init];

//STEREO AUDIO RECORDING
videoSession.usesApplicationAudioSession = YES;
videoSession.automaticallyConfiguresApplicationAudioSession = NO;

Upvotes: 1

William
William

Reputation: 26

Try this:

videoSession.usesApplicationAudioSession = true
videoSession.automaticallyConfiguresApplicationAudioSession = false

I was able to get stereo working in iOS 14 with this added.

Upvotes: 1

Related Questions