适用于 iOS 的脱机 FairPlay 流式处理与媒体服务 v3Offline FairPlay Streaming for iOS with Media Services v3

Azure 媒体服务提供一套设计良好的内容保护服务,包括:Azure Media Services provides a set of well-designed content protection services that cover:

备注

Google Widevine 内容保护服务目前在 Azure 中国区域不可用。Google Widevine content protection services are currently unavailable in the Azure China regions.

  • Microsoft PlayReadyMicrosoft PlayReady
  • Apple FairPlayApple FairPlay
  • AES-128 加密AES-128 encryption

数字版权管理 (DRM)/高级加密标准 (AES) 基于各种流式处理协议的请求,动态执行内容的 DRM/AES 加密。Digital rights management (DRM)/Advanced Encryption Standard (AES) encryption of content is performed dynamically upon request for various streaming protocols. 媒体服务还提供 DRM 许可证/AES 解密密钥传送服务。DRM license/AES decryption key delivery services also are provided by Media Services.

除通过各种流式处理协议对联机流式处理的内容提供保护外,通常还要求提供受保护内容的脱机模式功能。Besides protecting content for online streaming over various streaming protocols, offline mode for protected content is also an often-requested feature. 以下情况需要脱机模式支持:Offline-mode support is needed for the following scenarios:

  • 在 Internet 连接不可用(如旅行期间)时播放。Playback when internet connection isn't available, such as during travel.
  • 某些内容提供程序可能不允许在某个国家/地区的边界之外进行 DRM 许可证传送。Some content providers might disallow DRM license delivery beyond a country/region's border. 如果用户想在该国家/地区外旅行期间查看内容,需要脱机下载。If users want to watch content while traveling outside of the country/region, offline download is needed.
  • 在某些国家/地区,Internet 可用性和/或宽带仍然受到限制。In some countries/regions, internet availability and/or bandwidth is still limited. 为获得满意的观看体验,用户可能选择首先下载以便能够观看高分辨率的内容。Users might choose to download first to be able to watch content in a resolution that is high enough for a satisfactory viewing experience. 在此情况下,通常问题不在于网络可用性,而在于受限的网络宽带。In this case, the issue typically isn't network availability but limited network bandwidth. 此时,Over-the-Top (OTT)/联机视频平台 (OVP) 提供商会请求脱机模式支持。Over-the-top (OTT)/online video platform (OVP) providers request offline-mode support.

本文介绍 FairPlay Streaming (FPS) 脱机模式支持,适用于运行 iOS 10 或更高版本的设备。This article covers FairPlay Streaming (FPS) offline-mode support that targets devices running iOS 10 or later. 此功能不支持其他 Apple 平台,例如 watchOS、tvOS 或 macOS 上的 Safari。This feature isn't supported for other Apple platforms, such as watchOS, tvOS, or Safari on macOS.

备注

下载内容时,脱机 DRM 仅针对发出单个许可证请求进行计费。Offline DRM is only billed for making a single request for a license when you download the content. 任何错误都不收费。Any errors are not billed.

先决条件Prerequisites

在 iOS 10+ 设备上为 FairPlay 实现 脱机 DRM 之前:Before you implement offline DRM for FairPlay on an iOS 10+ device:

在 Azure 媒体服务中配置内容保护Configure content protection in Azure Media Services

GetOrCreateContentKeyPolicyAsync 方法中,执行以下操作:In the GetOrCreateContentKeyPolicyAsync method, do the following:

取消评论配置 FairPlay 策略选项的代码:Uncomment the code that configures the FairPlay policy option:

ContentKeyPolicyFairPlayConfiguration fairplayConfig = ConfigureFairPlayPolicyOptions();

此外,取消评论将 CBCS ContentKeyPolicyOption 添加到 ContentKeyPolicyOptions 列表中的代码Also, uncomment the code that adds CBCS ContentKeyPolicyOption into the list of ContentKeyPolicyOptions

options.Add(
    new ContentKeyPolicyOption()
    {
        Configuration = fairplayConfig,
        Restriction = restriction,
        Name = "ContentKeyPolicyOption_CBCS"
    });

启用脱机模式Enable offline mode

若要启用脱机模式,请在 CreateStreamingLocatorAsync 中创建 StreamingLocator 时创建自定义 StreamingPolicy 并使用其名称。To enable offline mode, create a custom StreamingPolicy and use its name when creating a StreamingLocator in CreateStreamingLocatorAsync.

