Outil de manipulation du fichier manifeste pour les flux de vidéo à la demande

L'API Pod Serving permet d'accéder à des séries d'annonces vidéo à débit adaptatif préparées de manière à pouvoir être assemblées directement dans une playlist de contenus multimédias HLS ou MPEG-DASH visible par l'utilisateur.

Ce guide est axé sur la mise en œuvre d'un serveur de manipulation de fichier manifeste de diffusion de séries d'annonces de base pour les flux de vidéo à la demande.

Recevoir des demandes de fichier manifeste de flux

Votre outil de manipulation du fichier manifeste doit fournir un point de terminaison d'API permettant d'écouter les requêtes de fichier manifeste provenant de l'application cliente du lecteur vidéo. Au minimum, ce point de terminaison doit collecter un ID de flux à partir de l'application du lecteur client. Cet ID de flux permet d'identifier la session de streaming auprès d'Ad Manager dans vos demandes de séries d'annonces.

Vous devez également collecter d'autres informations (par exemple, un ID de contenu) pour identifier le flux de contenu approprié.

Exemple de point de terminaison de requête de fichier manifeste

GET /api/stream_id/{stream_id}/video/{content_id}.{format}
Host: {your_domain}
Paramètres du chemin d'accès
stream_id ID de flux Ad Manager de l'application de lecteur vidéo cliente.
content_id Un identifiant fictif correspondant à la vidéo du contenu dans votre système.
format Paramètre hypothétique correspondant au format du flux. L'une des options suivantes:
mpd Pour les flux MPEG-DASH
m3u8 Pour les flux HLS

Récupérer le flux de contenu

Utilisez l'ID de contenu collecté à partir de la requête de fichier manifeste pour sélectionner le flux de contenu à assembler avec les annonces.

Demander des fichiers manifestes de séries d'annonces

Pour demander des annonces à Ad Manager, votre serveur doit envoyer une requête POST au point de terminaison des pods d'annonces, en transmettant les profils d'encodage, le tag d'emplacement publicitaire et les paramètres de ciblage demandés. Cette requête inclut également l'ID de flux que vous avez collecté à l'étape 1.

En retour, vous recevez une liste d'objets de séries d'annonces contenant des fichiers manifestes pour les séries d'annonces demandées par le tag d'emplacement publicitaire de l'éditeur, ainsi que des informations sur le moment et l'endroit où elles doivent être insérées dans votre contenu.

POST /ondemand/pods/api/v1/network/{network_code}/streams/{stream_id}/adpods
Host: dai.google.com
Content-Type: application/json
Paramètres du chemin d'accès
network_code Code de réseau Ad Manager 360 de l'éditeur.
stream_id ID de flux de l'application de lecteur vidéo cliente.

Corps JSON

Paramètres du corps
encoding_profiles Required Liste des représentations JSON des profils d'encodage que vous souhaitez recevoir pour chaque coupure publicitaire. Plus d'informations ci-dessous :

Pour que la lecture soit aussi fluide que possible, elle doit correspondre à l'ensemble des profils d'encodage utilisés dans votre flux de contenu.

ad_tag Required Un tag d'emplacement publicitaire permettant de demander des annonces VMAP.
cuepoints Optional Liste de points de repère dans le flux de contenu où les coupures publicitaires mid-roll seront insérées. Les points de repère sont mesurés en secondes à virgule flottante.

Requis uniquement pour les réponses VMAP contenant des annonces vidéo mid-roll utilisant des décalages temporels positionnels. C'est peu courant.

content_duration_seconds Optional Durée du contenu en secondes.

Obligatoire uniquement pour les réponses VMAP qui contiennent des annonces vidéo mid-roll en utilisant des décalages temporels de pourcentage. C'est peu courant.

manifest_type Optional Format des flux d'annonces demandés (hls ou dash). La valeur par défaut est hls.
dai_options Optional Options supplémentaires contrôlant certains aspects du rendu des fichiers manifestes Plus d'informations ci-dessous :
Profil d'encodage
profile_name Required Identifiant de ce profil d'encodage. Cette valeur peut être n'importe quelle chaîne de votre choix, mais vous ne pouvez pas avoir plusieurs profils d'encodage portant le même nom sur le même flux.
type Required Type d'encodage du flux décrit par ce profil d'encodage. Les types de contenus sont les suivants: media, iframe, subtitles.
container_type Required Format de conteneur utilisé par ce profil d'encodage. Les formats de conteneurs sont les suivants : mpeg2ts, fmp4cmaf et hls_packed_audio.
video_settings Optional Obligatoire si le profil d'encodage est de type iframe. Sinon, n'est autorisé que si le type de support contient vidéo. Voir les détails ci-dessous
audio_settings Optional Obligatoire si le profil d'encodage contient de l'audio. Uniquement autorisé s'il s'agit d'un média. Plus d'informations ci-dessous :
subtitle_settings Optional Obligatoire si le profil d'encodage comporte des sous-titres. Plus d'informations ci-dessous :
Paramètres vidéo
codec Required Chaîne de codec RFC6381.

