使用AVAudioRecorder录制无声音问题排查求助
我正在尝试用Swift实现iOS平台的简单音频录制功能,使用AVAudioRecorder编写了如下AudioRecorder类:
import Foundation import AVFoundation class AudioRecorder: NSObject, AVAudioRecorderDelegate { var audioRecorder: AVAudioRecorder? var file: URL? = nil func setupAudioSession() { let session = AVAudioSession.sharedInstance() do { try session.setCategory(.playAndRecord, mode: .default) try session.setActive(true) try session.overrideOutputAudioPort(.speaker) debugPrint("Listo todo") } catch { print("Error setting up audio session: \(error.localizedDescription)") } } func startRecording() { file = getDocumentsDirectory().appendingPathComponent("recording.wav") let settings: [String: Any] = [ AVFormatIDKey: kAudioFormatLinearPCM, AVSampleRateKey: 44100.0, AVNumberOfChannelsKey: 2, AVLinearPCMBitDepthKey: 16, AVLinearPCMIsFloatKey: false, AVLinearPCMIsBigEndianKey: false ] do { audioRecorder = try AVAudioRecorder(url: file!, settings: settings) audioRecorder?.delegate = self audioRecorder?.prepareToRecord() audioRecorder?.record() } catch { print("Error starting recording: \(error.localizedDescription)") } } func stopRecording() { audioRecorder?.stop() } private func getDocumentsDirectory() -> URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) return paths[0] } // MARK: AVAudioRecorderDelegate func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) { if flag { print("Recording was successful.") } else { print("Recording failed.") } } }
视图中会调用setupAudioSession方法,点击按钮时调用startRecording(调用前已通过AVAudioSession.sharedInstance().requestRecordPermission获取麦克风权限)。
点击停止录制后,audioRecorderDidFinishRecording回调返回"Recording was successful."日志。使用AVAudioPlayer播放文件时,能正确读取文件属性:
"Playing ... Optional("file:///var/mobile/Containers/Data/Application/0760DB3E-440E-4898-83A6-0888EC2EA399/Documents/recording.wav")" "Duration: 4.180997732426304" "Format: <AVAudioFormat 0x281ce80f0: 2 ch, 44100 Hz, Int16, interleaved>" "Current Time: 0.0" "Volume: 1.0"
但播放时完全没有声音,且我已在Info.plist中配置了NSMicrophoneUsageDescription。我在模拟器和真机上都做了测试,均无声音,将WAV文件下载到音频编辑器中查看发现文件为空。这是一个很基础的示例,搜索到的案例也都类似,请问我哪里遗漏了?
问题排查与解决方法
1. 修复AVAudioRecorder的强引用问题
你的audioRecorder是类的可选属性,如果AudioRecorder实例在录制过程中被提前释放,AVAudioRecorder也会被销毁,导致录制中断、文件无法写入。确保AudioRecorder实例在录制全程被强引用持有,比如在视图控制器中声明为var audioRecorder: AudioRecorder!,直到录制完成再释放。
2. 补充WAV格式的关键配置
使用kAudioFormatLinearPCM格式时,需要明确指定文件类型标识,否则可能导致文件写入不完整。在录制设置中添加AVAudioFileTypeKey:
let settings: [String: Any] = [ AVFormatIDKey: kAudioFormatLinearPCM, AVSampleRateKey: 44100.0, AVNumberOfChannelsKey: 2, AVLinearPCMBitDepthKey: 16, AVLinearPCMIsFloatKey: false, AVLinearPCMIsBigEndianKey: false, AVAudioFileTypeKey: AVFileType.wav.rawValue // 新增该行 ]
3. 确保文件写入完成
调用stopRecording后,AVAudioRecorder需要时间完成文件写入,建议在audioRecorderDidFinishRecording回调中再执行文件操作或播放。也可以在停止录制时显式触发写入:
func stopRecording() { audioRecorder?.stop() audioRecorder?.finishRecording() // 确保文件写入完成 }
4. 处理旧文件覆盖问题
每次调用startRecording都会生成相同路径的文件,若旧文件未被正确覆盖可能导致异常。录制前可删除旧文件:
func startRecording() { file = getDocumentsDirectory().appendingPathComponent("recording.wav") // 删除已存在的旧文件 if FileManager.default.fileExists(atPath: file!.path) { try? FileManager.default.removeItem(at: file!) } // 后续录制逻辑... }
5. 优化音频会话配置
将overrideOutputAudioPort替换为会话配置的options参数,更符合官方推荐的用法:
do { try session.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker]) try session.setActive(true) } catch { print("Audio session setup failed: \(error)") }
6. 确认麦克风权限状态
即使请求了权限,也建议在回调中确认权限是否真正被授予:
AVAudioSession.sharedInstance().requestRecordPermission { granted in DispatchQueue.main.async { if granted { // 执行录制操作 } else { print("麦克风权限未授权") } } }
内容的提问来源于stack exchange,提问作者Ricardo Markiewicz