CommonEncryptionCbcs objStreamingPolicyInput= new CommonEncryptionCbcs()
{
    Drm = new CbcsDrmConfiguration()
    {
        FairPlay = new StreamingPolicyFairPlayConfiguration()
        {
            AllowPersistentLicense = true // This enables offline mode
        }
    },
    EnabledProtocols = new EnabledProtocols()
    {
        Hls = true,
        Dash = true // Even though DASH under CBCS is not supported for either CSF or CMAF, HLS-CMAF-CBCS uses DASH-CBCS fragments in its HLS playlist
    },

    ContentKeys = new StreamingPolicyContentKeys()
    {
        // Default key must be specified if keyToTrackMappings is present
        DefaultKey = new DefaultKey()
        {
            Label = "CBCS_DefaultKeyLabel"
        }
    }
}

现在,媒体服务帐户已配置为传送脱机 FairPlay 许可证。Now your Media Services account is configured to deliver offline FairPlay licenses.

示例 iOS 播放器Sample iOS Player

FPS 脱机模式支持仅适用于 iOS 10 及更高版本。FPS offline-mode support is available only on iOS 10 and later. FPS Server SDK(3.0 或更高版本)包含 FPS 脱机模式文档和示例。The FPS Server SDK (version 3.0 or later) contains the document and sample for FPS offline mode. 具体而言,FPS Server SDK(3.0 或更高版本)包含以下与脱机模式相关的两项:Specifically, FPS Server SDK (version 3.0 or later) contains the following two items related to offline mode:

  • 文档:“使用 FairPlay Streaming 和 HTTP Live Streaming 的脱机播放”。Document: "Offline Playback with FairPlay Streaming and HTTP Live Streaming." 2016 年 9 月 14 日由 Apple 提供。Apple, September 14, 2016. 在 FPS Server SDK 版本 4.0 中,此文档已合并到主要 FPS 文档。In FPS Server SDK version 4.0, this document is merged into the main FPS document.

  • 示例代码:\FairPlay Streaming Server SDK version 3.1\Development\Client\HLSCatalog_With_FPS\HLSCatalog\ 中 FPS 脱机模式的 HLSCatalog 示例(Apple 的 FPS Server SDK 的一部分)。Sample code: HLSCatalog sample (part of the Apple's FPS Server SDK) for FPS offline mode in the \FairPlay Streaming Server SDK version 3.1\Development\Client\HLSCatalog_With_FPS\HLSCatalog. 在 HLSCatalog 示例应用中,以下代码文件用于实现脱机模式功能:In the HLSCatalog sample app, the following code files are used to implement offline-mode features:

    • AssetPersistenceManager.swift 代码文件:AssetPersistenceManager 是此示例中的主类,演示如何:AssetPersistenceManager.swift code file: AssetPersistenceManager is the main class in this sample that demonstrates how to:

      • 管理下载 HLS 流,例如用于开始和取消下载的 API 以及用于删除用户设备中现有资产的 API。Manage downloading HLS streams, such as the APIs used to start and cancel downloads and to delete existing assets off devices.
      • 监视下载进度。Monitor the download progress.
    • AssetListTableViewController.swift 和 AssetListTableViewCell.swift 代码文件:AssetListTableViewController 是此示例的主接口。AssetListTableViewController.swift and AssetListTableViewCell.swift code files: AssetListTableViewController is the main interface of this sample. 它提供示例可以用来播放、下载、删除或取消下载的资产列表。It provides a list of assets the sample can use to play, download, delete, or cancel a download.

以下步骤说明如何设置正在运行的 iOS 播放器。These steps show how to set up a running iOS player. 假设从 FPS Server SDK 版本 4.0.1 的 HLSCatalog 示例开始。需要对代码进行以下更改:Assuming you start from the HLSCatalog sample in FPS Server SDK version 4.0.1, make the following code changes:

在 HLSCatalog\Shared\Managers\ContentKeyDelegate.swift 中,使用以下代码实现方法 requestContentKeyFromKeySecurityModule(spcData: Data, assetID: String)In HLSCatalog\Shared\Managers\ContentKeyDelegate.swift, implement the method requestContentKeyFromKeySecurityModule(spcData: Data, assetID: String) by using the following code. 使“drmUr”成为分配到 HLS URL 的变量。Let "drmUr" be a variable assigned to the HLS URL.

    var ckcData: Data? = nil
    
    let semaphore = DispatchSemaphore(value: 0)
    let postString = "spc=\(spcData.base64EncodedString())&assetId=\(assetIDString)"
    
    if let postData = postString.data(using: .ascii, allowLossyConversion: true), let drmServerUrl = URL(string: self.drmUrl) {
        var request = URLRequest(url: drmServerUrl)
        request.httpMethod = "POST"
        request.setValue(String(postData.count), forHTTPHeaderField: "Content-Length")
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpBody = postData
        
        URLSession.shared.dataTask(with: request) { (data, _, error) in
            if let data = data, var responseString = String(data: data, encoding: .utf8) {
                responseString = responseString.replacingOccurrences(of: "<ckc>", with: "").replacingOccurrences(of: "</ckc>", with: "")
                ckcData = Data(base64Encoded: responseString)
            } else {
                print("Error encountered while fetching FairPlay license for URL: \(self.drmUrl), \(error?.localizedDescription ?? "Unknown error")")
            }
            
            semaphore.signal()
            }.resume()
    } else {
        fatalError("Invalid post data")
    }
    
    semaphore.wait()
    return ckcData

在 HLSCatalog\Shared\Managers\ContentKeyDelegate.swift 中,实现方法 requestApplicationCertificate()In HLSCatalog\Shared\Managers\ContentKeyDelegate.swift, implement the method requestApplicationCertificate(). 此实现取决于是将证书(仅公钥)嵌入设备还是将证书托管在 Web 上。This implementation depends on whether you embed the certificate (public key only) with the device or host the certificate on the web. 下面是使用测试示例中使用的托管应用程序证书的实现。The following implementation uses the hosted application certificate used in the test samples. 使 certUrl 成为一个包含应用程序证书 URL 的变量。Let "certUrl" be a variable that contains the URL of the application certificate.

func requestApplicationCertificate() throws -> Data {

        var applicationCertificate: Data? = nil
        do {
            applicationCertificate = try Data(contentsOf: URL(string: certUrl)!)
        } catch {
            print("Error loading FairPlay application certificate: \(error)")
        }
        
        return applicationCertificate
    }

对于最终集成测试,“集成测试”部分将提供视频 URL 和应用程序证书 URL 两者。For the final integrated test, both the video URL and the application certificate URL are provided in the section "Integrated Test."

在 HLSCatalog\Shared\Resources\Streams.plist 中添加测试视频 URL。In HLSCatalog\Shared\Resources\Streams.plist, add your test video URL. 对于内容密钥 ID,只需使用带有 SKD 协议的 FairPlay 许可证获取 URL 作为唯一值。For the content key ID, use the FairPlay license acquisition URL with the skd protocol as the unique value.

脱机 FairPlay iOS 应用流

如果已设置,可以使用自己的测试视频 URL、FairPlay 许可证获取 URL 和应用程序证书 URL。Use your own test video URL, FairPlay license acquisition URL, and application certificate URL, if you have them set up. 或者,可以继续查看包含测试示例的下一部分。Or you can continue to the next section, which contains test samples.

集成测试Integrated test

媒体服务中的三个测试示例包含以下三种方案:Three test samples in Media Services cover the following three scenarios:

  • FPS 受到保护,包括视频、音频和备用音频曲目FPS protected, with video, audio, and alternate audio track
  • FPS 受到保护,包括视频、音频,但不包括备用音频曲目FPS protected, with video and audio, but no alternate audio track
  • FPS 受到保护,仅包括视频,不包括音频FPS protected, with video only and no audio

可在此演示站点上找到这些示例,相应的应用程序证书托管在 Azure Web 应用中。You can find these samples at this demo site, with the corresponding application certificate hosted in an Azure web app. 使用 FPS Server SDK 的版本 3 或版本 4 示例时,如果在脱机模式期间主播放列表包含备用的音频,则只播放音频。With either the version 3 or version 4 sample of the FPS Server SDK, if a master playlist contains alternate audio, during offline mode it plays audio only. 因此,需要删除备用音频。Therefore, you need to strip the alternate audio. 换言之,前面所列的第二和第三个示例在联机和脱机模式下都可正常运行。In other words, the second and third samples listed previously work in online and offline mode. 所列的第一个示例在脱机模式期间只播放音频,联机流式处理可正常运行。The sample listed first plays audio only during offline mode, while online streaming works properly.

常见问题FAQ

请参阅常见问题解答提供故障排除帮助See frequently asked questions provide assistance with troubleshooting.

后续步骤Next steps

了解如何使用 AES-128 提供保护Check out how to protect with AES-128