我无法连接到通过HLS与128位加密连接的实时流,它是一个Azure媒体流。服务器还需要一个授权令牌,该令牌通过HTTP标头Authorization
提供,类型为Bearer <insert token here>
。
我的代码是:
let url = "http://<redacted>"
let headers = ["Authorization": "Bearer <token redacted>"]
let options = ["AVURLAssetHTTPHeaderFieldsKey": headers]
let avAsset = AVURLAsset(url: URL(string: url)!, options: options)
let avItem = AVPlayerItem(asset: avAsset)
player = AVPlayer(playerItem: avItem)
player.play()
我已经调试了网络呼叫,AVPlayer
发出了2个呼叫,一个用于查看是否有新版本(我猜测是从我在该呼叫上收到的304),还有一个用于获取流。这些调用分别返回304 Not Modified和206 Partial Content。
这些电话:
我没有听到任何声音,但设备上的任何其他声音都被静音(应该如此)。这告诉我播放接收的数据存在问题。我的同事可以在Android上加载流,只需在此处执行操作,我可以在http://ampdemo.azureedge.net/azuremediaplayer.html上加载。
我通过抓取player.currentItem?.status
来检查播放器的状态,这是failed
。 player.currentItem?.error
是
错误域= AVFoundationErrorDomain代码= -11828&#34;无法打开&#34; UserInfo = {NSUnderlyingError = 0x60800005a610 {Error Domain = NSOSStatusErrorDomain Code = -12847&#34;(null)&#34;},NSLocalizedFailureReason =不支持此媒体格式。,NSLocalizedDescription =无法打开}
编辑:我尝试进一步调试。我实施了AVAssetResourceLoaderDelegate
,并在resourceLoader:shouldWaitForLoadingOfRequestedResource:
中添加了以下代码:
func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
DispatchQueue.main.async {
var request = loadingRequest.request
var headers = request.allHTTPHeaderFields!
if headers["Authorization"] == nil {
headers["Authorization"] = "Bearer <token>"
} else {
print("Auth header exists: \(headers)")
}
request.url = URL(string: self.url)!
request.allHTTPHeaderFields = headers
URLSession(configuration: URLSessionConfiguration.default).dataTask(with: request) {
data, response, error in
if let error = error {
print(error)
loadingRequest.finishLoading(with: error)
} else {
loadingRequest.dataRequest?.respond(with: data!)
loadingRequest.finishLoading()
}
}.resume()
}
return true
}
我只在尚未存在时添加Authorization
标题。我认为在所有调用中覆盖Authorization
标头可能会破坏加密。
由于resourceLoader:shouldWaitForLoadingOfRequestedResource:
仅在请求使用http
和https
以外的方案时被调用,因此我将http://
替换为mycustomscheme://
。这也是我在这里设置网址的原因,因为请求中的原始网址没有有效的网址方案。
这种方式对我来说更好,因为我可以查看请求和响应,因为它们正在发生。没有更多的Burp Suite来调试电话。
我现在遇到的问题是我收到了我期望的数据(播放器确实执行了两次相同的请求),但当我检查player.currentItem?.status
时,这是failed
。 player.currentItem?.error
是
错误域= NSURLErrorDomain代码= -1001&#34;请求超时。&#34; UserInfo = {NSLocalizedDescription =请求超时。,NSUnderlyingError = 0x60000005f320 {错误域= NSOSStatusErrorDomain代码= -1001&#34;(null)&#34;}}
对我来说似乎很奇怪,因为Android和网络版本没有问题,我会暂停。
我查看了Android代码,他使用的是<url>.ism/manifest(format=m3u8-aapl-v3)
而不是<url>.ism/manifest
。如果我使用该网址,则会获得相同的failed
状态,但错误为
错误域= AVFoundationErrorDomain代码= -11800&#34;操作无法完成&#34; UserInfo = {NSUnderlyingError = 0x608000059e60 {Error Domain = NSOSStatusErrorDomain Code = -12936&#34;(null)&#34;},NSLocalizedFailureReason =发生未知错误(-12936),NSLocalizedDescription =操作无法完成}
好的,我得到了它的工作,但我不知道它为什么有用,为什么它没有工作。我输入了Android执行的URL作为第二次调用来获取流,这个URL嵌入了质量信息。它的格式为<url>.ism/QualityLevels(3782)/Manifest(video,format=m3u8-aapl-v3,audiotrack=aac_UND_2_192)
。
有谁能解释这里发生了什么?