La API de Pod Serving proporciona acceso a los grupos de anuncios de video con tasa de bits adaptable preparados de modo que se puedan unir directamente en una playlist multimedia de HLS o MPEG-DASH para el usuario.
Esta guía se enfoca en la implementación de un servidor básico de manipulación de manifiestos de la entrega de Pods para las transmisiones de VOD.
Cómo recibir solicitudes del manifiesto de transmisión
Tu manipulador de manifiestos debe proporcionar un extremo de API para escuchar las solicitudes de manifiestos de la app cliente del reproductor de video. Como mínimo, este extremo debe recopilar un ID de transmisión de la app del reproductor cliente. Este ID de transmisión se usa para identificar la sesión de transmisión a Ad Manager en tus solicitudes de grupos de anuncios.
También debes recopilar otra información para identificar la transmisión de contenido adecuada, por ejemplo, un ID de contenido.
Ejemplo de extremo de solicitud del manifiesto
GET /api/stream_id/{stream_id}/video/{content_id}.{format}
Host: {your_domain}
Parámetros de ruta | |||||
---|---|---|---|---|---|
stream_id |
El ID de transmisión de Ad Manager de la app cliente de reproductor de video | ||||
content_id |
Es un ID hipotético que corresponde al video de contenido en tu sistema. | ||||
format |
Es un parámetro hipotético que corresponde al formato de transmisión. Una de las siguientes opciones:
|
Cómo recuperar la transmisión de contenido
Usa el Content ID recopilado de la solicitud del manifiesto para seleccionar el flujo de contenido que deseas unir con los anuncios.
Solicita manifiestos de grupos de anuncios
Para solicitar anuncios de Ad Manager, tu servidor debe hacer una solicitud POST al extremo de grupos de anuncios y pasar los perfiles de codificación, la etiqueta de anuncio y los parámetros de segmentación solicitados. Esta solicitud también incluye el ID de transmisión que recopilaste en el paso 1.
A cambio, recibes una lista de objetos de pods de anuncios que contienen archivos de manifiesto para los pods de anuncios solicitados por la etiqueta de anuncio del publicador, además de información sobre cuándo y dónde deben insertarse en tu contenido.
POST /ondemand/pods/api/v1/network/{network_code}/streams/{stream_id}/adpods
Host: dai.google.com
Content-Type: application/json
Parámetros de ruta | |
---|---|
network_code |
El código de red de Ad Manager 360 del publicador. |
stream_id |
El ID de transmisión de la app cliente de reproductor de video. |
Cuerpo JSON
Parámetros corporales | ||
---|---|---|
encoding_profiles |
Required |
Una lista de representaciones JSON de los perfiles de codificación que deseas recibir para cada pausa publicitaria. Sigue leyendo para conocer más detalles
Para que la reproducción sea lo más fluida posible, debe coincidir con el conjunto de perfiles de codificación que se usan en la transmisión de contenido. |
ad_tag |
Required |
Una etiqueta de anuncio para solicitar anuncios de VMAP. |
cuepoints |
Optional |
Una lista de puntos de inserción dentro de la transmisión de contenido en los que se insertarán las pausas publicitarias durante el video. Los puntos de inserción se miden en segundos de punto flotante.
Obligatorio solo para las respuestas de VMAP que contienen anuncios durante el video que usan compensaciones de tiempo posicionales. Esto es poco común. |
content_duration_seconds |
Optional |
Es la duración del contenido en segundos.
Obligatorio solo para las respuestas de VMAP que contienen anuncios durante el video con compensaciones de tiempo de porcentaje. Esto es poco común. |
manifest_type |
Optional |
El formato de las transmisiones de anuncios que se solicitan, ya sea hls o dash . El valor predeterminado es hls .
|
dai_options |
Optional |
Opciones adicionales que controlan aspectos de la representación de los manifiestos. Sigue leyendo para conocer más detalles |
Perfil de codificación | ||
profile_name |
Required |
Es un identificador para este perfil de codificación. Este valor puede ser cualquier string que elijas, pero no puedes tener varios perfiles de codificación con el mismo nombre en la misma transmisión. |
type |
Required |
El tipo de codificación de la transmisión que se describe en este perfil de codificación. Los tipos de contenido son media , iframe y subtitles .
|
container_type |
Required |
El formato de contenedor que usa este perfil de codificación. Los formatos de contenedor son los siguientes:
mpeg2ts , fmp4cmaf y hls_packed_audio
|
video_settings |
Optional |
Obligatorio si el tipo de perfil de codificación es iframe. De lo contrario, solo se permite si el tipo de medio contiene video. Consulta los detalles a continuación |
audio_settings |
Optional |
Obligatorio si el perfil de codificación contiene audio. Solo se permite si el tipo es multimedia. Sigue leyendo para conocer más detalles |
subtitle_settings |
Optional |
Obligatorio si el perfil de codificación contiene subtítulos. Sigue leyendo para conocer más detalles |
Configuración de video | ||
codec |
Required |
La string de códec RFC6381.
Ejemplo: |
bitrate |
Required |
Es un número entero que representa la tasa de bits de video máxima de este perfil en bytes por segundo. |
frames_per_second |
Required |
Es la cantidad de FPS de punto flotante del video. |
resolution |
Required |
Es un valor codificado en JSON que contiene el "ancho" y la "altura" del video en píxeles.
Ejemplo: |
Configuración de audio | ||
codec |
Required |
La string de códec RFC6381.
Ejemplo: |
bitrate |
Required |
Es un número entero que representa la tasa de bits de audio máxima de este perfil en bytes por
segundo.
Ejemplo: |
channels |
Required |
Es un número entero que representa la cantidad de canales de audio, incluidos los canales de baja frecuencia. |
sample_rate |
Required |
Es un número entero que representa la tasa de muestreo de audio en hercios.
Ejemplo: |
Configuración de subtítulos | ||
format |
Required |
El formato de archivo que usan los subtítulos dentro de la banda. Los valores admitidos son webvtt o ttml .
|
language |
Optional |
El idioma del subtítulo como una cadena de idioma RFC5646. Si se proporciona, este valor solo se usa para el procesamiento de DASH.
Ejemplo: |
Opciones de DAI | ||
dash_profile |
Optional |
Es el perfil de MPEG-DASH que se aplicará a los manifiestos de grupos de anuncios. Esta configuración solo se usa para los manifiestos de DASH. Los valores permitidos son live o on-demand . El valor predeterminado es on-demand .
El valor
El valor |
ad_pod_timeout |
Optional |
El tiempo máximo que se dedica a seleccionar anuncios y crear grupos de anuncios, en segundos de punto flotante. Una vez transcurrido ese tiempo, Ad Manager mostrará todos los anuncios que ya estén seleccionados en la respuesta ad_pods y dejará de procesar.
|
sam_id |
Optional |
Especifica una clave de depuración alternativa que se puede usar para buscar sesiones en la supervisión de actividad de transmisión. |
Respuesta
Parámetros de respuesta | |
---|---|
valid_for |
La duración de la validez de estas playlists del grupo de anuncios, en formato dhms (días, horas, minutos y segundos).
|
valid_until |
Es la fecha y la hora hasta la cual estas playlists de grupos de anuncios son válidas como una cadena de fecha y hora ISO8601 en formato yyyy-MM-dd'T'hh:mm:ss.sssssssss[+|-]hh:mm .
|
ad_pods |
Es una lista de grupos de anuncios seleccionados para esta transmisión. |
Grupo de anuncios | |
manifest_uris |
Solo para transmisiones HLS. Mapa de los IDs de perfil de codificación para los URI del manifiesto de HLS. |
mpd_uri |
Solo para transmisiones DASH. El URI de la MPD de DASH. |
type |
Es el tipo de grupo de anuncios. Los tipos de grupos de anuncios son pre , mid o post .
|
start |
Solo para grupos de anuncios durante el video. Es la posición en la transmisión en la que se debe insertar este grupo de anuncios, en segundos de punto flotante. |
duration |
Es la duración de este grupo de anuncios, expresada en segundos de punto flotante. |
midroll_index |
Solo para grupos de anuncios durante el video. Es el índice del grupo de anuncios actual de anuncios durante el video. La indexación comienza con 1 .
|
Ejemplo de solicitud (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
Ejemplo de cuerpo de la solicitud
Este es el contenido de request-body.json
al que se hace referencia en la llamada cURL anterior.
{
"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"
}
Ejemplo de respuesta
{
"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
}
]
}
Une grupos de anuncios en el contenido
El proceso de unir grupos de anuncios a tus transmisiones de contenido varía según la implementación, el formato de transmisión y las funciones que elijas implementar a partir de las especificaciones del formato. Los siguientes flujos de trabajo son sugerencias para controlar este proceso. Los detalles precisos de tu implementación pueden variar según las necesidades de tu empresa y los flujos de contenido.
Transmisiones HLS
Si estás uniendo una transmisión en formato HLS, tu transmisión de contenido será una playlist de múltiples variantes de vínculos a manifiestos de transmisión separados, uno para cada perfil de codificación. Tus grupos de anuncios deben insertarse en cada uno de los manifiestos de estas variantes. Una forma de hacerlo es preparar todos los manifiestos de variantes y pasarlos a una red de distribución de contenidos (CDN) para alojarlos. La playlist final de múltiples variantes es un conjunto de vínculos a estos manifiestos alojados en CDN.
Realiza iteraciones en perfiles de codificación
Para cada perfil de codificación, recopila todos los manifiestos de Pods de anuncios asociados a partir de la respuesta de Ad Manager, junto con sus horas de inicio asociadas. Para los grupos de anuncios previos al video, establece la hora de inicio en 0
. Para los anuncios al final del video, usa la duración del contenido como la hora de inicio del grupo de anuncios. Identifica la transmisión de variantes en la playlist de múltiples variantes que coincida con la configuración de audio y video de cada perfil de codificación.
Ejemplo de array de grupos de anuncios
"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
}
]
Ejemplo de playlist de contenido de múltiples variantes
#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
Ejemplos de datos de variantes recopilados
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
Inserta anuncios en el manifiesto de cada variante
Para la transmisión de cada variante, revisa los segmentos del manifiesto de contenido y mantén un total activo del tiempo de contenido transcurrido. Cuando llegues a la posición de inicio de un grupo de anuncios, extrae la lista de segmentos del manifiesto del grupo de anuncios, une la lista de segmentos en dos etiquetas #EXT-X-DISCONTINUITY
y, luego, inserta la lista en la ubicación actual en el manifiesto de contenido. Continúa con este proceso hasta que se hayan procesado todos los grupos de anuncios y las transmisiones de variantes.
Los manifiestos resultantes deben cumplir con el estándar HLS. Por lo tanto, según las funciones de la especificación que incorpore tu manifiesto de contenido, es posible que debas realizar un último pase por el manifiesto combinado para corregir los números de las secuencias de medios, la duración del contenido, los números de la secuencia de discontinuidad y cualquier otra etiqueta que deban actualizarse para tener en cuenta los nuevos segmentos de anuncios. Una vez que se hayan corregido las discrepancias con el estándar, envía el manifiesto de cada variante específica del usuario a tu CDN para alojarla.
Si el manifiesto de contenido está encriptado, debes almacenar la última clave de encriptación que se encontró antes del inicio del grupo de anuncios actual en una etiqueta #EXT-X-KEY
. Luego, debes agregar la etiqueta #EXT-X-KEY:METHOD=NONE
para quitar la encriptación antes del primer segmento de cada Pod de anuncios. Por último, debes agregar una copia de la etiqueta #EXT-X-KEY
almacenada antes del primer segmento de contenido después de cada Pod de anuncios para restablecer la encriptación de contenido.
Ejemplos de datos de variantes recopilados
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
Ejemplo de manifiesto de contenido
Este es el contenido del manifiesto https://{...}/1080p.m3u8
que se incluye en los datos de variantes recopilados.
#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
{...}
Ejemplo de manifiesto de grupo de anuncios
Este es el contenido del manifiesto https://dai.google.com/{...}/pod/1/profile/1080p.m3u8
que se enumera en los datos de variantes recopilados.
#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
Ejemplo de manifiesto de una variante unida
Este sería el manifiesto resultante de la variante unida, que se pasa a la CDN y se aloja en 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
{...}
Cómo crear una playlist de múltiples variantes
Recopila las direcciones de CDN de cada manifiesto de variante completo, junto con los detalles del perfil de codificación que coincida, y ensambla los resultados en un manifiesto de múltiples variantes nuevo. Este manifiesto específico para el usuario se muestra como respuesta a la solicitud del manifiesto que recibiste en el paso 1.
Ejemplo de playlist final de múltiples variantes
#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
Transmisiones MPEG DASH
Si estás uniendo una transmisión en formato MPEG DASH, solo necesitas producir un solo archivo. Esto puede hacer que las transmisiones DASH sean más fáciles de unir que las de HLS.
Un archivo de descripción de presentación multimedia (MPD) MPEG DASH preparado correctamente debe constar de varios puntos, y cada uno de ellos contiene varias representaciones. Cada representación debe coincidir con uno de tus perfiles de codificación. Cada grupo de anuncios que muestra Ad Manager es también un archivo MPD que contiene una secuencia de períodos con representaciones coincidentes.
Para unir estos archivos MPD, comienza por tomar nota de los tiempos de inicio de cada grupo de anuncios. Para los anuncios previos al video, inserta los períodos del grupo de anuncios previos al video antes de cualquier período de contenido. Para los anuncios al final del video, inserta los períodos de grupos de anuncios al final del video después de todos los períodos de contenido. Itera los períodos en la MPD de contenido y realiza un seguimiento del tiempo de reproducción transcurrido para todos los períodos de contenido procesados. Cuando alcances un límite entre períodos que correspondan a la hora de inicio de un grupo de anuncios, inserta los puntos del archivo MPD del grupo de anuncios durante el video correspondiente en ese límite.
El archivo MPD final unido debe cumplir por completo con las especificaciones MPEG_DASH, por lo que es posible que debas iterar en el archivo final una vez más, corregir los tiempos de inicio de cualquier período, corregir la duración de la presentación multimedia para tener en cuenta los períodos del anuncio insertados recientemente y resolver cualquier otro conflicto que pueda haber surgido en el proceso de unión.
Ejemplo de MPD de contenido
<?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>
Ejemplo de JSON de grupo de anuncios
[{
"mpd_uri": "https://{...}pod/1.mpd",
"type": "mid",
"start": 15.0,
"duration": 15.0,
"midroll_index": 1
}]
Ejemplo de MPD del grupo de anuncios
Este es el contenido de mpd_uri
del JSON del grupo de anuncios anterior.
<?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>
Ejemplo de MPD unido
Ofrécele esto como respuesta a la solicitud inicial del manifiesto de transmisión.
<?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>
Recursos adicionales
- Reproducción de Pods con el SDK de IMA:
- Reproducción de un Pod con la API de DAI