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

iOS真机修改音频采样率setPreferredSampleRate无效解决方法

问题核心原因
  • setPreferredSampleRate 从API设计层面就不是强制修改采样率的接口,它仅用于向系统声明期望的采样率参数,系统会结合当前音频路由的硬件能力、系统资源占用情况,自动选择最接近请求值的可用采样率。模拟器运行时复用Mac端音频栈,硬件限制宽松,才会出现任意采样率都能设置成功的假象,真机返回固定48kHz的行为才符合API设计预期。
  • 从iPhone 6S开始,所有在售iPhone机型的内置音频硬件(内置麦克风、听筒、扬声器)原生固定工作采样率为48kHz,当音频路由为内置输入/输出设备时,系统不会为了匹配应用的偏好修改硬件工作参数,因此读取sampleRate属性永远返回48000。这是硬件层面的硬限制,不存在任何方案可以绕过这个限制直接把内置硬件的工作采样率改成其他值。
  • 当前代码的调用顺序不符合API要求:所有音频会话的偏好设置(包括采样率、IO缓冲时长、声道数等),都需要在会话处于未激活状态时设置,设置完成后重新调用setActive(true)激活会话,配置才会被系统真正读取评估。现有代码仅设置了分类、申请了录音权限,从未激活会话,设置的采样率偏好根本不会被系统处理。
对应解决方案

不需要强行修改内置硬件的工作采样率,根据实际业务场景选择对应方案即可:

  • 如果目标是生成指定采样率的录音文件(比如16kHz、44.1kHz):完全不需要修改AVAudioSession的采样率,直接在初始化AVAudioRecorder的配置字典中,给AVSampleRateKey赋值为需要的目标采样率即可。AVAudioRecorder会自动在录音链路中完成48kHz硬件原始流到目标采样率的重采样,最终输出的文件参数完全符合设置要求,硬件固定运行在48kHz不会对最终文件造成任何影响。
  • 如果目标是实时获取指定采样率的PCM流(用于实时语音处理、音视频直播、低延迟音频传输等场景),有两种成熟可行路径:
    • 保持会话默认的48kHz采样率做音频采集,拿到原始PCM数据后通过系统自带的AudioConverter或者成熟的开源重采样库(soxr、speexdsp等)自行转换为目标采样率,这也是绝大多数iOS音视频类应用采用的通用方案,重采样带来的性能损耗极低。
    • 接入支持目标采样率的外接音频设备(Lightning/Type-C接口外接麦克风、USB声卡等),当音频路由切换到外接设备时,只要硬件本身支持请求的采样率,设置偏好后激活会话即可拿到对应采样率的音频流,前述48kHz的固定采样率限制仅针对内置音频硬件。
代码调用顺序修正参考
class AudioSessionManager{
    private let audioSession = AVAudioSession.sharedInstance()

    func setAudioSession(targetSampleRate: Double) {
        do {
            // 修改配置前先把会话切到未激活状态
            try audioSession.setActive(false, options: .notifyOthersOnDeactivation)
            // 设置音频会话分类与选项
            try audioSession.setCategory(.playAndRecord, options: .defaultToSpeaker)
            // 设置采样率偏好
            try audioSession.setPreferredSampleRate(targetSampleRate)
            // 重新激活会话让配置生效
            try audioSession.setActive(true)
            // 激活会话后读取的采样率才是系统最终实际采用的硬件工作采样率
            print("实际生效采样率:\(audioSession.sampleRate)")
            
            // 录音权限建议在应用初始化阶段单独调用申请
            audioSession.requestRecordPermission{ accepted in
                accepted ? print("录音权限已获取") : print("未获取录音权限")
            }
        } catch {
            print("音频会话配置错误:\(error.localizedDescription)")
        }
    }

    func getCurrentSampleRate() -> Double {
        return audioSession.sampleRate
    }
}

注意:即便按照上述顺序修正调用逻辑,只要当前音频路由为内置麦克风/扬声器,最终拿到的实际采样率依然会是48000,这是硬件限制,并非代码逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 22:18:14