Exemple : avc1.4d000c

bitrate Required Entier représentant le débit vidéo maximal de ce profil en octets par seconde.
frames_per_second Required FPS à virgule flottante de la vidéo.
resolution Required Valeur encodée au format JSON contenant les valeurs "width" et "height" de la vidéo en pixels.

Exemple : {"width": 640, "height": 320}

Paramètres audio
codec Required Chaîne de codec RFC6381.

Exemple : mp4a.40.5

bitrate Required Entier représentant le débit audio maximal de ce profil en octets par seconde.

Exemple : 300000

channels Required Entier représentant le nombre de canaux audio, y compris les canaux basse fréquence.
sample_rate Required Entier représentant le taux d'échantillonnage audio en hertz.

Exemple : 4800

Paramètres des sous-titres
format Required Format de fichier utilisé par les sous-titres intégrés au groupe. Les valeurs acceptées sont webvtt ou ttml.
language Optional Langue des sous-titres en tant que chaîne de langue RFC5646. Si elle est fournie, cette valeur n'est utilisée que pour l'affichage DASH.

Exemple : en-us

Options d'insertion dynamique d'annonces
dash_profile Optional Profil MPEG-DASH à appliquer aux fichiers manifestes de séries d'annonces. Ce paramètre n'est utilisé que pour les fichiers manifestes DASH. Les valeurs autorisées sont live ou on-demand. La valeur par défaut est on-demand.

La valeur live correspond au profil MPEG-DASH "urn:mpeg:dash:profile:isoff-live:2011".

La valeur on-demand correspond au profil MPEG-DASH urn:mpeg:dash:profile:isoff-on-demand:2011.

ad_pod_timeout Optional Temps maximal consacré à la sélection des annonces et à la création de séries d'annonces, en secondes à virgule flottante. Une fois ce délai écoulé, Ad Manager renvoie toutes les annonces déjà sélectionnées dans la réponse ad_pods et arrête le traitement.
sam_id Optional Spécifie une autre clé de débogage pouvant être utilisée pour rechercher des sessions dans l'outil de contrôle de l'activité des flux.

Réponse

Paramètres de réponse
valid_for Durée de validité de ces playlists de séries d'annonces, au format dhms (jours, heures, minutes, secondes).
valid_until Date et heure jusqu'à laquelle ces playlists de séries d'annonces sont valides en tant que chaîne de date et d'heure ISO 8601, au format yyyy-MM-dd'T'hh:mm:ss.sssssssss[+|-]hh:mm.
ad_pods Liste des séries d'annonces sélectionnées pour ce flux.
Série d'annonces
manifest_uris Pour les flux HLS uniquement. Mappage des ID de profil d'encodage avec les URI de fichier manifeste HLS.
mpd_uri Pour les flux DASH uniquement. URI de la description de la présentation du média DASH.
type Type de série d'annonces. Les types de séries d'annonces sont les suivants: pre, mid ou post.
start Pour les séries d'annonces mid-roll uniquement. Position dans le flux où cette série d'annonces doit être insérée, en secondes à virgule flottante.
duration Durée de cette série d'annonces, en secondes à virgule flottante.
midroll_index Pour les séries d'annonces mid-roll uniquement. Index de la série d'annonces mid-roll actuelle. L'indexation commence par 1.

Exemple de requête (cURL)

curl -X POST \
     -d '@request-body.json' \
     -H 'Content-Type: application/json' \
  https://dai.google.com/ondemand/pods/api/v1/network/21775744923/streams/6e69425c-0ac5-43ef-b070-c5143ba68541:CHS/adpods

Exemple de corps de requête

Il s'agit du contenu de request-body.json référencé dans l'appel cURL ci-dessus.

