加密直播

本頁說明如何加密直播內容。Live Stream API 不會直接建立或管理加密金鑰或授權。如要使用這些功能,請改用第三方數位著作權管理 (DRM) 供應商。為媒體建立加密金鑰後,請使用 Secret Manager 將這些金鑰傳遞至 Live Stream API。

加密設定是在 Channel 設定中指定。開始串流後,Live Stream API 影片管道就會開始加密內容。輸出資訊清單包含在所選媒體播放器中解密內容所需的資訊。

支援的設定

串流通訊協定 容器 DRM 系統 加密配置
HLS TS ClearKey aes128
HLS TS ClearKey sampleAes
HLS TS FairPlay sampleAes
HLS fMP4 FairPlay 僅限 mpegCenc cbcs
MPEG-DASH fMP4 ClearKey mpegCenc cenc 或 cbcs
MPEG-DASH fMP4 Widevine mpegCenc cenc 或 cbcs
HLS fMP4 Widevine mpegCenc cenc 或 cbcs
MPEG-DASH fMP4 PlayReady mpegCenc cenc 或 cbcs
HLS fMP4 PlayReady mpegCenc cenc 或 cbcs

將加密金鑰新增至 Secret Manager

開始前,請先使用您選定的第三方 DRM 供應商建立加密金鑰。

使用 Live Stream API 時,您的密碼必須包含下列 JSON 格式的加密金鑰,以及其他必要資訊。

如需各個欄位的說明,請參閱 DRM 協定說明文件。請注意,您需要將蛇形命名法轉換為駝峰式大小寫,才能使用 JSON 格式。

範例 JSON

{
  "encryptionKeys": [
    {
      // Key for FairPlay configuration.
      "keyId": "d569cb35bd0548c7a99d92feb381df13",
      "key": "f1967daca83e81f38d80aa741e7b32c2",
      "iv": "8d80aa741e7b32c2f1967daca83e81f3",
      "keyUri": "skd://d569cb35bd0548c7a99d92feb381df13",
      "matchers": [
        {
          "muxStreams": ["ts_fairplay"]
        }
      ]
    },
    {
      // Key for Widevine configurations.
      "keyId": "44ec248b048c43a6a6ee58a752c6f9f8",
      "key": "f1967daca83e81f38d80aa741e7b32c2",
      "keyUri": "skd://44ec248b048c43a6a6ee58a752c6f9f8",
      "matchers": [
        {
          "muxStreams": [
            "fmp4_widevine_cenc_video",
            "fmp4_widevine_cenc_audio",
            "fmp4_widevine_cbcs_video",
            "fmp4_widevine_cbcs_audio"
          ]
        }
      ]
    },
    {
      // Key for PlayReady configurations.
      "keyId": "8beed229709f480bb6004ec0f33e82d1",
      "key": "ad20cd838f354dcc8a77c443d08ff09f",
      "keyUri": "skd://8beed229709f480bb6004ec0f33e82d1",
      "matchers": [
        {
          "muxStreams": [
            "fmp4_playready_cenc_video",
            "fmp4_playready_cenc_audio",
            "fmp4_playready_cbcs_video",
            "fmp4_playready_cbcs_audio"
          ]
        }
      ]
    },
    {
      // Key for all ClearKey configurations.
      "keyId": "3d9dccb479c64adbb6e514790caa7822",
      "key": "f1967daca83e81f38d80aa741e7b32c2",
      "keyUri": "https://example.com/keys/3d9dccb479c64adbb6e514790caa7822.bin",
      "iv": "8d80aa741e7b32c2f1967daca83e81f3"
      // No `matchers` field. This is the default key to use when none of the keys above match.
    }
  ]
}

如果加密設定 (例如 FairPlay) 需要明確的初始化向量 (IV),但未包含該向量,API 會使用 keyId 的值做為 iv 的值。

如要新增加密金鑰,請執行下列任一操作:

  • 手動新增及設定金鑰。使用上述 JSON 資料,按照「建立密鑰」一文中的步驟,將加密金鑰新增至 Secret Manager。

  • 實作 key publisher,取得所有必要的加密金鑰,並以密鑰版本的形式寫入 Secret Manager。請參閱以 Cloud Run functions 執行的範例實作

