Mengenkripsi live stream

Halaman ini menjelaskan cara mengenkripsi konten live stream. Live Stream API tidak membuat atau mengelola kunci atau lisensi enkripsi secara langsung. Sebagai gantinya, Anda harus menggunakan penyedia Manajemen Hak Digital (DRM) pihak ketiga untuk fitur-fitur ini. Setelah kunci enkripsi dibuat untuk media Anda, teruskan kunci tersebut ke Live Stream API menggunakan Secret Manager.

Setelan enkripsi ditentukan di setelan Channel. Setelah streaming dimulai, pipeline video Live Stream API akan mulai mengenkripsi konten Anda. Manifes output menyertakan informasi yang diperlukan untuk mendekripsi konten dalam pemutar media pilihan Anda.

Konfigurasi yang didukung

Protokol streaming Container Sistem DRM Skema enkripsi
HLS TS ClearKey aes128
HLS TS ClearKey sampleAes
HLS TS FairPlay sampleAes
HLS fMP4 FairPlay Khusus mpegCenc cbcs
MPEG-DASH fMP4 ClearKey mpegCenc cenc atau cbcs
MPEG-DASH fMP4 Widevine mpegCenc cenc atau cbcs
HLS fMP4 Widevine mpegCenc cenc atau cbcs
MPEG-DASH fMP4 PlayReady mpegCenc cenc atau cbcs
HLS fMP4 PlayReady mpegCenc cenc atau cbcs

Menambahkan kunci enkripsi ke Secret Manager

Sebelum memulai, buat kunci enkripsi menggunakan penyedia DRM pihak ketiga pilihan Anda.

Live Stream API memerlukan rahasia Anda untuk memuat kunci enkripsi dalam format JSON berikut, beserta informasi lain yang diperlukan.

Lihat dokumentasi protokol DRM untuk deskripsi setiap kolom. Perhatikan bahwa Anda harus mengonversi dari snake case ke camel case untuk format JSON.

Contoh 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.
    }
  ]
}

Jika konfigurasi enkripsi Anda (misalnya, FairPlay) memerlukan vektor inisialisasi eksplisit (IV) tetapi tidak disertakan, API akan menggunakan nilai keyId untuk nilai iv.

Untuk menambahkan kunci enkripsi, lakukan salah satu langkah berikut:

  • Menambahkan dan mengonfigurasi kunci secara manual. Gunakan data JSON sebelumnya, tambahkan kunci enkripsi Anda ke Secret Manager dengan mengikuti langkah-langkah di bagian Membuat secret.

  • Implementasikan key publisher yang mendapatkan kunci enkripsi yang diperlukan dan menulisnya ke Secret Manager sebagai versi rahasia. Lihat contoh implementasi yang dijalankan sebagai Cloud Functions.

Kemudian, lakukan hal berikut untuk mengonfigurasi kunci enkripsi Anda:

  1. Konfigurasikan izin IAM pada secret Anda agar Live Stream API dapat mengakses konten secret. Untuk melakukannya, berikan peran secretmanager.secretAccessor ke akun layanan service-PROJECT_NUMBER@gcp-sa-livestream.iam.gserviceaccount.com (ini mirip dengan cara akun layanan memiliki akses ke bucket Cloud Storage Anda).
  2. Temukan nama resource versi rahasia yang Anda buat (misalnya, projects/PROJECT_NUMBER/secrets/SECRET_ID/versions/VERSION_ID). Anda memerlukan nama ini untuk mengonfigurasi saluran.

Mengonfigurasi saluran

Setelan enkripsi ditentukan menggunakan objek dalam array encryptions di level Channel. ID unik (id) ditetapkan untuk setiap konfigurasi yang berbeda. Setiap muxStream menggunakan ID untuk menunjukkan konfigurasi enkripsi yang akan digunakan, atau menghilangkan kolom tersebut agar tetap tidak dienkripsi.

Format 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.
}

Contoh (ClearKey)

Contoh berikut mengonfigurasi muxStream AES-128 dan Sample-AES dalam manifes HLS, dan muxStream MPEG-CENC (cenc dan cbcs) dalam manifes DASH:

"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": [
  {
    "fileName": "manifest_aes128.m3u8",
    "type": "HLS",
    "muxStreams": ["ts_aes128"],
    "maxSegmentCount": 10
  },
  {
    "fileName": "manifest_sampleaes.m3u8",
    "type": "HLS",
    "muxStreams": ["ts_sampleaes"],
    "maxSegmentCount": 10
  },
  {
    "fileName": "manifest_cenc.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_cenc_video", "fmp4_cenc_audio"],
    "maxSegmentCount": 10
  },
  {
    "fileName": "manifest_cbcs.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_cbcs_video", "fmp4_cbcs_audio"],
    "maxSegmentCount": 10
  }
]