{
  "encoding_profiles": [
   {
     "profile_name": "1080p",
     "type": "media",
     "container_type": "mpeg2ts",
     "video_settings": {
       "codec": "avc1.4d000c",
       "bitrate": 5000000,
       "frames_per_second": 30.0,
       "resolution": {
         "width": 1920,
         "height": 1080
       }
     },
     "audio_settings": {
       "codec": "mp4a.40.5",
       "bitrate": 300000,
       "channels": 2,
       "sample_rate": 48000
     }
   },
   {
     "profile_name": "360p",
     "type": "media",
     "container_type": "mpeg2ts",
     "video_settings": {
       "codec": "avc1.4d000d",
       "bitrate": 1000000,
       "frames_per_second": 30.0,
       "resolution": {
         "width": 640,
         "height": 360
       }
     },
     "audio_settings": {
       "codec": "mp4a.40.5",
       "bitrate": 64000,
       "channels": 2,
       "sample_rate": 48000
     }
   },
   {
     "profile_name": "subtitles-webvtt",
     "type": "subtitles",
     "subtitle_settings": {
       "format": "webvtt"
     }
   }
 ],
 "ad_tag": "https://pubads.g.doubleclick.net/gampad/ads?...",
 "manifest_type": "hls"
}

Exemple de réponse

{
  "valid_for": "8h0m0s",
  "valid_until": "2023-03-24T08:30:26.839717986-07:00",
  "ad_pods": [
    {
      "manifest_urls":{
        "1080p": "https://{...}/pod/0/profile/1080p.m3u8",
        "360p": "https://{...}/pod/0/profile.m3u8",
        "subtitles-webvtt": "https://{...}/pod/0/profile/subtitles-en.vtt"
      },
      "type": "pre",
      "duration": 10.0
    },
    {
      "manifest_urls":{
        "1080p": "https://{...}/pod/1/profile/1080p.m3u8",
        "360p": "https://{...}/pod/1/profile.m3u8",
        "subtitles-webvtt": "https://{...}/pod/1/profile/subtitles-en.vtt"
      },
      "type": "mid",
      "start": 15.0,
      "duration": 15.0,
      "midroll_index": 1
    },
    {
      "manifest_urls":{
        ]"1080p": "https://{...}/pod/2/profile/1080p.m3u8",
        "360p": "https://{...}/pod/2/profile.m3u8",
        "subtitles-webvtt": "https://{...}/pod/0/profile/subtitles-en.vtt""
      },
      "type": "post",
      "duration": 10.0
    }
  ]
}

Assembler les séries d'annonces dans le contenu

Le processus d'intégration des séries d'annonces dans vos flux de contenu varie en fonction de votre implémentation, du format de flux et des fonctionnalités que vous choisissez d'implémenter parmi les spécifications du format. Les workflows suivants sont des suggestions pour gérer ce processus. Les détails précis de votre implémentation peuvent varier en fonction des besoins de votre entreprise et de vos flux de contenu.

Flux HLS

Si vous assemblez un flux au format HLS, votre flux de contenu sera une playlist multivariante de liens vers des fichiers manifestes de flux distincts, un pour chaque profil d'encodage. Vous devez insérer vos séries d'annonces dans chacun de ces fichiers manifestes de variantes. Pour ce faire, vous pouvez préparer tous les fichiers manifestes de variantes et les transmettre à un réseau de diffusion de contenu (CDN) pour l'hébergement. La playlist de multivariantes finale est un ensemble de liens vers ces fichiers manifestes hébergés sur CDN.

Itérer des profils d'encodage

Pour chaque profil d'encodage, rassemblez tous les fichiers manifestes de séries d'annonces associés à partir de la réponse d'Ad Manager, ainsi que les heures de début associées. Pour les séries d'annonces pré-roll, définissez l'heure de début sur 0. Pour les annonces vidéo post-roll, utilisez la durée du contenu comme heure de début de la série d'annonces. Dans la playlist de multivariantes, identifiez le flux de variantes qui correspond aux paramètres audio et vidéo de chaque profil d'encodage.

Tableau des exemples de séries d'annonces
"ad_pods": [
    {
      "manifest_urls":{
        "1080p": "https://{...}/pod/0/profile/1080p.m3u8",
        "360p": "https://{...}/pod/0/profile/360p.m3u8",
        "subtitles-en": "https://{...}/pod/0/profile/subitles-en.vtt"
      },
      "type": "pre",
      "duration": 10.0
    },
    {
      "manifest_urls":{
        "1080p": "https://{...}/pod/1/profile/1080p.m3u8",
        "360p": "https://{...}/pod/1/profile/360p.m3u8",
        "subtitles-en": "https://{...}/pod/1/profile/subitles-en.vtt"
      },
      "type": "mid",
      "start": 15.0,
      "duration": 15.0,
      "midroll_index": 1
    },
    {
      "manifest_urls":{
        "1080p": "https://{...}/pod/2/profile/1080p.m3u8",
        "360p": "https://{...}/pod/2/profile/360p.m3u8",
        "subtitles-en": "https://{...}/pod/2/profile/subitles-en.vtt"
      },
      "type": "post",
      "duration": 10.0
    }
  ]
