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

使用AVAudioPlayer播放音频:真机报错及改格式后无声问题求助

问题分析与修复方案

错误原因拆解

  1. 格式不匹配:代码里加载的是.m4a文件,但fileTypeHint指定为caf,真机对音频格式校验更严格,直接导致文件打开失败(错误码1685348671对应音频格式不支持/文件无法识别)。后续改后缀为caf后,代码里的文件名后缀没同步修改,实际加载的文件不存在,自然没有声音。
  2. 音频会话管理不当:每次播放都激活会话,但播放完成后未停用,多次调用会导致会话冲突,占用系统音频资源。
  3. 播放器实例生命周期问题:如果player是类的弱引用或局部变量,会被ARC提前释放,导致播放中断或无声音。

具体修复步骤

1. 统一音频文件格式与参数

确保文件名后缀和fileTypeHint完全一致,以caf格式为例:

func playByUrl(url: String) {
    // 统一文件后缀为caf
    let audioFilename = getDocumentsDirectory().appendingPathComponent("\(url).caf")
    do {
        // 配置音频会话,添加混音选项避免和其他音频冲突
        try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.mixWithOthers])
        try AVAudioSession.sharedInstance().setActive(true)
        
        // fileTypeHint与文件格式保持一致
        player = try AVAudioPlayer(contentsOf: audioFilename, fileTypeHint: AVFileType.caf.rawValue)
        guard let player = player else { return }
        
        // 设置代理监听播放完成,及时释放资源
        player.delegate = self
        player.prepareToPlay()
        player.play()
    } catch let error {
        print("播放失败:\(error.localizedDescription)")
        // 激活失败时强制停用会话,避免资源占用
        try? AVAudioSession.sharedInstance().setActive(false)
    }
}

2. 固定播放器实例生命周期

在类中声明强引用的player属性,防止被提前释放:

class YourAudioManager: NSObject, AVAudioPlayerDelegate {
    var player: AVAudioPlayer? // 强引用存储播放器实例
    
    // ... 其他业务代码
}

3. 播放完成后释放资源

实现AVAudioPlayerDelegate回调,完成后清理会话和播放器:

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    // 停用音频会话并通知其他应用
    try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
    // 重置播放器,释放资源
    self.player = nil
}

4. 录制阶段同步格式

如果是自行录制音频,录制时也要指定caf格式的参数,确保文件可用:

let recordSettings: [String: Any] = [
    AVFormatIDKey: kAudioFormatLinearPCM,
    AVSampleRateKey: 44100.0,
    AVNumberOfChannelsKey: 1,
    AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
// 录制文件后缀统一为caf
let recordUrl = getDocumentsDirectory().appendingPathComponent("\(url).caf")
let recorder = try AVAudioRecorder(url: recordUrl, settings: recordSettings)

额外注意事项

  • 真机测试时,确认设备未静音、音量已开启。
  • 每次播放前检查旧播放器状态,避免资源冲突:
if let existingPlayer = player, existingPlayer.isPlaying {
    existingPlayer.stop()
    existingPlayer.delegate = nil
}
player = nil

内容的提问来源于stack exchange,提问作者Миша Гарлинский

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 10:51:20