共用方式為


如何產生 PlayReady 標頭

封裝工具必須在加密的內容中包含 PlayReady 標頭。

如需 PlayReady 標頭和 PlayReady 物件的詳細描述,請參閱 PlayReady 標頭規格

PlayReady 標頭包含現正播放的內容相關資訊,包括金鑰識別碼 (KID) 識別用來加密資料的金鑰、PlayReady 授權伺服器的預設授權取得 URL,以及您想要包含的任何自訂資料。 用來加密內容的金鑰和 KID 必須與 PlayReady 授權伺服器共用,該伺服器會發行該特定內容的授權,通常是透過金鑰管理系統 (KMS) 。

注意

Microsoft 不提供具有 PlayReady 的金鑰管理系統。

下列 XML 程式碼提供 PlayReady 標頭的範例,此標頭可能插入分段 MP4 檔案的標頭中,通常是隨選內容。 它包含 KID 清單, (用戶端解密內容所需的內容加密金鑰識別碼) 。 這是針對隨選檔案或資料流程發出這些 KID 訊號最常見的方式。

<WRMHEADER xmlns="http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader" version="4.3.0.0">
  <DATA>
    <PROTECTINFO>
      <KIDS>
        <KID ALGID="AESCTR" VALUE="PV1LM/VEVk+kEOB8qqcWDg=="></KID>
        <KID ALGID="AESCTR" VALUE="tuhDoKUN7EyxDPtMRNmhyA=="></KID>
      </KIDS>
    </PROTECTINFO>
    <LA_URL>http://rm.contoso.com/rightsmanager.asmx</LA_URL>
    <DS_ID>AH+03juKbUGbHl1V/QIwRA==</DS_ID>
  </DATA>
</WRMHEADER>

下列 XML 程式碼提供 Live Linear 內容的 PlayReady 標頭範例。 它不包含任何 KID,因為內容加密金鑰 (及其相關聯的 KID) 偶爾會變更 (,例如,非常頻繁或位於程式界限,或每小時或每天) 。 用於內容資料流程的 KID 會在區段標頭中發出訊號,而且不需要將它們包含在資料流程最上層 PlayReady 標頭中。 DECRYPTORSETUP 屬性設定為 ONDEMAND,這表示 PlayReady 標頭和解密程式會視需要設定,這表示當用戶端實際需要開始解密區段時,用戶端將可以存取區段標頭中的另一個 PlayReady 標頭,以找出涉及哪些功能。

注意

DECRYPTORSETUP = ONDEMAND 不表示內容會隨選提供,實際上相反。

<WRMHEADER version="4.2.0.0" xmlns="http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader">
  <DATA>
    <DECRYPTORSETUP>ONDEMAND</DECRYPTORSETUP>
  </DATA>
</WRMHEADER>

有多種方式可在您的封裝工具中建立 PlayReady 標頭產生器。 下列各節一般說明如何產生 PlayReady 標頭。

方法 1 - 根據 PlayReady 標頭規格建置您自己的程式碼

PlayReady 物件和標頭規格是公用的,因此在產生 PlayReady 物件和 PlayReady 標頭的服務中撰寫程式碼,以便封裝內容,並相當簡單。

PlayReady 標頭產生器必須具有輸入參數,例如:

  • 隨選內容或即時線性內容。
  • 用於保護整個資產的 KID 或清單。
  • (AESCTR 或 AESCBC) 使用的加密類型。
  • Defaut LA URL - 即將在封裝時發出授權之 PlayReady 授權伺服器的預設 URL。
  • 如果服務使用網域,則為預設網域服務識別碼。

您現在可以建立 PlayReady 物件及其相關聯的 PlayReady 標頭。 下列程式碼範例示範如何建立 PlayReady 物件,其中包含用於隨選內容的 PlayReady 標頭。

// This function gets values from the key management system and your specified encryption mode
// (and optionally the domainID), creates a PlayReady Header, adds the header to a 
// PlayReady Object, and stores them in a file in UTF-16 little endian format

