解决从FileManager下载的歌曲无法通过AVPlayer播放的问题
AVPlayer无法播放Documents目录本地音频的排查方案
以下是针对你遇到的问题的具体排查方向和解决办法:
1. 验证文件完整性
下载后移动文件的过程可能出现写入不完整的情况,导致文件损坏无法播放。在moveItem后添加文件大小校验:
try FileManager.default.moveItem(at: location, to: destinationUrl) // 校验源文件与目标文件大小一致 guard let sourceSize = try? FileManager.default.attributesOfItem(atPath: location.path)[.size] as? Int64, let destSize = try? FileManager.default.attributesOfItem(atPath: destinationUrl.path)[.size] as? Int64, sourceSize == destSize else { print("文件移动不完整,可能已损坏") return } print("File moved to documents folder") completion(destinationUrl)
2. 监听AVPlayerItem加载状态
直接初始化AVPlayer可能无法及时获取资源状态,通过监听status可以明确失败原因:
audioDownloader.downloadTrack(url: urlString) { url in DispatchQueue.main.async { let asset = AVURLAsset(url: url) let playerItem = AVPlayerItem(asset: asset) playerItem.addObserver(self, forKeyPath: "status", options: .new, context: nil) self.player = AVPlayer(playerItem: playerItem) } } // 在当前类中添加监听回调 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard keyPath == "status", let item = object as? AVPlayerItem else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) return } switch item.status { case .readyToPlay: self.player?.play() self.player?.volume = 1.0 case .failed: print("播放失败原因:\(item.error?.localizedDescription ?? "未知错误")") case .unknown: print("资源正在加载") @unknown default: break } } // 记得在deinit中移除监听 deinit { self.player?.currentItem?.removeObserver(self, forKeyPath: "status") }
3. 修复文件权限
iOS 13+中,临时目录文件移动到Documents后可能存在权限问题,手动设置文件权限:
try FileManager.default.moveItem(at: location, to: destinationUrl) // 设置文件可读可写权限 try FileManager.default.setAttributes([.posixPermissions: 0o644], ofItemAtPath: destinationUrl.path)
4. 确保Player的生命周期
确认player是类级别属性而非闭包内的局部变量,否则会被立即释放导致播放终止:
class YourClass: UIViewController { var player: AVPlayer? // 必须声明在类作用域内 // ... }
5. 配置音频会话
iOS需要正确激活音频会话才能播放声音,尤其是静音或后台场景:
// 在播放前添加 do { try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default) try AVAudioSession.sharedInstance().setActive(true) } catch { print("音频会话配置失败:\(error)") }
内容的提问来源于stack exchange,提问作者kesape
相关产品推荐
相关产品推荐

