gpt4 book ai didi

ios - AVPlayer 在在线模式下停止播放 AES 加密的离线 HLS 视频

转载 作者:行者123 更新时间:2023-12-01 22:19:46 25 4
gpt4 key购买 nike

我编写了一个代码来下载 HLS 视频并在离线模式下播放。
此代码适用于编码视频。现在我有一个 AES 加密的视频,我们有自定义的加密 key 。下载 AES 加密 HLS 视频后,我使用下面给定的代码来提供用于解密视频的 key 。

- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest {

NSString *scheme = loadingRequest.request.URL.scheme;

if ([scheme isEqualToString:@"ckey"]) {

NSString *request = loadingRequest.request.URL.host;
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:request];

if (data) {
[loadingRequest.dataRequest respondWithData:data];
[loadingRequest finishLoading];
} else {
// Data loading fail
}
}
return NO; }

我正在拦截对 key 的请求并传递存储在 UserDefaults 中的 key 以进行解密。

当我的设备的 wifi 或数据连接关闭时,此带有自定义 key 的 AES 加密 HLS 视频播放良好。

如果我在设备的 wifi 或数据连接启用时开始播放此视频,或者如果
我在播放视频时启用了设备的 wifi 或数据连接;视频立即停止播放,没有任何错误,并且不再播放。


我检查了 playerItem 的 accessLog 和 errorLog 但没有发现任何有用的东西。

为了在下载 HLS 内容后提供自定义 URL key ,我通过替换来更新 .m3u8 文件的内容

URI="..."



字符串与

URI="ckey://..."



这是为 AES 加密视频提供 key 的正确方法吗?

这种行为的原因可能是什么以及如何解决这个问题?

提前致谢。

最佳答案

最后我设法解决了这个问题。下载的 HLS 视频的大致包结构如下所示:

HLS.movpkg 
|_ 0-12345
|_ 123.m3u8
|_ StreamInfoBoot.xml
|_ StreamInfoRoot.xml
|_ <>.frag
|_ boot.xml
  • boot.xml 包含 HLS 的网络 URL(基于 https:)
  • StreamBootInfo.xml 包含 HLS URL(基于 https:)和本地下载的 .frag 文件之间的映射。

  • 在离线模式下,HLS 视频播放完美。但是当启用网络连接时,它指的是 https: URL 而不是本地 .frag 文件。
    我用自定义方案 (fakehttps:) 替换了这些文件中的 https: 方案,以限制 AVPlayer 在线获取资源。
    这件事解决了我的问题,但我不知道它背后的确切原因以及 AVPlayer 如何播放 HLS。
    我提到了 this 并得到了一些想法,所以尝试了一些东西。
    我正在进一步更新这个答案,以解释如何在离线模式下播放加密视频。
    1. Get the key required for video decryption.

    2. Save that key some where.

    You can save that key as NSData or Data object in UserDefault I am using video file name as key to save key data in UserDefaults.

    1. Use FileManager API to iterate over all the files inside .movpkg.

    2. Get the content of each .m3u8 file and replace URI="some key url" with URI="ckey://keyusedToSaveKeyDataInUserDefaults"

    You can refer code given below for this process.

      if let url = asset.asset?.url, let data = data {

    let keyFileName = "\(asset.contentCode!).key"
    UserDefaults.standard.set(data, forKey: keyFileName)

    do {

    // ***** Create key file *****
    let keyFilePath = "ckey://\(keyFileName)"

    let subDirectories = try fileManager.contentsOfDirectory(at: url,
    includingPropertiesForKeys: nil, options: .skipsSubdirectoryDescendants)

    for url in subDirectories {

    var isDirectory: ObjCBool = false

    if fileManager.fileExists(atPath: url.path, isDirectory: &isDirectory) {

    if isDirectory.boolValue {

    let path = url.path as NSString

    let folderName = path.lastPathComponent
    let playlistFilePath = path.appendingPathComponent("\(folderName).m3u8")

    if fileManager.fileExists(atPath: playlistFilePath) {

    var fileContent = try String.init(contentsOf: URL.init(fileURLWithPath: playlistFilePath))

    let stringArray = self.matches(for: "URI=\"(.+?)\"", in: fileContent)

    for pattern in stringArray {
    fileContent = fileContent.replacingOccurrences(of: pattern, with: "URI=\"\(keyFilePath)\"")
    }

    try fileContent.write(toFile: playlistFilePath, atomically: true, encoding: .utf8)
    }

    let streamInfoXML = path.appendingPathComponent("StreamInfoBoot.xml")

    if fileManager.fileExists(atPath: streamInfoXML) {

    var fileContent = try String.init(contentsOf: URL.init(fileURLWithPath: streamInfoXML))
    fileContent = fileContent.replacingOccurrences(of: "https:", with: "fakehttps:")
    try fileContent.write(toFile: streamInfoXML, atomically: true, encoding: .utf8)
    }
    } else {

    if url.lastPathComponent == "boot.xml" {

    let bootXML = url.path

    if fileManager.fileExists(atPath: bootXML) {

    var fileContent = try String.init(contentsOf: URL.init(fileURLWithPath: bootXML))
    fileContent = fileContent.replacingOccurrences(of: "https:", with: "fakehttps:")
    try fileContent.write(toFile: bootXML, atomically: true, encoding: .utf8)
    }
    }
    }
    }
    }

    userInfo[Asset.Keys.state] = Asset.State.downloaded.rawValue

    // Update download status to db
    let user = RoboUser.sharedObject()
    let sqlDBManager = RoboSQLiteDatabaseManager.init(databaseManagerForCourseCode: user?.lastSelectedCourse)
    sqlDBManager?.updateContentDownloadStatus(downloaded, forContentCode: asset.contentCode!)

    self.notifyServerAboutContentDownload(asset: asset)

    NotificationCenter.default.post(name: AssetDownloadStateChangedNotification, object: nil, userInfo: userInfo)
    } catch {
    }
    }

    func matches(for regex: String, in text: String) -> [String] {

    do {
    let regex = try NSRegularExpression(pattern: regex)
    let nsString = text as NSString
    let results = regex.matches(in: text, range: NSRange(location: 0, length: nsString.length))
    return results.map { nsString.substring(with: $0.range)}
    } catch let error {
    print("invalid regex: \(error.localizedDescription)")
    return []
    }
    }
    这将更新您的下载包结构,以便在离线模式下播放加密视频。
    现在要做的最后一件事是在 AVAssetResourceLoader 类的给定方法下面实现如下
    - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest {

    NSString *scheme = loadingRequest.request.URL.scheme;

    if ([scheme isEqualToString:@"ckey"]) {

    NSString *request = loadingRequest.request.URL.host;
    NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:request];

    if (data) {
    loadingRequest.contentInformationRequest.contentType = AVStreamingKeyDeliveryPersistentContentKeyType;
    loadingRequest.contentInformationRequest.byteRangeAccessSupported = YES;
    loadingRequest.contentInformationRequest.contentLength = data.length;
    [loadingRequest.dataRequest respondWithData:data];
    [loadingRequest finishLoading];
    } else {
    // Data loading fail
    }
    }

    return YES;
    }
    此方法将在播放时提供视频 key 以对其进行解密。

    关于ios - AVPlayer 在在线模式下停止播放 AES 加密的离线 HLS 视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46097856/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com