Contoh (FP/PR/Widevine)

Contoh berikut mengonfigurasi muxStreams FairPlay/Sample-AES, Widevine/MPEG-CENC (cenc dan cbcs), dan PlayReady/MPEG-CENC (cenc dan cbcs). MuxStream Widevine dan PlayReady disertakan dalam manifes HLS dan DASH.

"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": [
  {
    "fileName": "manifest_fairplay.m3u8",
    "type": "HLS",
    "muxStreams": ["ts_fairplay"],
    "maxSegmentCount": 10
  },
  {
    "fileName": "manifest_widevine_cenc.m3u8",
    "type": "HLS",
    "muxStreams": ["fmp4_widevine_cenc_video", "fmp4_widevine_cenc_audio"],
    "maxSegmentCount": 10
  },
  {
    "fileName": "manifest_widevine_cbcs.m3u8",
    "type": "HLS",
    "muxStreams": ["fmp4_widevine_cbcs_video", "fmp4_widevine_cbcs_audio"],
    "maxSegmentCount": 10
  },
  {
    "fileName": "manifest_widevine_cenc.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_widevine_cenc_video", "fmp4_widevine_cenc_audio"],
    "maxSegmentCount": 10
  },
  {
    "fileName": "manifest_widevine_cbcs.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_widevine_cbcs_video", "fmp4_widevine_cbcs_audio"],
    "maxSegmentCount": 10
  },
  {
    "fileName": "manifest_playready_cenc.m3u8",
    "type": "HLS",
    "muxStreams": ["fmp4_playready_cenc_video", "fmp4_playready_cenc_audio"],
    "maxSegmentCount": 10
  },
  {
    "fileName": "manifest_playready_cbcs.m3u8",
    "type": "HLS",
    "muxStreams": ["fmp4_playready_cbcs_video", "fmp4_playready_cbcs_audio"],
    "maxSegmentCount": 10
  },
  {
    "fileName": "manifest_playready_cenc.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_playready_cenc_video", "fmp4_playready_cenc_audio"],
    "maxSegmentCount": 10
  },
  {
    "fileName": "manifest_playready_cbcs.mpd",
    "type": "DASH",
    "muxStreams": ["fmp4_playready_cbcs_video", "fmp4_playready_cbcs_audio"],
    "maxSegmentCount": 10
  }
]

Setelah Anda mengetahui konfigurasi JSON yang ingin digunakan, buat saluran seperti biasa.

Mulai streaming

Setelah saluran dibuat, mulai saluran dan kirim aliran input.

Saat saluran dimulai, Live Stream API akan mengambil kunci enkripsi yang diidentifikasi oleh secretVersion dari Secret Manager. Jika Live Stream API tidak dapat mengambil kunci atau kunci dalam format yang tidak dapat dikenali, status saluran menjadi STREAMING_ERROR. Jika kunci berhasil diambil, status saluran menjadi AWAITING_INPUT seperti biasa.

Setelah streaming dimulai, Live Stream API akan mulai mengenkripsi konten output sesuai dengan konfigurasi yang diberikan pada waktu pembuatan.

Memantau output

Streaming output terenkripsi berisi manifes yang dimodifikasi dengan informasi yang diperlukan untuk mendekripsi konten untuk diputar.

Contoh manifes

Manifes berikut menunjukkan informasi yang diperlukan untuk mendekripsi konten terkait.

HLS 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

CONTOH HLS-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>

Pemutar yang didasarkan pada HLS.js direkomendasikan untuk dekripsi HLS/TS. Pemain berdasarkan Shaka Player direkomendasikan untuk dekripsi DASH/fMP4.

Skema 'cenc' PlayReady didukung pada perangkat fisik yang menjalankan Windows 10 dengan browser Microsoft Edge, Xbox One (versi 1703 atau yang lebih lama), dan beberapa perangkat non-Windows (misalnya, smart TV). Skema 'cbcs' PlayReady hanya didukung di Xbox One versi 1709 atau yang lebih baru. Lihat Mode Enkripsi Konten PlayReady untuk mengetahui informasi selengkapnya.

Perbarui kunci enkripsi

Untuk mengalihkan saluran ke kunci enkripsi baru, lakukan tindakan berikut:

  1. Menghentikan channel.
  2. Perbarui setelan enkripsi di saluran.
  3. Memulai channel.