# Apple FairPlay DRM
ByteArk Player SDK สำหรับ iOS รองรับ Apple FairPlay Streaming (FPS) (opens new window) ซึ่งช่วยให้สามารถเล่นเนื้อหาที่เข้ารหัสได้
ในการเปิดใช้งานฟีเจอร์นี้ คุณต้องทำการ implement protocol ByteArkPlayerDrmDataSource
และเมื่อ SDK ตรวจพบว่าเนื้อหามีการเข้ารหัสด้วย FairPlay ระบบจะร้องขอให้แอปของคุณจัดเตรียมข้อมูลและคีย์ที่จำเป็นสำหรับการถอดรหัสเนื้อหานั้น
ByteArkPlayerDrmDataSource Protocol
// A dataSource requests the necessary data to decrypt Apple FairPlay Drm content
@objc public protocol ByteArkPlayerDrmDataSource: AnyObject {
/// Called when player needs to decrypt the current protected content and requires a content identifier (content id) from the application to start the decryption process
///
/// - Parameters:
/// - url: The url of the resource being loaded.
/// - completionHandler: The handler block used to provide the content identifier to the ByteArk Player.
///
func contentIdentifier(for url: URL, completionHandler handler: @escaping (_ contentIdentifier: Data?) -> Void)
/// Called when player needs to decrypt the current protected content and requires an application certificate from the application to start the decryption process
///
/// - Parameters:
/// - url: The url of the resource being loaded.
/// - completionHandler: The handler block used to provide the application certificate to the ByteArk Player, the Application Certificate data you receive after registering an FPS playback app.
///
func applicationCertificate(for url: URL, completionHandler handler: @escaping (_ certificate: Data?) -> Void)
/// Called when player needs to decrypt the current protected content and requires a content key from the application to start the decryption process
///
/// - Parameters:
/// - spcData: The SPC (Server Playback Context) message from the operating system which must be sent to the Key Server in order to obtain the CKC (Content Key Context) message.
/// - completionHandler: The completion block used to provide CKC (Content Key Context) that received from the Server Response to the ByteArk Player.
///
func contentKey(with spcData: Data, completionHandler handler: @escaping (_ ckcData: Data?) -> Void)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Implementation
WARNING
การถอดรหัส FairPlay สามารถใช้งานได้เฉพาะบนอุปกรณ์จริงเท่านั้น และจะไม่ทำงานบนตัวจำลอง (simulator)
- Implement the
contentIdentifier(for url: URL, completionHandler handler: @escaping (_ contentIdentifier: Data?) -> Void)
delegate method in your class
This delegate method requests the identifier for the protected content to be passed through the delegate method's completion block.
func contentIdentifier(for url: URL, completionHandler handler: @escaping (Data?) -> Void) {
// extract content identifier from url
if #available(iOS 16.0, *) {
handler(url.host()?.data(using: .utf8))
} else {
// Fallback on earlier versions
handler(url.host?.data(using: .utf8))
}
}
2
3
4
5
6
7
8
9
- Implement the
applicationCertificate(for url: URL, completionHandler handler: @escaping (_ certificate: Data?) -> Void)
delegate method in your class
This delegate method requests an Application Certificate binary which must be passed through the completion block.
func applicationCertificate(for url: URL, completionHandler handler: @escaping (Data?) -> Void) {
// request an application certificate from server
var request = URLRequest(url: URL(string: "APPLICATION_CERTIFICATE_URL")!)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
handler(data)
}
task.resume()
}
2
3
4
5
6
7
8
9
10
11
- Implement the
contentKey(with spcData: Data, completionHandler handler: @escaping (_ ckcData: Data?) -> Void)
delegate method in your class
This delegate method provides the SPC (Server Playback Context) message from the operating system which must be sent to the Key Server in order to obtain the CKC (Content Key Context) message. The CKC message must be returned via the completion block under the response parameter.
func contentKey(with spcData: Data, completionHandler handler: @escaping (Data?) -> Void) {
var request = URLRequest(url: URL(string: "APPLE_FAIRPLAY_KEY_SERVER_URL")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
// convert spc to base64 and set json body
let json: [String: Any] = [ "spc": spcData.base64EncodedString() ]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data,
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
let ckcString = json["ckc"] as? String,
let ckcData = Data(base64Encoded: ckcString)
else {
handler(nil)
return
}
handler(ckcData)
}
task.resume()
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- Set your
ByteArkPlayerDrmDataSource
implementation toByteArkPlayerItemBuilder
.
do {
let item = try ByteArkPlayerItemBuilder()
.title("FairPlay Source")
.media(URL(string: "FAIRPLAY_MEDIA_URL")!)
.drmDataSource(YOUR_DRM_DATA_SOURCE_IMPLEMENTATION)
.build()
let config = try ByteArkPlayerConfigBuilder()
.autoplay(true)
.item(item)
.build()
bytearkPlayerViewController.player.configure(with: config)
} catch {
print(error.localizedDescription)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16