Swift y grabación de audio

Estoy desarrollando una aplicación de iOS en forma rápida y el cliente devolvió un problema con la grabación de audio. Básicamente no registra nada. Probó en un iPhone 5/5 con ios 9.x. Se verificaron los permissions y si tiene suficiente espacio en el teléfono, estos no fueron el problema.

Personalmente, se probó con un dispositivo iPhone 6s con ios 10.xy iphone 5 en el simulador y el logging funciona. Cualquiera se encontró con esto antes o tal vez hice algo mal que me elude.

Se agregaron comentarios a las diferentes funciones que dice lo que hace la aplicación.

protocol RecordAndPlayManagerDelegate : class{ func recorderDidStopRecording() } class RecordAndPlayManager: NSObject, AVAudioRecorderDelegate { var soundRecorder: AVAudioRecorder! let recordSettings = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 12000, AVNumberOfChannelsKey: 1, AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue ] class func directoryURL() -> URL? { let fileManager = FileManager.default let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask) let documentDirectory = urls[0] as URL let soundURL = documentDirectory.appendingPathComponent("recording.m4a") return soundURL } //calling this from outside to get the audio class func getLocalOrRemoteRecording(_ recordingID : String!) -> URL?{ let fileManager = FileManager.default let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask) let documentDirectory = urls[0] as URL let soundURL = documentDirectory.appendingPathComponent(recordingID) if (fileManager.fileExists(atPath: soundURL.path)){ return soundURL } let path = kBaseServerURLNOPORT + "data/" + recordingID let url = URL(string: path) return url } //called from outside, recordingID -> name of the file class func storeRecording(_ recordingID : String!) -> URL? { let fileManager = FileManager.default let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask) let documentDirectory = urls[0] as URL let soundURL = documentDirectory.appendingPathComponent("recording.m4a") let data = try? Data(contentsOf: soundURL) //data here has only 28bytes and from this I know it didn't record. In my tests, I always get at least 20000 bytes. let newSoundURL = documentDirectory.appendingPathComponent(recordingID) try? data?.write(to: newSoundURL, options: [.atomic]) do { try FileManager.default.removeItem(at: soundURL) } catch _ { print("failed to delete file") return newSoundURL } return newSoundURL } //called on viewDidLoad in another screen func setupRecorder() { let url = DRMessageRecordAndPlayManager.directoryURL()! do { try self.soundRecorder = AVAudioRecorder(url: url, settings: self.recordSettings) } catch _ { return } soundRecorder.delegate = self soundRecorder.prepareToRecord() } //calling this from outside to start recording func startRecording() { if !self.soundRecorder.isRecording { let audioSession = AVAudioSession.shanetworkingInstance() do { try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord) try audioSession.setActive(true) soundRecorder.record(forDuration: 15) } catch { } } } //called from outside when I hit stop func stopRecording() { self.soundRecorder.stop() let audioSession = AVAudioSession.shanetworkingInstance() do { try audioSession.setActive(false) } catch { } } func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) { self.delegate?.recorderDidStopRecording() } } 

Mi conjetura es que la catch en startRecording() está funcionando como se esperaba y previene un locking, pero no estás conectándolo.

Recomiendo cambiar las dos sentencias de captura imprimir el object de error suministrado de esta manera:

 catch { // or use an alert controller to display the error print("caught error: \(error)") } 

Aquí hay un código para la grabación de audio en el objective c.

  NSMutableDictionary *recordSetting; NSString *recorderFilePath; AVAudioRecorder *recorder; - (void) startRecording{ AVAudioSession *audioSession = [AVAudioSession shanetworkingInstance]; NSError *err = nil; [audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err]; if (err) { NSLog(@"audioSession: %@ %ld %@", [err domain], (long)[err code], [[err userInfo] description]); return; } [audioSession setActive:YES error:&err]; err = nil; if (err) { NSLog(@"audioSession: %@ %ld %@", [err domain], (long)[err code], [[err userInfo] description]); return; } recordSetting = [[NSMutableDictionary alloc] init]; [recordSetting setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey]; [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey]; [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey]; [recordSetting setValue :[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey]; [recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey]; [recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey]; // Create a new dated file NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0]; NSString *caldate = [now description]; recorderFilePath = [NSString stringWithFormat:@"%@/%@.caf", DOCUMENTS_FOLDER, caldate]; NSURL *url = [NSURL fileURLWithPath:recorderFilePath]; err = nil; recorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSetting error:&err]; if (!recorder) { NSLog(@"recorder: %@ %ld %@", [err domain], (long)[err code], [[err userInfo] description]); return; } //prepare to record [recorder setDelegate:self]; [recorder prepareToRecord]; recorder.meteringEnabled = YES; BOOL audioHWAvailable = audioSession.inputAvailable; if (!audioHWAvailable) { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"title_warning", nil) message:NSLocalizedString(@"recorder_warning_message", nil) prefernetworkingStyle:UIAlertControllerStyleAlert]; UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"ok_action", nil) style:UIAlertActionStyleDefault handler:nil]; [alertController addAction:ok]; [self presentViewController:alertController animated:YES completion:nil]; return; } else { [recorder record]; } }