Crittografare un live streaming

Questa pagina spiega come criptare i contenuti dei live streaming. La L'API Live Stream non crea né gestisce le chiavi di crittografia o le licenze . Per queste funzionalità, devi invece utilizzare un fornitore di DRM (Digital Rights Management) di terze parti. Dopo aver creato le chiavi di crittografia per i contenuti multimediali, trasmettile all'API Live Stream utilizzando Secret Manager.

Le impostazioni di crittografia sono specificate nelle impostazioni di Channel. Una volta avviato lo streaming, la pipeline video dell'API Live Stream inizia a criptare i contenuti. Il manifest di output include informazioni necessaria per decriptare i contenuti all'interno del media player di tua scelta.

Configurazioni supportate

Protocollo di streaming Container Sistema DRM Schema di crittografia
HLS TS ClearKey aes128
HLS TS ClearKey sampleAes
HLS TS FairPlay sampleAes
HLS fMP4 FairPlay Solo mpegCenc cbcs
MPEG-DASH fMP4 ClearKey mpegCenc cenc o cbcs
MPEG-DASH fMP4 Widevine mpegCenc cenc o cbcs
HLS fMP4 Widevine mpegCenc cenc o cbcs
MPEG-DASH fMP4 PlayReady mpegCenc cenc o cbcs
HLS fMP4 PlayReady mpegCenc cenc o cbcs

Aggiungi la chiave di crittografia a Secret Manager

Prima di iniziare, crea le chiavi di crittografia utilizzando il fornitore DRM di terze parti di tua scelta.

L'API Live Stream richiede che il tuo secret contenga la chiave di crittografia il seguente formato JSON, insieme ad altre informazioni necessarie.

Consulta la documentazione sul protocollo DRM per una descrizione di ciascun campo. Tieni presente che devi convertire da snake case a camel case per il formato JSON.

Esempio di struttura 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.
    }
  ]
}

Se la configurazione della crittografia (ad esempio, FairPlay) richiede un'esplicita vettore di inizializzazione (IV), ma non è incluso, l'API utilizzerà il valore keyId per il valore iv.

Per aggiungere la chiave di crittografia, esegui una delle seguenti operazioni:

  • Aggiungi e configura manualmente le chiavi. Usa i dati JSON precedenti, aggiungi la tua chiave di crittografia a Secret Manager seguendo i passaggi su Crea un secret.

  • Implementa un key publisher che ottiene le chiavi di crittografia necessarie e le scrive in Secret Manager come versioni del secret. Guarda un esempio che viene eseguita come una funzione di Cloud Run.

Poi, procedi nel seguente modo per configurare la chiave di crittografia:

  1. Configura le autorizzazioni IAM sul tuo secret in modo che l'API Live Stream possono accedere ai contenuti del secret. A questo scopo, concedi la ruolo secretmanager.secretAccessor alla service-PROJECT_NUMBER@gcp-sa-livestream.iam.gserviceaccount.com account di servizio (è simile a come l'account di servizio ha accesso al tuo nei bucket Cloud Storage).
  2. Trova il nome risorsa della versione del secret che hai creato (ad esempio, projects/PROJECT_NUMBER/secrets/SECRET_ID/versions/VERSION_ID). Questo nome è necessario per configurare il canale.

Configurare il canale

Le impostazioni di crittografia vengono specificate utilizzando gli oggetti nel encryptions a livello di Channel. Un identificatore univoco (id) viene assegnato a ogni configurazione diversa. Ogni muxStream utilizza un per indicare la configurazione di crittografia da utilizzare oppure che non crittografare.

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

Esempio (ClearKey)

L'esempio seguente configura i muxStream AES-128 e sample-AES in HLS e muxStream MPEG-CENC (cenc e cbcs) nei manifest 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": [
  {
    "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
  }
]

Esempio (FP/PR/Widevine)

L'esempio seguente configura muxStreams FairPlay/SAMPLE-AES, Widevine/MPEG-CENC (cenc e cbcs) e PlayReady/MPEG-CENC (cenc e cbcs). I MuxStream Widevine e PlayReady sono inclusi sia in HLS che in DASH e i file manifest.

"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
  }
]

Una volta che conosci la configurazione JSON che vuoi utilizzare, Crea un canale come normale.

Avvia streaming

Una volta creato il canale, avvialo e invia lo stream di input.

Quando il canale viene avviato, l'API Live Stream recupera la chiave di crittografia identificata da secretVersion da Secret Manager. Se L'API Live Stream non è in grado di recuperare la chiave oppure la chiave si trova in un non riconoscibile, lo stato del canale diventa STREAMING_ERROR. Se la chiave viene recuperato correttamente, lo stato del canale diventa AWAITING_INPUT come di consueto.

Una volta avviato lo streaming, l'API Live Stream inizia a criptare l'output contenuti in base alla configurazione fornita al momento della creazione.

Monitorare l'output

I flussi di output criptati contengono manifest modificati con le informazioni necessarie per decriptare i contenuti per la riproduzione.

Esempi di file manifest

I seguenti manifest mostrano le informazioni necessarie per decriptare i file associati contenuti.

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

ESEMPIO 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

MPEG-CENC/Widevine HLS

#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>

Per la decrittografia HLS/TS sono consigliati i lettori basati su HLS.js. Per la decrittografia DASH/fMP4 sono consigliati i lettori basati su Shaka Player.

Lo schema "cenc" di PlayReady è supportato su macchine fisiche con Windows 10 con il browser Microsoft Edge, Xbox One (versione 1703 o precedente) e alcuni dispositivi non Windows (ad esempio le smart TV). Lo schema "cbcs" di PlayReady è supportato solo su Xbox One versione 1709 o successive. Per ulteriori informazioni, consulta Modalità di crittografia dei contenuti PlayReady.

Aggiorna la chiave di crittografia

Per passare un canale a una nuova chiave di crittografia:

  1. Interrompere il canale.
  2. Aggiorna le impostazioni di crittografia sul canale.
  3. Avvia il canale.