PlayReady 加密媒體延伸模組
本節說明如何修改 PlayReady Web 應用程式,以支援從舊版 Windows 8.1 到 Windows 10 版本所做的變更。
在 Internet Explorer 中使用 PlayReady 媒體元素可讓開發人員建立 Web 應用程式,以在強制執行內容提供者定義的存取規則的同時,將 PlayReady 內容提供給使用者。 本節說明如何使用 HTML5 和 JavaScript,將 PlayReady 媒體元素新增至現有的 Web 應用程式。
PlayReady 加密媒體延伸模組的新增功能
本節提供對 PlayReady 加密媒體延伸模組 (EME) 所做的變更清單,以在 Windows 10 上啟用 PlayReady 內容保護。
以下列表介紹了適用於 Windows 10 的 PlayReady 加密媒體延伸模組的新功能和變更:
已新增硬體數位版權管理 (DRM)。
硬體型內容保護支援可在多個裝置平台上安全地播放高畫質 (HD) 和超高畫質 (UHD) 內容。 金鑰資料 (包括私鑰、內容金鑰,以及用來衍生或解除鎖定上述金鑰的任何其他金鑰資料),以及解密壓縮和未壓縮的視訊範例會利用硬體安全性來保護。
提供主動取得非持續性授權。
提供在一則訊息中取得多個授權。
您可以在 Windows 8.1 中使用具有多個金鑰識別碼 (KeyID) 的 PlayReady 物件,或使用具有多個 KeyID 的內容解密模型資料 (CDMData)。
注意
在 Windows 10 中,CDMData 中的 <KeyID> 底下支援多個金鑰識別碼。
已新增即時到期支援,或有限的持續時間授權 (LDL)。
提供在授權上設定即時到期的能力。
已新增 HDCP 類型 1 (2.2 版) 原則支援。
Miracast 現在隱含為輸出。
已新增安全停止。
安全停止為 PlayReady 裝置提供了一種方法,可以自信地針對媒體串流服務判斷,任何指定內容的媒體播放已停止。
已新增音訊和視訊授權分隔。
個別曲目可防止視訊解碼為音訊;啟用更健全的內容保護。 新興標準要求音訊和視訊曲目使用單獨的金鑰。
已新增 MaxResDecode。
新增此功能是為了將內容播放限制為最大解析度,即使擁有功能更強大的金鑰 (但不是授權) 也是如此。 它支援使用單一金鑰對多個串流大小進行編碼的情況。
PlayReady 中的加密媒體延伸模組支援
本節說明 PlayReady 支援的 W3C 加密媒體延伸模組版本。
PlayReady for Web Apps 目前繫結至 2013 年 5 月 10 日 W3C 加密媒體延伸模組 (EME) 草稿。 此支援將會在未來的 Windows 版本中變更為更新的 EME 規格。
使用硬體DRM
本節說明 Web 應用程式如何使用 PlayReady 硬體 DRM,以及如何停用受保護內容不支援的硬體 DRM。
若要使用 PlayReady 硬體 DRM,您的 JavaScript Web 應用程式應該使用 isTypeSupported 方法,並搭配金鑰系統識別碼 com.microsoft.playready.hardware
,從瀏覽器查詢 PlayReady 硬體 DRM 支援。
有時,硬體 DRM 不支援某些內容。 硬體 DRM 永遠不支援雞尾酒內容;如果您想播放雞尾酒內容,則必須選擇退出硬體 DRM。 某些硬體 DRM 將支援 HEVC,有些則不支援;如果您想要播放 HEVC 內容,且硬體 DRM 不支援它,您也可以退出宣告。
注意
若要判斷是否支援 HEVC 內容,請在具現化 com.microsoft.playready
之後,使用 PlayReadyStatics.CheckSupportedHardware 方法。
將安全停止新增至 Web 應用程式
本節說明如何將安全停止新增至 Web 應用程式。
安全停止為 PlayReady 裝置提供了一種方法,可以自信地針對媒體串流服務判斷,任何指定內容的媒體播放已停止。 此功能可確保您的媒體串流服務為指定帳戶的不同裝置上的使用限制提供準確的執行和報告。
傳送安全停止挑戰有兩個主要案例:
- 當媒體簡報因為內容結束而停止,或使用者停止中間某個位置的媒體簡報時。
- 當上一個工作階段意外結束時 (例如,因為系統或應用程式當機)。 應用程式必須在啟動時或關機查詢任何未完成的安全停止工作階段,並將挑戰與任何其他媒體播放分開傳送。
下列程序說明如何為各種案例設定安全停止。
若要為簡報的正常結束設定安全停止:
- 在播放開始之前註冊 onEnded 事件。
- onEnded 事件處理常式必須從視訊/音訊元素物件呼叫
removeAttribute("src")
,將來源設定為 NULL,這會觸發媒體基礎卸除拓撲、終結解密器,並設定停止狀態。 - 您可以在處理常式內啟動安全停止 CDM 工作階段,將安全停止挑戰傳送給伺服器,以通知播放目前已停止,但稍後也可以完成。
若要在使用者離開頁面或關閉索引標籤或瀏覽器時設定安全停止:
- 無需應用程式操作即可記錄停止狀態;它將為您記錄。
若要為自訂頁面控制項或使用者操作 (例如自訂導覽按鈕或在目前簡報完成之前開始新簡報) 設定安全性停止:
- 當發生自訂使用者操作時,應用程式需要將來源設為 NULL,這將觸發媒體基礎拆除拓撲、終結解密器並設定停止狀態。
下列範例示範如何在 Web 應用程式中使用安全停止:
// JavaScript source code
var g_prkey = null;
var g_keySession = null;
var g_fUseSpecificSecureStopSessionID = false;
var g_encodedMeteringCert = 'Base64 encoded of your metering cert (aka publisher cert)';
// Note: g_encodedLASessionId is the CDM session ID of the proactive or reactive license acquisition
// that we want to initiate the secure stop process.
var g_encodedLASessionId = null;
function main()
{
...
g_prkey = new MSMediaKeys("com.microsoft.playready");
...
// add 'onended' event handler to the video element
// Assume 'myvideo' is the ID of the video element
var videoElement = document.getElementById("myvideo");
videoElement.onended = function (e) {
//
// Calling removeAttribute("src") will set the source to null
// which will trigger the MF to tear down the topology, destroy the
// decryptor(s) and set the stop state. This is required in order
// to set the stop state.
//
videoElement.removeAttribute("src");
videoElement.load();
onEndOfStream();
};
}
function onEndOfStream()
{
...
createSecureStopCDMSession();
...
}
function createSecureStopCDMSession()
{
try{
var targetMediaCodec = "video/mp4";
var customData = "my custom data";
var encodedSessionId = g_encodedLASessionId;
if( !g_fUseSpecificSecureStopSessionID )
{
// Use "*" (wildcard) as the session ID to include all secure stop sessions
// TODO: base64 encode "*" and place encoded result to encodedSessionId
}
var int8ArrayCDMdata = formatSecureStopCDMData( encodedSessionId, customData, g_encodedMeteringCert );
var emptyArrayofInitData = new Uint8Array();
g_keySession = g_prkey.createSession(targetMediaCodec, emptyArrayofInitData, int8ArrayCDMdata);
addPlayreadyKeyEventHandler();
} catch( e )
{
// TODO: Handle exception
}
}
function addPlayreadyKeyEventHandler()
{
// add 'keymessage' eventhandler
g_keySession.addEventListener('mskeymessage', function (event) {
// TODO: Get the keyMessage from event.message.buffer which contains the secure stop challenge
// The keyMessage format for the secure stop is similar to LA as below:
//
// <PlayReadyKeyMessage type="SecureStop" >
// <SecureStop version="1.0" >
// <Challenge encoding="base64encoded">
// secure stop challenge
// </Challenge>
// <HttpHeaders>
// <HttpHeader>
// <name>Content-Type</name>
// <value>"content type data"</value>
// </HttpHeader>
// <HttpHeader>
// <name>SOAPAction</name>
// <value>soap action</value>
// </HttpHeader>
// ....
// </HttpHeaders>
// </SecureStop>
// </PlayReadyKeyMessage>
// TODO: send the secure stop challenge to a server that handles the secure stop challenge
// TODO: Receive and response and call event.target.Update() to process the response
});
// add 'keyerror' eventhandler
g_keySession.addEventListener('mskeyerror', function (event) {
var session = event.target;
...
session.close();
});
// add 'keyadded' eventhandler
g_keySession.addEventListener('mskeyadded', function (event) {
var session = event.target;
...
session.close();
});
}
/**
* desc@ formatSecureStopCDMData
* generate playready CDMData
* CDMData is in xml format:
* <PlayReadyCDMData type="SecureStop">
* <SecureStop version="1.0">
* <SessionID>B64 encoded session ID</SessionID>
* <CustomData>B64 encoded custom data</CustomData>
* <ServerCert>B64 encoded server cert</ServerCert>
* </SecureCert>
* </PlayReadyCDMData>
*/
function formatSecureStopCDMData(encodedSessionId, customData, encodedPublisherCert)
{
var encodedCustomData = null;
// TODO: base64 encode the custom data and place the encoded result to encodedCustomData
var CDMDataStr = "<PlayReadyCDMData type=\"SecureStop\">" +
"<SecureStop version=\"1.0\" >" +
"<SessionID>" + encodedSessionId + "</SessionID>" +
"<CustomData>" + encodedCustomData + "</CustomData>" +
"<ServerCert>" + encodedPublisherCert + "</ServerCert>" +
"</SecureStop></PlayReadyCDMData>";
var int8ArrayCDMdata = null
// TODO: Convert CDMDataStr to Uint8 byte array and palce the converted result to int8ArrayCDMdata
return int8ArrayCDMdata;
}
注意
上面範例中的安全停止資料<SessionID>B64 encoded session ID</SessionID>
可以是星號 (*),它是所有記錄的安全停止工作階段的萬用字元。 也就是說,SessionID 標籤可以是特定工作階段,也可以是萬用字元 (*) 選取所有安全停止工作階段。
加密媒體延伸模組的程式設計考慮
本節列出您在為 Windows 10 建立已啟用 PlayReady 的 Web 應用程式時應該考慮的程式設計考慮。
應用程式所建立的 MSMediaKeys 和 MSMediaKeySession 物件必須保持運作,直到您的應用程式關閉為止。 確保這些物件保持運作的其中一種方式是將它們指派為全域變數 (如果宣告為函式內的局部變數,變數就會變成範圍外,並受限於垃圾集合)。 例如,下列範例會將變數 g_msMediaKeys 和 g_mediaKeySession 指派為全域變數,然後指派給函式中的 MSMediaKeys 和 MSMediaKeySession 物件。
var g_msMediaKeys;
var g_mediaKeySession;
function foo() {
...
g_msMediaKeys = new MSMediaKeys("com.microsoft.playready");
...
g_mediaKeySession = g_msMediaKeys.createSession("video/mp4", intiData, null);
g_mediaKeySession.addEventListener(this.KEYMESSAGE_EVENT, function (e)
{
...
downloadPlayReadyKey(url, keyMessage, function (data)
{
g_mediaKeySession.update(data);
});
});
g_mediaKeySession.addEventListener(this.KEYADDED_EVENT, function ()
{
...
g_mediaKeySession.close();
g_mediaKeySession = null;
});
}
如需詳細資訊,請參閱範例應用程式。