具有resourceLoader委托的AVPlayer获取数据但不播放视频

问题描述

这是我第一次在此网站上寻求帮助。我搜索了整个Internet,尝试了很多事情,甚至阅读了文档:),但找不到解决该问题的方法

我的任务是从需要证书的存储库中播放视频。如果我使用简单的AVPlayer设置而不设置AVAssetResourceLoaderDelegate:

controller.player = AVPlayer(url: urlFromUnprotectedplace)

播放器可以完美打开不受保护的存储中的网址并播放视频。但是在尝试从受保护的文件夹播放视频时,会出现错误“此服务器的证书无效” 。通过设置resourceLoader委托可以解决此问题:

let asset = AVURLAsset(url: customSchemeUrl)
asset.resourceLoader.setDelegate(myDelegate,queue: .main)
let item = AVPlayerItem(asset: asset)
controller.player = AVPlayer(playerItem: item)

和委托方法本身:

func resourceLoader(
        _ resourceLoader: AVAssetResourceLoader,shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest
    ) -> Bool {
        guard let url = url else {
            logger.log("nil url")
            return false
        }
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        request.setValue("bytes=0-",forHTTPHeaderField: "Range")
        
        let sessionTask = urlSession?.dataTask(with: request) { [weak self] data,response,error in
            if let error = error {
                self?.logger.log(error.localizedDescription)
                return
            }
            loadingRequest.contentinformationRequest?.contentType = AVFileType.mp4.rawValue
            loadingRequest.contentinformationRequest?.isByterangeAccessSupported = true
            loadingRequest.response = response
            if let data = data {
                loadingRequest.contentinformationRequest?.contentLength = Int64(data.count)
                loadingRequest.dataRequest?.respond(with: data)
            }
            loadingRequest.finishLoading()
        }
        sessionTask?.resume()
        return true
    }

数据和响应到来,错误为nil。数据大小正确。响应包含状态206。播放器的项目具有其状态的观察者,但没有人显示任何错误-播放器只是黑色,而下载轮却在旋转。

但是我走得更远。有这样一个项目:https://github.com/2ZGroupSolutionsArticles/Article_EZ002 我用他的代表代替了我的代表-行为相同。但它也可以将下载的数据保存到本地文件中。因此,如果在保存完成后尝试播放此文件-一切正常,就可以播放。

我的SwiftUI播放器:

final class MyVideoPlayer: UIViewControllerRepresentable {
    private let controller = AVPlayerViewController()
    private var playerItemObserver: MyPlayerItemStateObserver?
    private var resourceLoaderDelegate: EugeneResourceLoaderDelegate?
    
    private var playingStarted = false
    
    init(url: URL?) {
        guard let url = url else { return }
        resourceLoaderDelegate = EugeneResourceLoaderDelegate(withURL: url)
        resourceLoaderDelegate?.completion = downloadCompletion()
        controller.player = createPlayer()
    }
    
    func makeUIViewController(context: Context) -> AVPlayerViewController {
        controller
    }

    func updateUIViewController(_ uiViewController: AVPlayerViewController,context: Context) {}
    
    func play() -> some View {
        playingStarted = true
        controller.player?.play()
        return self
    }
}

extension MyVideoPlayer {
    private func createPlayer() -> AVPlayer? {
        guard
            let delegate = resourceLoaderDelegate,let streamingUrl = delegate.streamingAssetURL
        else {
            return nil
        }
        let asset = AVURLAsset(url: streamingUrl)
        asset.resourceLoader.setDelegate(delegate,queue: .main)
        playerItemObserver = MyPlayerItemStateObserver(asset: asset,logger: logger)
        if let item = playerItemObserver?.item {
            return AVPlayer(playerItem: item)
        }
        return nil
    }
    
    private func downloadCompletion() -> (URL?) -> Void {
        { [weak self] localFileURL in
            guard let self = self else { return }
            guard let localFileURL = localFileURL else {
                print("Failed to download media file.")
                return
            }
            print("Media file saved to: \(localFileURL)")
            let status = self.controller.player?.timeControlStatus
            if self.playingStarted && status?.rawValue == 1 {
                self.controller.player = AVPlayer(url: localFileURL)
                self.controller.player?.play()
            }
        }
    }
}

我认为我已经没有主意了。我将不胜感激。

已更新。在重新创建播放器的状态及其currentItem来播放本地文件之前,我将其打印出来,我得到了:

player?.reasonForWaitingToPlay - AVPlayerWaitingWhileEvaluatingBufferingRateReason
player?.currentItem?.isPlaybackBufferEmpty - true
player?.currentItem?.duration - value: 0

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)