Exemple de playlist de contenus multivariantes
#EXTM3U
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs0",LANGUAGE="en",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="https://{...}/subitles-en.vtt"
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.4d000c,mp4a.40.5"
https://{...}/1080p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.4d000d,mp4a.40.5"
https://{...}/360p.m3u8
Exemples de données de variantes collectées
Encoding profile: "1080p"
Profile settings: {...}
Content manifest: https://{...}/1080p.m3u8
Ad pods (start time -> manifest):
    0 -> https://{...}/pod/0/profile/1080p.m3u8
   15 -> https://{...}/pod/1/profile/1080p.m3u8
  600 -> https://{...}/pod/2/profile/1080p.m3u8

Insérer des annonces dans chaque fichier manifeste de variante

Pour chaque flux de variantes, parcourez les segments du fichier manifeste de contenu, en conservant le total cumulé de la durée écoulée pour le contenu. Lorsque vous atteignez la position de départ d'une série d'annonces, extrayez la liste des segments à partir du fichier manifeste de la série d'annonces, encapsulez la liste des segments dans deux tags #EXT-X-DISCONTINUITY, puis insérez la liste à l'emplacement actuel dans le fichier manifeste du contenu. Continuez jusqu'à ce que toutes les séries d'annonces et tous les flux de variantes aient été traités.

Les fichiers manifestes générés doivent être conformes à la norme HLS. Par conséquent, en fonction des fonctionnalités de la spécification qui sont intégrées dans votre fichier manifeste de contenu, vous devrez peut-être effectuer une dernière transmission sur le fichier manifeste combiné pour corriger les numéros séquentiels du média, la durée du contenu, les numéros de séquence de discontinuité et toute autre balise devant être mise à jour pour tenir compte des nouveaux segments d'annonces. Une fois les différences avec la norme corrigées, transférez chaque fichier manifeste de variante spécifique à l'utilisateur vers votre CDN pour l'hébergement.

Si votre fichier manifeste de contenu est chiffré, vous devez stocker la dernière clé de chiffrement trouvée avant le début de la série d'annonces actuelle dans une balise #EXT-X-KEY. Vous devez ensuite ajouter le tag #EXT-X-KEY:METHOD=NONE pour supprimer le chiffrement avant le premier segment de chaque série d'annonces. Enfin, vous devez ajouter une copie de la balise #EXT-X-KEY stockée avant le premier segment de contenu après chaque série d'annonces afin de restaurer le chiffrement du contenu.

Exemples de données de variantes collectées
Encoding profile: "1080p"
Content manifest: https://{...}/1080p.m3u8
Ad pods (start time -> manifest):
    0 -> https://dai.google.com/{...}pod/0/profile/1080p.m3u8
   15 -> https://dai.google.com/{...}pod/1/profile/1080p.m3u8
  600 -> https://dai.google.com/{...}pod/2/profile/1080p.m3u8
Exemple de fichier manifeste de contenu

Il s'agit du contenu du fichier manifeste https://{...}/1080p.m3u8 répertorié dans les données de variantes collectées.

#EXTM3U
{...}
#EXTINF:5.000,
https://{...}/1080p/content-segment-0.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-1.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-2.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-3.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-4.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-5.ts
{...}
Exemple de fichier manifeste de série d'annonces

Il s'agit du contenu du fichier manifeste https://dai.google.com/{...}/pod/1/profile/1080p.m3u8 répertorié dans les données de variantes collectées.

#EXTM3U
{...}
#EXTINF:5.000,
https://dai.google.com/{...}/0.ts
#EXTINF:5.000,
https://dai.google.com/{...}/1.ts
#EXTINF:5.000,
https://dai.google.com/{...}/2.ts
Exemple de fichier manifeste de variantes assemblées

Il s'agit du fichier manifeste de variante assemblée obtenu, transmis au CDN et hébergé à https://cdn.{...}/{userid}/1080p.m3u8.

#EXTM3U
{...}
#EXTINF:5.000,
https://{...}/1080p/content-segment-0.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-1.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-2.ts
#EXT-X-DISCONTINUITY
#EXTINF:5.000,
https://dai.google.com/{...}/0.ts
#EXTINF:5.000,
https://dai.google.com/{...}/1.ts
#EXTINF:5.000,
https://dai.google.com/{...}/2.ts
#EXT-X-DISCONTINUITY
#EXTINF:5.000,
https://{...}/1080p/content-segment-3.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-4.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-5.ts
{...}

