# Apple FairPlay 集成

了解如何使用 Swift 和 AVFoundation，在 iOS、iPadOS、tvOS 及 Safari 上接入 DRM-X 6.0 FairPlay Streaming，包括服务端授权以及 SPC 请求和 CKC 响应的处理。

FairPlay 证书与许可证交互流程

整个交互过程中，SPC 和 CKC 二进制数据必须保持原样。

- 01**证书**

从获准访问的 URL 加载应用证书。

- 02**SPC**

使用证书和 HLS 标识符，生成设备的 SPC 请求。

- 03**CKC**

将 SPC 发送到获准访问的许可证 URL，并接收 CKC 响应。

- 04**AVFoundation**

将 CKC 交给 AVFoundation，用于播放加密视频。

证书 – SPC 挑战 – CKC 回复 – 本地播放 。 保留二进制挑战和响应字节不变 。

**开发状态**实体 iPhone 测试已覆盖加密下载、本地续播、播放列表模式和续期。测试传输层还验证了阻止 SDK 发起 HTTP 请求时的本地播放；当时设备 Wi-Fi 仍开启。发布前仍需验证完全断网播放、实体 iPad，以及您的内容和输出策略。可分发的原生示例包尚未完成。更新后的 WayMaker HLS 主播放列表及重新下载的 iPhone 内容已验证中英文 WebVTT 字幕；其他媒体需要各自提供兼容字幕轨道。这些播放器改进属于开发构建，并不代表新的客户 SDK 已正式发布。 

## 集成前配置 FairPlay 部署[#](#register-fairplay-before-integration)

在 DRM-X Console 中配置 FairPlay 部署及证书材料。私钥材料以加密形式保留在服务器端。为待测试的 Content ID 发布 HLS/CBCS 版本。



## 请求 Apple 会话[#](#request-the-apple-session)

由已认证的后端发送 `drmSystem: fairplay`、`manifestTypes: ["hls"]` 和适当的 `clientPlatform`。响应包含已注册的 HLS Manifest、证书路径、CKC 许可证路径、授权说明及会话释放路径。

**保留原生二进制数据**除非响应中的接口契约明确要求，否则不要对 SPC 和 CKC 进行 Base64 转换、JSON 封装或重新解释。按原始二进制请求和响应类型进行转发。



## AVFoundation 接入步骤[#](#avfoundation-sequence)

- **加载证书。**使用响应返回的受限授权，从指定的 FairPlay 证书 URL 获取证书。
- **生成内容密钥请求数据。**使用 HLS 播放列表提供的 `skd://` 标识及应用证书。
- **发送 SPC。**通过 POST 向返回的许可证 URL 原样发送 SPC 字节，并原样接收 CKC 字节。
- **完成请求并释放会话。**响应内容密钥请求；观看结束后释放 DRM-X 会话。



## Safari 和原生应用验收[#](#safari-and-app-acceptance)

- 在 iPhone 和 iPad Safari 中测试原生 HLS FairPlay。
- 在 macOS Safari 中测试可用的 Shaka MSE FairPlay 路径，以及回退到原生 HLS 的情况。
- 测试原生 iOS、iPadOS 和 tvOS 播放，包括 AirPlay 策略、AV 转接器策略、前后台切换、许可证续期及输出设备变化。
- Development 和 Production 使用各自独立的 FairPlay 部署及凭据。



Apple SDK 

## iOS、iPadOS 和 tvOS 的原生 FairPlay 集成[#](#ios-ipados-and-tvos-with-native-fairplay)



Swift Package 面向 iOS 和 tvOS 15+，通过 AVFoundation 的 AVContentKeySession 处理 FairPlay 内容密钥请求，涵盖证书获取、二进制 SPC/CKC 交换、续期、取消及会话释放。



```
import AVKit
import DrmXFairPlay

let controller = DrmXFairPlayPlayer()
let player = try await controller.prepare(
    endpoint: URL(string: "https://customer.example/api/drmx/playback-session")!,
    contentId: "course-12-lesson-4",
    contentType: .vod,
    customerHeaders: ["Authorization": "Bearer \(customerAccessToken)"]
)
playerViewController.player = player
player.play()
```