接著,請按照下列步驟設定加密金鑰:

  1. 設定密鑰的 IAM 權限,讓 Live Stream API 可以存取密鑰內容。如要這麼做,請將 secretmanager.secretAccessor 角色授予 service-PROJECT_NUMBER@gcp-sa-livestream.iam.gserviceaccount.com 服務帳戶 (這與服務帳戶存取 Cloud Storage 值區的方式類似)。
  2. 找出您建立的密鑰版本資源名稱 (例如 projects/PROJECT_NUMBER/secrets/SECRET_ID/versions/VERSION_ID)。設定管道時需要這個名稱。

設定管道

加密設定是使用 Channel 層級的 encryptions 陣列中的物件指定。系統會為每種不同的設定指派專屬 ID (id)。每個 muxStream 都會使用 ID 指出要使用的加密設定,或省略該欄位以保持未加密狀態。

JSON 格式

{
  // other channel settings …
  "encryptions": [
    {
      // Identifier for this encryption configuration, to be specified in muxStream(s).
      "id": string,
      // Configuration for secrets stored in Google Secret Manager.
      "secretManagerKeySource": {
        // The name of the Secret Version containing the encryption key.
        // `projects/{project}/secrets/{secret_id}/versions/{version_number}`
        // Using {version_number} of `latest` is not supported.
        "secretVersion": string
      },
      // DRM system(s) that will be used. At least one must be specified. If a DRM system
      // is omitted, it will be considered disabled.
      "drmSystems": {
        // Widevine configuration.
        "widevine": {},
        // FairPlay configuration.
        "fairplay": {},
        // PlayReady configuration.
        "playready": {},
        // ClearKey configuration.
        "clearkey": {}
      },
      // Union field encryption_mode can be only one of the following:
      // Configuration for HLS AES-128 encryption.
      "aes128": {},
      // Configuration for HLS SAMPLE-AES encryption.
      "sampleAes": {},
      // Configuration for MPEG-DASH Common Encryption (MPEG-CENC).
      "mpegCenc": {
        // Specify the encryption scheme. Supported schemes:
        // - `cenc` - AES-CTR subsample
        // - `cbcs`- AES-CBC subsample pattern
        "scheme": string
      }
      // End of list of possible types for union field encryption_mode.
    }
    // Any other encryption configurations.
  ],
  "muxStreams": [
    {
      // Unique identifier for the muxStream.
      "key": string,
      // Identifier of the encryption configuration for the muxStream.
      "encryptionId": string
      // … other muxStream settings.
    }
    // Other muxStreams.
  ],

  // Other channel settings.
}

範例 (ClearKey)

以下範例會在 HLS 資訊清單中設定 AES-128 和 SAMPLE-AES muxStreams,並在 DASH 資訊清單中設定 MPEG-CENC muxStreams (cenc 和 cbcs):

