Swift 中的 Fairplay 实现,AVAssetResourceDelegate
Posted
技术标签:
【中文标题】Swift 中的 Fairplay 实现,AVAssetResourceDelegate【英文标题】:Fairplay implementation in Swift, AVAssetResourceDelegate 【发布时间】:2018-01-19 12:11:43 【问题描述】:我观看了 Apple FairPlay 介绍视频,我阅读了以下代码: https://gist.github.com/fousa/5709fb7c84e5b53dbdae508c9cb4fadc 而且我还浏览了苹果的 HLS 目录,最后一个问题是我只需要播放 DRM 视频而无需任何下载和所有这些东西,所以我从 GitHub 示例开始。 我有证书、FairPlay 中的视频和密钥服务器模块。 我的第一个也是主要的问题是当我给 AVURLAsset 提供视频 url 时 AVResourceDelegate 没有调用。我在堆栈中读到我需要将方案更改为其他内容,例如来自 https 的“DRM”和正确的 AVResourceDelegate 调用,但我没有 .m3u8 文件,因为视频链接错误! 你能不能请男孩/女孩帮帮我。
import Foundation
import AVKit
import NotificationCenter
public struct DRMVideoData
var drmKey: String?
var proxyFairPlay: String
var fileFairPlay: String
var idVideo: String
class VODDRMImplementation: NSObject, AVAssetResourceLoaderDelegate
let domain = "DRMDelegate.ContentKeyQueue"
let contentKeyDelegateQueue = DispatchQueue(label: "DRMDelegate.ContentKeyQueue")
var drmData: DRMVideoData?
func startPlayerWithDRM(_ videoDRM: DRMVideoData,_ player: AVPlayer?,_ playerLayer: AVPlayerLayer?, c: @escaping (AVPlayer?, AVPlayerLayer?) -> Void)
var urlcomp = URLComponents(string: videoDRM.fileFairPlay)
urlcomp?.scheme = "drm"
if let url = try? urlcomp?.asURL()
self.drmData = videoDRM
let url = url
let asset = AVURLAsset(url: url!)
asset.resourceLoader.setDelegate(self, queue: self.contentKeyDelegateQueue)
let playerItem = AVPlayerItem(asset: asset)
let player = AVPlayer(playerItem: playerItem)
let playerLayer = AVPlayerLayer(player: player)
player.pause()
c(player, playerLayer)
else
c(nil, nil)
func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool
log.debug("DRM: started")
// getting data for KSM server
guard let urlToConvert = loadingRequest.request.url,
let drmData = drmData else
log.debug("DRM: unable to read URL from loadingRequest")
loadingRequest.finishLoading(with: NSError(domain: domain, code: -1, userInfo: nil))
return false
do
log.debug("DRM: video link \(urlToVideo)")
guard let certificateData = getCertificateFromServer() else
log.debug("DRM: false to get public certificate")
loadingRequest.finishLoading(with: NSError(domain: domain, code: -3, userInfo: nil))
return false
let contentId = drmData.idVideo // content id
guard let contentIdData = contentId.data(using: String.Encoding.utf8),
let spcData = try? loadingRequest.streamingContentKeyRequestData(forApp: certificateData, contentIdentifier: contentIdData, options: nil),
let dataRequest = loadingRequest.dataRequest else
loadingRequest.finishLoading(with: NSError(domain: domain, code: -3, userInfo: nil))
log.debug("DRM: false to get SPC Data from video")
return false
let ksmServer = URL(string: drmData.proxyFairPlay)! // KSM link
var request = URLRequest(url: ksmServer)
request.httpMethod = "GET"
request.httpBody = spcData
let session = URLSession(configuration: .default)
let task = session.dataTask(with: request) data, response, error in
guard let data = data else
log.debug("DRM: unable to fetch ckc key :/")
loadingRequest.finishLoading(with: NSError(domain: self.domain, code: -4, userInfo: nil))
return
dataRequest.respond(with: data)
loadingRequest.finishLoading()
task.resume()
catch
loadingRequest.finishLoading(with: NSError(domain: domain, code: -3, userInfo: nil))
log.debug("DRM: cannot generate url to video")
return false
return true
func takeURLFromId(_ videoLink: String) -> URL
let urlString = videoLink
let url = URLComponents(string: urlString)
do
let urlToReturn = try url?.asURL()
guard let urlToReturn2 = urlToReturn else
let error = NSError(domain: domain, code: 0, userInfo: nil)
throw error
return urlToReturn2
catch
if let url = NSURL(string: videoLink)
return url as URL
else
return NSURL(string: videoLink)! as URL
func getCertificateFromServer() -> Data?
let filePath = Bundle.main.path(forResource: "privatekey", ofType: "pem")
guard let data = try? Data(contentsOf: URL(string: filePath!)!) else
return nil
return data
【问题讨论】:
您好,您得到解决方案了吗,如果是,请分享答案 @pkesaj 你得到答案了吗? @RaviOjha 你解决了这个问题吗? @AmritTiwari 对不起。我没有得到解决方案 你是在设备还是模拟器上测试?不幸的是,您只会在设备上运行时获得 shouldWaitForLoadingOfRequestedResource 回调。此外,如果您正在寻找好的测试流,您可以在苹果开发者网站的“FairPlay Streaming Test Streams”下找到有效的 .m3u8 文件:developer.apple.com/streaming/fps 【参考方案1】:你可以试试换行:
player.pause()
到 player.play()
另外,我认为在您的班级中保留对播放器的引用应该会有所帮助,如下所示:
var player: AVPlayer?
【讨论】:
以上是关于Swift 中的 Fairplay 实现,AVAssetResourceDelegate的主要内容,如果未能解决你的问题,请参考以下文章
Azure 媒体服务 Fairplay V3 DRM 内容密钥策略