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

使用AVAudioPlayer播放Firebase音频报OSStatus Error 2003334207求助

解决AVAudioPlayer播放Firebase远程音频报错2003334207的问题

你遇到的OSStatus 2003334207错误,本质是AVAudioPlayer不支持直接加载远程HTTPS URL——它只能处理本地文件路径的URL(以file://开头),哪怕Chrome能直接播放这个远程音频,AVAudioPlayer也无法直接解析远程地址。

下面给两种可行的解决方案:

方案一:先下载音频到本地,再用AVAudioPlayer播放

通过URLSession将远程音频下载到App沙盒的临时目录,拿到本地URL后再初始化AVAudioPlayer播放:

func startPlaying(url: URL) {
    let downloadTask = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
        guard let self = self, let audioData = data, error == nil else {
            Helper.shared.printDebug("音频下载失败:\(error?.localizedDescription ?? "未知错误")")
            return
        }
        
        // 将音频数据写入沙盒临时文件
        let tempDirectory = FileManager.default.temporaryDirectory
        let localAudioURL = tempDirectory.appendingPathComponent(url.lastPathComponent)
        
        do {
            try audioData.write(to: localAudioURL)
            // 切回主线程初始化播放器并播放
            DispatchQueue.main.async {
                do {
                    self.audioPlayer = try AVAudioPlayer(contentsOf: localAudioURL)
                    self.audioPlayer.prepareToPlay()
                    self.audioPlayer.play()
                } catch {
                    Helper.shared.printDebug("本地音频播放失败:\(error.localizedDescription)")
                }
            }
        } catch {
            Helper.shared.printDebug("本地文件写入失败:\(error.localizedDescription)")
        }
    }
    downloadTask.resume()
}

方案二:改用AVPlayer直接播放远程URL

AVPlayer是Apple官方用于处理远程流媒体/音频的播放器,支持直接加载HTTPS URL,更适配这种场景:

首先在ViewModel中声明AVPlayer相关对象:

import AVKit

class YourViewModel: ObservableObject {
    var audioPlayer: AVPlayer?
    var playerStatusObserver: NSKeyValueObservation?
    // 其他属性...
}

然后修改startPlaying函数:

func startPlaying(url: URL) {
    let playerItem = AVPlayerItem(url: url)
    audioPlayer = AVPlayer(playerItem: playerItem)
    
    // 监听播放状态,处理加载/失败逻辑
    playerStatusObserver = playerItem.observe(\.status, options: [.new]) { [weak self] item, _ in
        guard let self = self else { return }
        switch item.status {
        case .readyToPlay:
            self.audioPlayer?.play()
        case .failed:
            Helper.shared.printDebug("播放失败:\(item.error?.localizedDescription ?? "未知错误")")
        case .unknown:
            Helper.shared.printDebug("音频加载中...")
        @unknown default:
            break
        }
    }
}

同时调整按钮的播放/暂停逻辑(通过AVPlayer的rate属性判断播放状态):

Button {  
    if vm.audioPlayer?.rate ?? 0 > 0 {
        vm.audioPlayer?.pause()
    } else {
        if vm.audioPlayer == nil {
            vm.startPlaying(url: audioURL ?? URL(fileURLWithPath: ""))
        } else {
            vm.audioPlayer?.play()
        }
    }
} label: {
    Image(systemName: (vm.audioPlayer?.rate ?? 0 > 0) ? "pause.fill" : "play.fill")
        .foregroundColor(.black)
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 10)
                .foregroundColor(.gray)
                .frame(width: 100)
        )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:30:57