AVFragmentedAssetMinder在iPhone真机失效但模拟器正常问题求助
问题描述
我们通过WebSecureSocket(wss://)接收碎片化视频数据,将数据写入temp.mp4的同时播放已写入文件的分片内容。因此我们使用AVFragmentedAsset和AVFragmentedAssetMinder实现该逻辑,该功能在模拟器上运行符合预期,但在真机上不会更新资源时长,也不会触发.AVAssetDurationDidChange通知。暂未排查出问题原因,已经花费2天时间定位仍无进展,希望获得大家的帮助。
实现代码
WssPlayerSource类实现
public class WssPlayerSource: WebSocketDelegate { static let ASSET_MINDER = AVFragmentedAssetMinder() private let socketClient: WebSocketStreamingClient private var tempMovieFile:FileHandle? = nil private var startedPlay = false private var fragmentedAsset: AVFragmentedAsset? = nil let player = AVPlayer() init(withUrl url: URL) { socketClient = WebSocketStreamingClient(wssUrl: url) socketClient.delegate = self do { self.tempMovieFile = try getTemporaryMovieFileWriter() }catch { print("打开文件出错") } NotificationCenter.default.addObserver(self, selector: #selector(onVideoUpdate), name: .AVAssetDurationDidChange, object: nil) socketClient.connect() } // Socket代理方法 public func didReceive(event: WebSocketEvent, client: WebSocket) { switch event { case .binary(let data): self.tempMovieFile?.write(data) if !startedPlay { startedPlay = true DispatchQueue.global().async { [weak self] in self?.didReceivedInitialData() } } break; default: break; } } func didReceivedInitialData() { fragmentedAsset = AVFragmentedAsset(url: getTemporaryMovieFile()!) fragmentedAsset?.loadValuesAsynchronously(forKeys: ["duration", "containsFragments", "canContainFragments"], completionHandler: { WssPlayerSource.ASSET_MINDER.mindingInterval = 1 WssPlayerSource.ASSET_MINDER.addFragmentedAsset(self.fragmentedAsset!) self.player.replaceCurrentItem(with: AVPlayerItem(asset: self.fragmentedAsset!)) self.player.play() }) } @objc func onVideoUpdate() { print("视频时长已更新..") // 真机上不会触发该方法,但模拟器上运行正常 } func stop() { socketClient.forceDisconnect() NotificationCenter.default.removeObserver(self) if let asset = self.fragmentedAsset { WssPlayerSource.ASSET_MINDER.addFragmentedAsset(asset) } } }
ViewController实现
class ViewController: UIViewController { @IBOutlet var playerView:PlayerView! private static let SOCKET_URL = "wss://..." private var playerSource:WssPlayerSource? = nil private var playerLayer:AVPlayerLayer? = nil override func viewDidLoad() { super.viewDidLoad() self.playerSource = WssPlayerSource(withUrl: URL(string: ViewController.SOCKET_URL)!) self.playerLayer = AVPlayerLayer(player: self.playerSource!.player) self.playerLayer?.videoGravity = .resize self.playerView.layer.addSublayer(self.playerLayer!) } }
内容的提问来源于stack exchange,提问作者Suryavel TR
相关产品推荐
相关产品推荐

