swift-无法播放使用AVAssetResourceLoaderDelegate加载的视频

问题描述 投票:0回答:1

我正在尝试使用AVPlayer播放视频,该视频已加载到AVAssetResourceLoaderDelegate内,但我始终会出现空白屏幕,并且该视频无法播放。

这是代码:

let asset = AVURLAsset(url: URL(string: "fakescheme://video.mp4")!)
asset.resourceLoader.setDelegate(ResourceLoaderDelegate(), queue: DispatchQueue.main)
let item = AVPlayerItem(asset: asset)
let player = AVPlayer(playerItem: item)

let playerLayer = AVPlayerLayer(player: self.player)
playerLayer!.frame = self.view.bounds;
self.view.layer.addSublayer(self.playerLayer!)
player!.play()

...

class ResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate, URLSessionDelegate, URLSessionDataDelegate, URLSessionTaskDelegate {
    public func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource resourceLoadingRequest: AVAssetResourceLoadingRequest) -> Bool {

        var newRequest = URLRequest(url: URL(string: "https://example.com/video.mp4")!)
        newRequest.allHTTPHeaderFields = resourceLoadingRequest.request.allHTTPHeaderFields

        let sessionTask = URLSession.shared.dataTask(with: newRequest) { data, response, error in
            resourceLoadingRequest.contentInformationRequest?.contentType = "video/mp4"
            resourceLoadingRequest.contentInformationRequest?.isByteRangeAccessSupported = true
            resourceLoadingRequest.contentInformationRequest?.contentLength = Int64(data.count)

            resourceLoadingRequest.response = response

            resourceLoadingRequest.dataRequest?.respond(with: data)
            resourceLoadingRequest.finishLoading()
        }

        sessionTask.resume()
        return true
    }
}

这是基本概念:

[fakescheme://导致调用resourceLoader()委托,在其中创建了一个新的HTTP请求,以下载实际的视频。

然后它调用resourceLoadingRequest.dataRequest?.respond(with:data),这应该导致AVPlayer播放下载的视频。数据变量已正确填充,但我总是黑屏。

视频文件也很好,如果我直接将其输入AVURLAsset(),则可以播放。

我尝试了上百万种事物和组合,但是无法使用委托使其发挥作用。任何帮助将不胜感激!

编辑:我将添加更多信息。

我曾尝试使用AES加密视频来执行此操作,该视频使用3个文件-.m3u8,加密密钥和.ts视频。我设法使它使用委托下载.m3u8和密钥,但是当我尝试对视频文件进行操作时,再次出现黑屏。

这使我认为它可能需要分批进行下载,但是我不确定如何正确进行下载。我也找不到关于它的任何文档,例如-您是否应该将HTTP标头设置为好像来自Web服务器,还是应该设置contentInformationRequest等,则该委托被调用了2次:

// first time: 
resourceLoadingRequest.dataRequest!.requestedLength == 2,
resourceLoadingRequest.dataRequest!.requestsAllDataToEndOfResource == false

// second time: 
resourceLoadingRequest.dataRequest!.requestedLength == MAX_INT,
resourceLoadingRequest.dataRequest!.requestsAllDataToEndOfResource == true

我不确定要怎么做-我两次都给了整个视频,但没有成功。

我看到其他人一直在同一个方面挣扎而没有成功,有人能做到这一点吗?至少知道这是有可能的,并且这不是一些未记录的限制或类似限制。

swift video avplayer
1个回答
0
投票

我终于让它工作了。因此,上面的代码有2个问题:

1)contentType应该是AVFileType.mp4.rawValue,它是“ public.mpeg-4”。传递“ video / mp4”或其他值会破坏它

2)resourceLoadingRequest.dataRequest!.requestedLength实际上需要得到尊重,因此视频文件需要按请求分块发送。

这是工作代表代码:

// this IF is an ugly way to catch the first request to the delegate
// in this request you should populate the contentInformationRequest struct with the size of the video, etc
if (resourceLoadingRequest.dataRequest!.requestedLength == 2) {
    let bytes : [UInt8] = [0x0, 0x0] // these are the first 2 bytes of the video, as requested
    let data = Data(bytes: bytes, count: bytes.count)

    resourceLoadingRequest.contentInformationRequest?.contentType = AVFileType.mp4.rawValue // this is public.mpeg-4, video/mp4 does not work
    resourceLoadingRequest.contentInformationRequest?.isByteRangeAccessSupported = true
    resourceLoadingRequest.contentInformationRequest?.contentLength = Int64(videoSize)

    resourceLoadingRequest.dataRequest!.respond(with: data)
    resourceLoadingRequest.finishLoading()

    return true
}

// here we are at the second request. the OS may request the entire file, or a portion of it 
// here we don't need to set any headers or contentInformationRequest, just reply with the requested data
resourceLoadingRequest.dataRequest?.respond(with: data)
resourceLoadingRequest.finishLoading()

return true
© www.soinside.com 2019 - 2024. All rights reserved.