void buildRMObject(string KeyID1, string KeyID2, string encryptMode, string domainID)
{
	// The string parameters include the following:
	// KeyID1, KeyID2 - The key identifiers - these values are returned from the key management system or
	//                                        the KeySeed mechanism
	// encryptMode - the encryption mode used to encrypt content, can be AESCTR or AESCBC
	// domainID - the optional domain service identifier (only used for domains)

	string xmlString = "<WRMHEADER xmlns=\"http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader\" version=\"4.3.0.0\"><DATA><PROTECTINFO><KIDS><KID ALGID=\"";
	xmlString.append(encryptMode);
	xmlString.append("\" VALUE=\"");
	xmlString.append(KeyID1);
	xmlString.append("\"></KID><KID ALGID=\"");
	xmlString.append(encryptMode);
	xmlString.append("\" VALUE=\"");
	xmlString.append(KeyID2);
	xmlString.append("\"></KID></KIDS></PROTECTINFO><LA_URL>http://rm.contoso.com/rightsmanager.asmx</LA_URL><DS_ID>");
	xmlString.append(domainID);
	xmlString.append("</DS_ID></DATA></WRMHEADER>");

	// Convert the PlayReady header to UFT-16 format
	wstring_convert<codecvt_utf8_utf16<wchar_t>> convert;
	wstring utf16XML = convert.from_bytes(xmlString);

	// Calculate the length of the PlayReady Header
	int32_t headerLength = (utf16XML.size() * sizeof(wchar_t));
	// Calculate the length of the PlayReady Object
	int32_t objectLength = headerLength + 10;
	// Set the number of PlayReady object records (in this case, 1)
	int16_t recordCount = 1;
	// Set the record type (in this case, a PlayReady Header)
	// If this was an embedded license store, this value would be 3
	int16_t recordType = 1;

	// Write the PlayReady Object and PlayReady Header to a file
	wofstream wofs("C:\\Temp\\PRObject.txt", ios::binary);
	wofs.imbue(locale(wofs.getloc(),
			  new codecvt_utf16<wchar_t, 0x10ffff, little_endian>));
	wofs.write(reinterpret_cast<const wchar_t *>(&objectLength), 2);
	wofs.write(reinterpret_cast<const wchar_t *>(&recordCount), 1);
	wofs.write(reinterpret_cast<const wchar_t *>(&recordType), 1);
	wofs.write(reinterpret_cast<const wchar_t *>(&headerLength), 1);
	wofs <<  utf16XML;
}

方法 2 - 使用 PlayReady 伺服器 API

如果您是 PlayReady Server SDK 授權者,伺服器 SDK 會包含可用來建構 PlayReady Header 的 PlayReadyHeader 類別。 其中包含您可以使用的方法,以及您可以填入 PlayReady 標頭所需資訊的屬性。

PlayReadyHeader類別會在您透過 PlayReady Server SDK 授權收到的 PlayReady 檔中詳細說明。 PlayReady Server SDK 也包含範例封裝工具 (AESPackaging) ,示範如何建立 PlayReady 標頭。

如同方法 1,您需要金鑰管理系統所產生的 KeyID () 、加密類型 (AESCTR 或 AESCBC) 、PlayReady 授權伺服器的 URL,以及選擇性的網域服務識別碼。

方法 3 - 使用Windows應用程式

開始之前需要的專案。

  1. 您必須擁有金鑰管理系統所產生的 KeyID () 。
  2. 您必須知道 AESCTR 或 AESCBC) (加密類型。
  3. 使用PlayReadyContentHeader 類別Windows 10 PlayReadyContentHeader 類別,在 PlayReady 物件內建立 PlayReady 標頭

如同先前的方法,您需要金鑰管理系統所產生的 KeyID () 、加密類型 (AESCTR 或 AESCBC) 、PlayReady 授權伺服器的 URL,以及選擇性的網域服務識別碼。