策略模板由后端选择。不要在应用包中放入策略、Manifest URL、Site Key、Access Key 或长期有效的 Token。使用真实 HLS/CBCS 媒体在实体 iPhone、iPad 和 Apple TV 上测试，并验证 HDMI 和 AirPlay 的策略判断。







## 一个软件包，三种集成方式[#](#one-package-three-integration-choices)



可使用面向 iOS/iPadOS 的 Universal Player、面向 tvOS 的 Universal Player，或上述原生 AVPlayer 集成。它们使用相同的 DrmXFairPlay 软件包和客户播放会话接口。宿主应用负责用户认证，租户凭据保留在后端。



在线播放器支持播放列表、随机与循环播放、可取消的自动播放下一项、续播进度、跳转、倍速、画质偏好、音轨与字幕选择、字幕大小、书签、可选章节和文字稿、A–B 循环、睡眠定时器及全屏。界面适配触摸屏和 Apple TV 遥控器。



```
let playlist = try DrmXPlaylist(items: [
    DrmXPlaylistItem(contentId: "lesson-1", title: "Getting started"),
    DrmXPlaylistItem(contentId: "lesson-2", title: "Next lesson")
])
let model = DrmXUniversalPlayer(
    endpoint: URL(string: "https://customer.example/api/drmx/playback-session")!,
    playlist: playlist,
    storageNamespace: "your-tenant-and-viewer"
) {
    ["Authorization": "Bearer \(customerAccessToken)"]
}
// Retain the model with @StateObject or an owning coordinator.
DrmXUniversalPlayerView(model: model)
// Stop when the owning screen is actually dismissed.
model.stop()
```



画质设置仅表达偏好的最高画质，且不得超出会话授权上限。AVPlayer 会根据可用带宽自适应调整；FairPlay 许可证和输出限制始终有效。播放位置和书签按客户及用户命名空间保存，不存储播放凭据。



当前开发版在视频区域内提供上一项、播放/暂停、下一项、CC、设置和全屏控件。播放期间两秒后自动隐藏，触摸或遥控器操作时重新显示。随机播放、循环和 VOD 进度按指定的客户及用户命名空间保存，下载后播放也适用。关闭随机播放和循环时，队列在最后一个视频结束后停止。



### iPhone 和 iPad 上受保护的下载



向 `DrmXUniversalPlayer` 传入已认证的 `offlineEndpoint`，即可启用下载及已下载视频模式。iOS 使用 AVAssetDownloadURLSession 保存本地 HLS 内容包，并通过 AVContentKeySession 管理绑定到设备的持久 FairPlay 密钥。它只保存不透明的原生密钥和本地元数据，不保存 DRM License Tokens 或明文密钥。下载内容按客户和用户命名空间隔离。离线队列仅包含已完成下载的目录项，并共用保存的进度、随机播放和循环设置。许可证续期需要重新获得在线授权；删除操作只移除选中的下载。



PHP 示例支持 `fairplay`/`hls`/`ios` 持久许可证请求。为每个内容项配置可信的 `hlsManifestUrl`；证书路径使用新签发 Token 中的有效部署。FairPlay 负责执行过期限制。离线播放只能使用已下载的画质及已缓存的语言轨道。tvOS 使用在线播放器。



### 截图与录屏行为验证



可在 iPad 和 Apple TV 模拟器中检查布局、播放列表、设置及遥控导航。这些模拟器不支持 FairPlay 播放；SDK 会报告此限制并释放并发播放名额，不会创建不受支持的原生密钥会话。模拟器界面测试不能证明加密播放、离线下载或实体设备验收已通过。



当 iOS 检测到正在录屏或镜像输出时，播放器会暂停音视频，并遮挡非活动场景。系统在截图完成后才发送通知，因此无法修改已经保存的截图。较早的示例曾在截图中保留视频画面。安装采用原生 AVPlayerViewController 展示的扩展播放器后，用户在开发用 iPhone 上重新测试了 WayMaker 截图，并在 Photos 中确认视频区域为黑色。发布前仍需分别验证其他播放状态、设备、录屏、AirPlay 和输出策略变更。

<!-- Canonical: https://docs.drm-x.com/zh-Hans/sdk/apple -->
<!-- Language: zh-Hans -->
