使用 avplayer 播放 AES 加密的 hls 流 - ios swift

Playing AES encrypted hls stream using avplayer - ios swift

我正在尝试在 AVPlayer 中播放 AES 加密流。通常,link 密钥会传送到 M3U8 播放列表中的播放器。在我的场景中,密钥被分成两半。 . 前半部分由服务器发送,我应该将另一半附加到应用程序中以在播放时解密

我已经在 Android 上完成了这个,有没有办法在 iOS 上也这样做?

这是播放列表:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=200000,RESOLUTION=284x160
chunklist_w670540365_b200000.m3u8?t=57b5b16d3824d
#EXT-X-STREAM-INF:BANDWIDTH=850000,RESOLUTION=640x360
chunklist_w670540365_b850000.m3u8?t=57b5b16d3824d

这是块列表:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:13544
#EXT-X-KEY:METHOD=AES-128,URI="http://example.com/api/getEncryptionKey?t=57b5b16d3824d"
#EXTINF:9.6,
media_w670540365_b200000_13544.ts?t=57b5b16d3824d
#EXTINF:9.6,
media_w670540365_b200000_13545.ts?t=57b5b16d3824d
#EXTINF:10.56,
media_w670540365_b200000_13546.ts?t=57b5b16d3824d

这是 AVPlayer 的作用:

1- 下载播放列表并选择块列表 2- 玩家下载区块列表 3- 解密块的解密密钥已下载 4- 播放器开始按顺序下载块来播放它们 5-每个块都被解密和播放

我需要做的是: 在玩家调用 api 使用此 link 获取加密密钥的第 3 步之后:'http://example.com/api/getEncryptionKey?t=57b5b16d3824d',我想拦截响应并附加密钥的另一半

可能吗?

是的,很有可能!我最近在我的一个项目中做到了。

每当 AVPlayer 加载加密视频时,它都会尝试从 prog_index.m3u8 中提到的 URL 加载解密密钥。如果 AVPlayer 无法使用获取的密钥播放视频,或者它根本没有在指定的 url 上获取密钥,它会调用 AVAssetResourceLoaderDelegate 的委托方法,即

 public func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForRenewalOfRequestedResource renewalRequest: AVAssetResourceRenewalRequest) -> Bool {
    return shouldLoadOrRenewRequestedResource(resourceLoadingRequest: renewalRequest)
}

并且

public func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
    return shouldLoadOrRenewRequestedResource(resourceLoadingRequest: loadingRequest)
}

当然,它们在被调用的情况下有所不同。前一个在玩家应该等待加载资源时调用,后一个在玩家需要更新资源时调用。

func shouldLoadOrRenewRequestedResource(resourceLoadingRequest: AVAssetResourceLoadingRequest) -> Bool {

    guard var url = resourceLoadingRequest.request.url else {
        return false
    }

   //FETCH THE KEY FROM NETWORK CALL/KEYSTORE, CONVERT IT TO DATA AND FINISH LOADING OF RESOURCE WITH THAT DATA, IN YOUR CASE JOIN THE OTHER HALF OF THE KEY TO ACTUAL KEY (you can get the first half from the url above)
   resourceLoadingRequest.dataRequest?.respond(with: keyData)
   resourceLoadingRequest.finishLoading()

    return true;
}}

一旦您 return 使用实际密钥,视频将立即播放。

尝试使用 Azure 媒体服务时,以下示例运行良好。在这里,我们将令牌添加为 AVURLAsset 选项的一部分。

    var options = [String: [String: String]]()
    if (!token.isEmpty) {
        let headers = ["Authorization": "Bearer " + token!]
        options = ["AVURLAssetHTTPHeaderFieldsKey": headers]
    }
    let avAsset = AVURLAsset(url: videoUrl, options: options)
    let avItem = AVPlayerItem(asset: avAsset)
    let player = AVPlayer(playerItem: avItem)
    
    let playerFrame = view.viewWithTag(1)?.frame
    controller.player = player
    if (autoPlay.isOn) {
        player.rate = 1
    }
    controller.view.frame = playerFrame ?? CGRect(x: 0, y: 0, width: view.frame.width , height: 250)
    addChild(controller)
    view.viewWithTag(1)?.addSubview(controller.view)
    controller.didMove(toParent: self)
    

完整的工作样本可以从

找到

https://github.com/Azure-Samples/media-services-3rdparty-player-samples/tree/master/src/avplayer