You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

排查Swift中AVAudioRecorder的NSOSStatusErrorDomain错误(Code=1718449215)

错误原因与解决方案

错误码1718449215对应kAudioSessionErr_CategoryNotPermitted,核心问题是音频会话配置时机不对+权限请求与初始化顺序颠倒,以下是具体修复步骤:

关键问题分析

  • 初始化时先调用setUpRecorder(),但此时权限可能还处于undetermined状态,recordPermission()直接返回false,导致初始化失败。
  • 音频会话激活时未处理可能的冲突(比如其他应用占用音频),也未设置必要的category选项。
  • 文件名后缀与编码格式不匹配:用kAudioFormatMPEG4AAC编码应该对应.m4a后缀,而非.mp3。

修复步骤

  1. 调整权限请求与初始化顺序:先请求权限,在权限授予后再初始化录制器。
  2. 完善音频会话配置:设置category时添加必要选项,激活会话时处理可能的错误。
  3. 添加重新初始化逻辑:权限授予后重新调用setUpRecorder()。
  4. 修正文件后缀:将.mp3改为.m4a。

修改后的完整代码

class Recorder : NSObject, AVAudioRecorderDelegate {
    let recordingName: String
    var audioRecorder: AVAudioRecorder?
    var isRecording = false
    
    init(recordingName: String) {
        self.recordingName = recordingName
        super.init()
        requestRecordPermission()
    }
    
    func filePath() -> URL {
        // 修正后缀为m4a,匹配AAC编码
        let fileName = self.recordingName + ".m4a"
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let documentsDirectory = paths[0]
        return documentsDirectory.appendingPathComponent(fileName)
    }
    
    func requestRecordPermission() {
        AVAudioApplication.requestRecordPermission { [weak self] permission in
            guard let self = self else { return }
            if permission {
                print("已获取录音权限")
                // 权限授予后才初始化录制器
                self.audioRecorder = self.setUpRecorder()
            } else {
                print("应用无录音权限")
            }
        }
    }
    
    func recordPermission() -> Bool {
        let permissionStatus = AVAudioApplication.shared.recordPermission
        switch permissionStatus {
        case .granted:
            return true
        case .denied:
            return false
        case .undetermined:
            print("录音权限未确定")
            return false
        @unknown default:
            print("录音权限状态需更新")
            return false
        }
    }
    
    func setUpRecorder() -> AVAudioRecorder? {
        guard recordPermission() else { return nil }
        
        let session = AVAudioSession.sharedInstance()
        do {
            // 添加options,适配不同场景,比如允许蓝牙输入
            try session.setCategory(.record, mode: .default, options: .allowBluetooth)
            // 激活会话时处理可能的冲突,比如其他应用占用音频
            try session.setActive(true, options: .notifyOthersOnDeactivation)
            
            let settings = [
                AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
                AVSampleRateKey: 44100,
                AVNumberOfChannelsKey: 2,
                AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
            ]
            
            let audioRecorder = try AVAudioRecorder(url: filePath(), settings: settings)
            audioRecorder.delegate = self
            audioRecorder.isMeteringEnabled = true
            audioRecorder.prepareToRecord()
            return audioRecorder
        } catch let error {
            print("录制器初始化失败: \(error.localizedDescription)")
            return nil
        }
    }
    
    func toggleRecording() {
        guard let recorder = self.audioRecorder else {
            print("录制器未初始化,请检查权限")
            return
        }
        
        if isRecording {
            recorder.stop()
            isRecording = false
        } else {
            // 开始录制前再次确认会话状态
            let session = AVAudioSession.sharedInstance()
            do {
                try session.setActive(true)
            } catch {
                print("激活音频会话失败: \(error)")
                return
            }
            
            if recorder.record() {
                isRecording = true
            } else {
                print("开始录制失败")
            }
        }
    }
    
    // 实现代理方法,处理录制完成或错误
    func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
        if flag {
            print("录制完成,文件路径: \(recorder.url)")
        } else {
            print("录制失败")
        }
        isRecording = false
    }
    
    func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) {
        if let error = error {
            print("录制编码错误: \(error)")
        }
    }
}

代码点评

  • 权限处理优化:将权限请求放在初始化第一步,确保权限授予后才初始化录制器,避免因权限未确定导致的初始化失败。
  • 音频会话健壮性提升:添加category选项和会话激活的错误处理,适配更多场景(如蓝牙麦克风),同时处理与其他音频应用的冲突。
  • 格式一致性修正:文件名后缀与编码格式匹配,避免后续播放时的兼容性问题。
  • 错误反馈增强:在toggleRecording()中添加录制器未初始化的提示,以及开始录制前的会话状态检查,便于调试。
  • 代理方法补充:实现AVAudioRecorderDelegate的核心方法,能及时获取录制完成或错误的状态,方便业务逻辑处理。

内容的提问来源于stack exchange,提问作者Anton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:31:14