"elementaryStreams": [
  {
    "key": "es_video",
    "videoStream": {
      "h264": {
        "profile": "main",
        "heightPixels": 600,
        "widthPixels": 800,
        "bitrateBps": 1000000,
        "frameRate": 60,
      },
    },
  },
  {
    "key": "es_audio",
    "audioStream": {
      "codec": "aac",
      "channelCount": 2,
      "bitrateBps": 160000
    }
  }
],
"encryptions": [
  {
    "id": "aes-128",
    "secretManagerKeySource": {
      "secretVersion": "projects/12345/secrets/key-1/versions/1"
    },
    "drmSystems": {"clearkey": {}},
    "aes128": {}
  },
  {
    "id": "sample-aes",
    "secretManagerKeySource": {
      "secretVersion": "projects/12345/secrets/key-1/versions/1"
    },
    "drmSystems": {"clearkey": {}},
    "sampleAes": {}
  },
  {
    "id": "cenc",
    "secretManagerKeySource": {
      "secretVersion": "projects/12345/secrets/key-1/versions/1"
    },
    "drmSystems": {"clearkey": {}},
    "mpegCenc": {
      "scheme": "cenc"
    }
  },
  {
    "id": "cbcs",
    "secretManagerKeySource": {
      "secretVersion": "projects/12345/secrets/key-1/versions/1"
    },
    "drmSystems": {"clearkey": {}},
    "mpegCenc": {
      "scheme": "cbcs"
    }
  }
],
"muxStreams": [
  {
    "key": "ts_aes128",
    "container": "ts",
    "elementaryStreams": ["es_video", "es_audio"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "aes-128"
  },
  {
    "key": "ts_sampleaes",
    "container": "ts",
    "elementaryStreams": ["es_video", "es_audio"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "sample-aes"
  },
  {
    "key": "fmp4_cenc_video",
    "container": "fmp4",
    "elementaryStreams": ["es_video"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "cenc"
  },
  {
    "key": "fmp4_cenc_audio",
    "container": "fmp4",
    "elementaryStreams": ["es_audio"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "cenc"
  },
  {
    "key": "fmp4_cbcs_video",
    "container": "fmp4",
    "elementaryStreams": ["es_video"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "cbcs"
  },
  {
    "key": "fmp4_cbcs_audio",
    "container": "fmp4",
    "elementaryStreams": ["es_audio"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "cbcs"
  }
],
"manifests": [
  {
    "key": "manifest_aes128_hls",
    "fileName": "manifest_aes128.m3u8",
    "type": "HLS",
    "muxStreams": ["ts_aes128"],
    "maxSegmentCount": 10
  },
  {
    "key": "manifest_sampleaes_hls",
    "fileName": "manifest_sampleaes.m3u8",
    "type": "HLS",
    "muxStreams": ["ts_sampleaes"],
    "maxSegmentCount": 10
  },
  {
    "key": "manifest_cenc_dash",
    "fileName": "manifest_cenc.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_cenc_video", "fmp4_cenc_audio"],
    "maxSegmentCount": 10
  },
  {
    "key": "manifest_cbcs_dash",
    "fileName": "manifest_cbcs.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_cbcs_video", "fmp4_cbcs_audio"],
    "maxSegmentCount": 10
  }
]

範例 (FP/PR/Widevine)

以下範例會設定 FairPlay/SAMPLE-AES、Widevine/MPEG-CENC (cenc 和 cbcs),以及 PlayReady/MPEG-CENC (cenc 和 cbcs) muxStreams。HLS 和 DASH 資訊清單都包含 Widevine 和 PlayReady muxStream。

"elementaryStreams": [
  {
    "key": "es_video",
    "videoStream": {
      "h264": {
        "profile": "main",
        "heightPixels": 600,
        "widthPixels": 800,
        "bitrateBps": 1000000,
        "frameRate": 60,
      },
    },
  },
  {
    "key": "es_audio",
    "audioStream": {
      "codec": "aac",
      "channelCount": 2,
      "bitrateBps": 160000
    }
  }
],
"encryptions": [
  {
    "id": "fairplay",
    "secretManagerKeySource": {
      "secretVersion": "projects/12345/secrets/key-1/versions/1"
    },
    "drmSystems": {"fairplay": {}},
    "sampleAes": {}
  },
  {
    "id": "widevine-cenc",
    "secretManagerKeySource": {
      "secretVersion": "projects/12345/secrets/key-1/versions/1"
    },
    "drmSystems": {"widevine": {}},
    "mpegCenc": {
      "scheme": "cenc"
    }
  },
  {
    "id": "widevine-cbcs",
    "secretManagerKeySource": {
      "secretVersion": "projects/12345/secrets/key-1/versions/1"
    },
    "drmSystems": {"widevine": {}},
    "mpegCenc": {
      "scheme": "cbcs"
    }
  },
  {
    "id": "playready-cenc",
    "secretManagerKeySource": {
      "secretVersion": "projects/12345/secrets/key-1/versions/1"
    },
    "drmSystems": {"playready": {}},
    "mpegCenc": {
      "scheme": "cenc"
    }
  },
  {
    "id": "playready-cbcs",
    "secretManagerKeySource": {
      "secretVersion": "projects/12345/secrets/key-1/versions/1"
    },
    "drmSystems": {"playready": {}},
    "mpegCenc": {
      "scheme": "cbcs"
    }
  }
],
"muxStreams": [
  {
    "key": "ts_fairplay",
    "container": "ts",
    "elementaryStreams": ["es_video", "es_audio"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "fairplay"
  },
  {
    "key": "fmp4_widevine_cenc_video",
    "container": "fmp4",
    "elementaryStreams": ["es_video"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "widevine-cenc"
  },
  {
    "key": "fmp4_widevine_cenc_audio",
    "container": "fmp4",
    "elementaryStreams": ["es_audio"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "widevine-cenc"
  },
  {
    "key": "fmp4_widevine_cbcs_video",
    "container": "fmp4",
    "elementaryStreams": ["es_video"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "widevine-cbcs"
  },
  {
    "key": "fmp4_widevine_cbcs_audio",
    "container": "fmp4",
    "elementaryStreams": ["es_audio"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "widevine-cbcs"
  },
  {
    "key": "fmp4_playready_cenc_video",
    "container": "fmp4",
    "elementaryStreams": ["es_video"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "playready-cenc"
  },
  {
    "key": "fmp4_playready_cenc_audio",
    "container": "fmp4",
    "elementaryStreams": ["es_audio"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "playready-cenc"
  },
  {
    "key": "fmp4_playready_cbcs_video",
    "container": "fmp4",
    "elementaryStreams": ["es_video"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "playready-cbcs"
  },
  {
    "key": "fmp4_playready_cbcs_audio",
    "container": "fmp4",
    "elementaryStreams": ["es_audio"],
    "segmentSettings": {"segmentDuration": "2s"},
    "encryptionId": "playready-cbcs"
  }
],
"manifests": [
  {
    "key": "manifest_fairplay_hls",
    "fileName": "manifest_fairplay.m3u8",
    "type": "HLS",
    "muxStreams": ["ts_fairplay"],
    "maxSegmentCount": 10
  },
  {
    "key": "manifest_widevine_cenc_hls",
    "fileName": "manifest_widevine_cenc.m3u8",
    "type": "HLS",
    "muxStreams": ["fmp4_widevine_cenc_video", "fmp4_widevine_cenc_audio"],
    "maxSegmentCount": 10
  },
  {
    "key": "manifest_widevine_cbcs_hls",
    "fileName": "manifest_widevine_cbcs.m3u8",
    "type": "HLS",
    "muxStreams": ["fmp4_widevine_cbcs_video", "fmp4_widevine_cbcs_audio"],
    "maxSegmentCount": 10
  },
  {
    "key": "manifest_widevine_cenc_dash",
    "fileName": "manifest_widevine_cenc.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_widevine_cenc_video", "fmp4_widevine_cenc_audio"],
    "maxSegmentCount": 10
  },
  {
    "key": "manifest_widevine_cbcs_dash",
    "fileName": "manifest_widevine_cbcs.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_widevine_cbcs_video", "fmp4_widevine_cbcs_audio"],
    "maxSegmentCount": 10
  },
  {
    "key": "manifest_playready_cenc_hls",
    "fileName": "manifest_playready_cenc.m3u8",
    "type": "HLS",
    "muxStreams": ["fmp4_playready_cenc_video", "fmp4_playready_cenc_audio"],
    "maxSegmentCount": 10
  },
  {
    "key": "manifest_playready_cbcs_hls",
    "fileName": "manifest_playready_cbcs.m3u8",
    "type": "HLS",
    "muxStreams": ["fmp4_playready_cbcs_video", "fmp4_playready_cbcs_audio"],
    "maxSegmentCount": 10
  },
  {
    "key": "manifest_playready_cenc_dash",
    "fileName": "manifest_playready_cenc.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_playready_cenc_video", "fmp4_playready_cenc_audio"],
    "maxSegmentCount": 10
  },
  {
    "key": "manifest_playready_cbcs_dash",
    "fileName": "manifest_playready_cbcs.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_playready_cbcs_video", "fmp4_playready_cbcs_audio"],
    "maxSegmentCount": 10
  }
]

確定要使用的 JSON 設定後,請建立頻道

開始串流

建立頻道後,請啟動頻道傳送輸入串流

頻道啟動時,Live Stream API 會從 Secret Manager 擷取 secretVersion 識別的加密金鑰。如果 Live Stream API 無法擷取金鑰,或金鑰格式無法辨識,頻道狀態會變成 STREAMING_ERROR。如果成功擷取金鑰,管道狀態會照常變成 AWAITING_INPUT

開始串流後,Live Stream API 會根據建立時提供的設定,開始加密輸出內容。

監控輸出內容

加密輸出串流包含經過修改的資訊清單,其中含有解密內容以供播放所需的資訊。

資訊清單範例

下列資訊清單會顯示解密相關聯內容所需的資訊。

HTTP 即時串流 AES-128/ClearKey

#EXTM3U
#EXT-X-VERSION:7
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-DISCONTINUITY-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="https://example.com/keys/3d9dccb479c64adbb6e514790caa7822.bin",IV=0x8d80aa741e7b32c2f1967daca83e81f3
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:22.870Z
#EXTINF:2.576778
segment-0000000000.ts
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:25.447Z
#EXTINF:2.000000
segment-0000000001.ts
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:27.447Z
#EXTINF:2.000000
segment-0000000002.ts
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:29.447Z
#EXTINF:2.000000
segment-0000000003.ts

HLS SAMPLE-AES/FairPlay

#EXTM3U
#EXT-X-VERSION:7
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-DISCONTINUITY-SEQUENCE:0
#EXT-X-KEY:METHOD=SAMPLE-AES,URI="skd://d569cb35bd0548c7a99d92feb381df13",KEYFORMAT="com.apple.streamingkeydelivery",KEYFORMATVERSIONS="1"
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:22.870Z
#EXTINF:2.576778
segment-0000000000.ts
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:25.447Z
#EXTINF:2.000000
segment-0000000001.ts
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:27.447Z
#EXTINF:2.000000
segment-0000000002.ts
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:29.447Z
#EXTINF:2.000000
segment-0000000003.ts

HLS MPEG-CENC/Widevine

#EXTM3U
#EXT-X-VERSION:7
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-DISCONTINUITY-SEQUENCE:0
#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,URI="data:text/plain;base64,AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfSEAB3Gcrj/8kFtioyiVbJMh9I49yVmwY=",KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed",KEYFORMATVERSIONS="1"
#EXT-X-MAP:URI="segment-initialization_segment_0000000000.m4s"
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:22.870Z
#EXTINF:2.576778
segment-0000000000.m4s
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:25.447Z
#EXTINF:2.000000
segment-0000000001.m4s
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:27.447Z
#EXTINF:2.000000
segment-0000000002.m4s
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T20:08:29.447Z
#EXTINF:2.000000
segment-0000000003.m4s

DASH MPEG-CENC/Widevine

<AdaptationSet segmentAlignment="true" maxWidth="800" maxHeight="600">
  <Representation mimeType="video/mp4" id="fmp4_widevine_cenc_video" codecs="avc1.4d001f">
    <ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="44ec248b-048c-43a6-a6ee-58a752c6f9f8"/>
    <ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed" value="Widevine">
      <cenc:pssh>AAAAOHBzc2gAAAAA7e+LqXnWSs6jCfc1R0h7QAAABgSEAB3Gcrj/8kFklokiVbJMh9VmwY=</cenc:pssh>
    </ContentProtection>
  </Representation>
</AdaptationSet>
<AdaptationSet segmentAlignment="true" mimeType="audio/mp4" id="1" label="fmp4_widevine_cenc_audio">
  <Representation id="fmp4_widevine_cenc_audio" codecs="mp4a.40.2">
    <ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="44ec248b-048c-43a6-a6ee-58a752c6f9f8"/>
    <ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed" value="Widevine">
      <cenc:pssh>AAAAOHBzc2gAAAAA7e+LqXnWSs6jCfc1R0h7QAAABgSEAB3Gcrj/8kFklokiVbJMh9VmwY=</cenc:pssh>
    </ContentProtection>
  </Representation>
</AdaptationSet>

建議使用以 HLS.js 為基礎的播放器進行 HLS/TS 解密。建議使用以 Shaka Player 為基礎的播放器,解密 DASH/fMP4。

PlayReady「cenc」方案適用於搭載 Microsoft Edge 瀏覽器的 Windows 10 實體電腦、Xbox One (1703 以下版本),以及部分非 Windows 裝置 (例如智慧型電視)。PlayReady「cbcs」方案僅支援 Xbox One 1709 以上版本。詳情請參閱「PlayReady 內容加密模式」。

更新加密金鑰

你可以切換頻道使用新的加密金鑰,不必停止串流或重新啟動頻道。

如要更新金鑰,請先將新金鑰新增至 Secret Manager。新金鑰可以是現有密鑰的新版本,也可以是新密鑰。如果您建立新的密鑰,請務必為 Live Stream API 指派該密鑰的 secretmanager.secretAccessor 角色。

將新金鑰加入 Secret Manager 後,請建立更新加密事件。系統會更新要求主體中指定的任何加密設定。未指定的設定會維持不變。