Créer une playlist de multivariantes

Collectez les adresses CDN pour chaque fichier manifeste de variante terminé, ainsi que les détails du profil d'encodage correspondant, puis assemblez les résultats dans un nouveau fichier manifeste de multivariantes. Ce fichier manifeste spécifique à l'utilisateur est renvoyé en réponse à la requête de fichier manifeste reçue à l'étape 1.

Exemple de playlist de multivariantes finale
#EXTM3U
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs0",LANGUAGE="en",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="https://cdn.{...}-subitles-en.vtt"
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.4d000c,mp4a.40.5"
https://cdn.{...}/{userid}/1080p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.4d000d,mp4a.40.5"
https://cdn.{...}/{userid}/360p.m3u8

Flux MPEG DASH

Si vous assemblez un flux au format MPEG DASH, il vous suffit de produire un seul fichier. Cela peut rendre les flux DASH plus faciles à assembler que HLS.

Un fichier MPEG DASH Mediapresentation Description (MPD) correctement préparé doit comporter plusieurs points, chacun contenant plusieurs représentations. Chaque représentation doit correspondre à l'un de vos profils d'encodage. Chaque série d'annonces renvoyée par Ad Manager est également un fichier MPD contenant une séquence de points avec des représentations correspondantes.

Pour assembler ces fichiers MPD, commencez par noter les heures de début de chaque série d'annonces. Pour les annonces vidéo pré-roll, insérez les périodes de série d'annonces pré-roll avant toute période de contenu. Pour les annonces vidéo post-roll, insérez les périodes de série d'annonces post-roll après toutes les périodes de contenu. Itérez les périodes de la description de la présentation du média pour le contenu, en suivant le temps de lecture écoulé pour toutes les périodes de contenu traitées. Lorsque vous atteignez une limite entre les périodes correspondant à l'heure de début d'une série d'annonces, insérez les points du fichier MPD de la série d'annonces mid-roll correspondant à cette limite.

Le fichier MPD final assemblé doit être entièrement conforme aux spécifications MPEG_DASH. Par conséquent, vous devrez peut-être itérer une nouvelle fois le fichier final en corrigeant les heures de début des périodes, en corrigeant la durée de présentation du média pour tenir compte des nouvelles périodes d'annonces et en résolvant tout autre conflit pouvant survenir lors du processus d'assemblage.

Exemple de description de la présentation du média pour le contenu

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500000S" type="static" mediaPresentationDuration="PT0H10M00.000S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">
  <ProgramInformation moreInformationURL="http://.../info">
    <Title>Example Stream</Title>
  </ProgramInformation>
  <Period duration="PT0H0M15.000S" id="content-period-1">
    ...
  </Period>
  <Period duration="PT0H0M15.000S" id="content-period-2">
    ...
  </Period>
  <Period duration="PT0H0M15.000S" id="content-period-3">
    ...
  </Period>
  ...
</MPD>

Exemple de code JSON de série d'annonces

[{
  "mpd_uri": "https://{...}pod/1.mpd",
  "type": "mid",
  "start": 15.0,
  "duration": 15.0,
  "midroll_index": 1
}]

Exemple de description de la présentation du média pour la série d'annonces

Il s'agit du contenu du mpd_uri du fichier JSON de série d'annonces ci-dessus.

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500000S" type="static" mediaPresentationDuration="PT0H0M15.000S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">
  <ProgramInformation moreInformationURL="http://.../info">
    <Title>Ad Pod 1</Title>
  </ProgramInformation>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-1">
    ...
  </Period>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-2">
    ...
  </Period>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-3">
    ...
  </Period>
  ...
</MPD>

Exemple de description de la présentation du média assemblé

Servir de réponse à la requête initiale du fichier manifeste de flux.

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500000S" type="static" mediaPresentationDuration="PT0H10M15.000S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">
  <ProgramInformation moreInformationURL="http://.../info">
    <Title>Example Stream</Title>
  </ProgramInformation>
  <Period duration="PT0H0M15.000S" id="content-period-1">
    ...
  </Period>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-1">
    ...
  </Period>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-2">
    ...
  </Period>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-3">
    ...
  </Period>
  <Period duration="PT0H0M15.000S" id="content-period-2">
    ...
  </Period>
  <Period duration="PT0H0M15.000S" id="content-period-3">
    ...
  </Period>
  ...
</MPD>

Ressources supplémentaires