首页 > 解决方案 > AVFragmentedAssetMinder 不能在 iPhone 设备上运行,但可以在模拟器上运行

问题描述

我们有来自 WebSecureSocket (wss://) 的片段电影数据。我们将其写入temp.mp4并同时播放写入文件的片段。因此,我们为此使用了 AVFragmentedAssetAVFragmentedAssetMinder。它在模拟器中按预期工作。但在设备中,不会更新资产的持续时间,也不会发布.AVAssetDurationDidChange通知。不知道可能是什么问题。已经花了 2 天时间弄清楚这一点,但没有运气。有人可以帮我解决这个问题吗,

执行..

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("Error opening file")
        }
        
        NotificationCenter.default.addObserver(self, selector: #selector(onVideoUpdate), name: .AVAssetDurationDidChange, object: nil)
        socketClient.connect()
    }
    
    // Socket delegate
    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("Video duration updated..")
        // This is not called in device.. but in simulator it works as expected
    }
    
    func stop() {
        socketClient.forceDisconnect()
        NotificationCenter.default.removeObserver(self)
        if let asset = self.fragmentedAsset {
            WssPlayerSource.ASSET_MINDER.addFragmentedAsset(asset)
        }
    }
}

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!)
    }
}

标签: iosavfoundationavplayer

解决方案


推荐阅读