VOD ストリーム用のマニフェスト マニピュレータ

Pod Serving API を使用すると、ユーザー向けの HLS または MPEG-DASH メディア プレイリストに直接組み込むことができるように準備された、アダプティブ ビットレート動画広告 Pod にアクセスできます。

このガイドでは、VOD ストリーム用の基本的な Pod Serving マニフェスト操作サーバーを実装することに焦点を当てます。

ストリーム マニフェスト リクエストを受信する

マニフェスト マニピュレータは、動画プレーヤー クライアント アプリからのマニフェスト リクエストをリッスンする API エンドポイントを提供する必要があります。このエンドポイントは、少なくともクライアント プレーヤー アプリからストリーム ID を収集する必要があります。このストリーム ID は、広告連続配信リクエストでアド マネージャーへのストリーミング セッションを識別するために使用されます。

また、適切なコンテンツ ストリームを特定するために、コンテンツ ID などのその他の情報も収集する必要があります。

マニフェスト リクエスト エンドポイントの例

GET /api/stream_id/{stream_id}/video/{content_id}.{format}
Host: {your_domain}
パスパラメータ
stream_id クライアントの動画プレーヤー アプリのアド マネージャー ストリーム ID。
content_id システム内のコンテンツ動画に対応する仮想 ID。
format ストリーム形式に対応する仮想パラメータ。次のいずれか:
mpd MPEG-DASH ストリームの場合
m3u8 HLS ストリームの場合

コンテンツ ストリームを取得する

マニフェスト リクエストから収集したコンテンツ ID を使用して、広告と結合するコンテンツ ストリームを選択します。

広告連続配信マニフェストをリクエストする

アド マネージャーから広告をリクエストするには、サーバーが広告連携エンドポイントに POST リクエストを行い、リクエストされたエンコード プロファイルと広告タグを渡す必要があります。このリクエストには、手順 1 で収集したストリーム ID も含まれます。

パブリッシャーの広告タグによってリクエストされた広告連続配信の広告マニフェスト ファイルと、コンテンツに広告連続配信を挿入するタイミングと場所に関する情報が含まれる広告連続配信オブジェクトのリストが返されます。

POST /ondemand/pods/api/v1/network/{network_code}/streams/{stream_id}/adpods
Host: dai.google.com
Content-Type: application/json
パスパラメータ
network_code パブリッシャーのアド マネージャー 360 ネットワーク コード。
stream_id クライアントの動画プレーヤー アプリのストリーム ID。

JSON 本文

本文パラメータ
encoding_profiles Required ミッドロール挿入点ごとに受信するエンコード プロファイルの JSON 表現のリスト。詳細は下記をご覧ください

再生をできるだけシームレスにするには、コンテンツ ストリームで使用されているエンコード プロファイルのセットと一致させる必要があります。

ad_tag Required VMAP 広告をリクエストする広告タグ。
cuepoints Optional ミッドロール広告ブレークが挿入されるコンテンツ ストリーム内のキューポイントのリスト。キューポイントは浮動小数点秒単位で測定されます。

位置情報の時間オフセットを使用するミッドロールを含む VMAP レスポンスにのみ必要です。これはまれなケースです。

content_duration_seconds Optional コンテンツの長さ(秒単位)。

割合の時間オフセットを使用するミッドロールを含む VMAP レスポンスにのみ必要です。これはまれなケースです。

manifest_type Optional リクエストされる広告ストリームの形式(hls または dash)。デフォルト値は hls です。
dai_options Optional マニフェストのレンダリング方法を制御するその他のオプション。詳細は下記をご覧ください
エンコード プロファイル
profile_name Required このエンコード プロファイルの識別子。この値には任意の文字列を使用できますが、同じストリームに同じ名前のエンコード プロファイルを複数設定することはできません。
type Required このエンコード プロファイルで記述されているストリームのエンコード タイプ。コンテンツ タイプは mediaiframesubtitles です。
container_type Required このエンコード プロファイルで使用されるコンテナ形式。コンテナ形式は、mpeg2tsfmp4cmafhls_packed_audio です。
video_settings Optional エンコード プロファイルのタイプが iframe の場合は必須です。それ以外の場合は、メディアタイプに動画が含まれている場合にのみ許可されます。詳細は下記をご覧ください
audio_settings Optional エンコード プロファイルに音声が含まれている場合は必須です。タイプがメディアの場合にのみ許可されます。詳細は下記をご覧ください
subtitle_settings Optional エンコード プロファイルに字幕が含まれている場合は必須です。詳細は下記をご覧ください
動画の設定
codec Required RFC6381 コーデック文字列。

例: avc1.4d000c

bitrate Required このプロファイルの最大動画ビットレートを秒あたりのバイト数で表す整数。
frames_per_second Required 動画の浮動小数点 FPS。
resolution Required 動画の「幅」と「高さ」(ピクセル単位)を含む JSON でエンコードされた値。

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

音声設定
codec Required RFC6381 コーデック文字列。

例: mp4a.40.5

bitrate Required このプロファイルの最大オーディオ ビットレート(1 秒あたりのバイト数)を表す整数。

例: 300000

channels Required 低周波チャンネルを含む音声チャンネルの数を表す整数。
sample_rate Required 音声のサンプリング レートをヘルツ単位で表す整数。

例: 4800

字幕の設定
format Required インバンド字幕で使用されるファイル形式。指定できる値は webvtt または ttml です。
language Optional 字幕の言語(RFC5646 言語文字列)。指定した場合、この値は DASH レンダリングにのみ使用されます。

例: en-us

DAI オプション
dash_profile Optional 広告連続配信マニフェストに適用する MPEG-DASH プロファイル。この設定は DASH マニフェストにのみ使用されます。指定できる値は live または on-demand です。デフォルト値は on-demand です。

liveMPEG-DASH プロファイル "urn:mpeg:dash:profile:isoff-live:2011" に対応します。

on-demandMPEG-DASH プロファイル urn:mpeg:dash:profile:isoff-on-demand:2011 に対応します。

ad_pod_timeout Optional 広告の選択と連続配信広告の作成に費やせる最大時間(浮動小数点秒単位)。この時間が経過すると、アド マネージャーは、すでに選択されている広告を ad_pods レスポンスで返して処理を停止します。
sam_id Optional ストリーム アクティビティ モニターでセッションを検索するために使用できる代替のデバッグキーを指定します。

レスポンス

レスポンス パラメータ
valid_for これらの広告連続再生リストの有効期間(dhms 形式(日、時間、分、秒))。
valid_until これらの広告連続再生リストが ISO8601 日時文字列として有効な日時(yyyy-MM-dd'T'hh:mm:ss.sssssssss[+|-]hh:mm 形式)。
ad_pods このストリーム用に選択された広告連続配信のリスト。
連続配信広告
manifest_uris HLS ストリームにのみ使用できます。エンコード プロファイル ID と HLS マニフェスト URI のマッピング。
mpd_uri DASH ストリームのみ。DASH MPD の URI。
type 広告連続配信のタイプ。連続配信広告のタイプは、premidpost です。
start ミッドロール連続配信広告のみ。この連続配信広告を挿入するストリーム内の位置(浮動小数点秒単位)。
duration この連続配信広告の再生時間(浮動小数点秒単位)。
midroll_index ミッドロール連続配信広告のみ。現在のミッドロール連続配信広告のインデックス。インデックスは 1 で始まります。

リクエストの例(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

リクエスト本文の例

これは、上記の cURL 呼び出しで参照される request-body.json の内容です。

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

レスポンスの例

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

広告連続配信をコンテンツに縫い付ける

広告連続配信をコンテンツ ストリームに縫い付けるプロセスは、実装方法、ストリーム形式、フォーマットの仕様から実装する機能によって異なります。次のワークフローは、このプロセスを処理する方法の候補です。実装の詳細は、ビジネスニーズとコンテンツ ストリームによって異なる場合があります。

HLS ストリーム

HLS 形式でストリームをステッチする場合、コンテンツ ストリームは、エンコード プロファイルごとに 1 つずつ、個別のストリーム マニフェストへのリンクのマルチバリアント プレイリストになります。広告 Pod は、これらの各バリエーション マニフェストに挿入する必要があります。これを行う方法の一つは、すべてのバリアント マニフェストを準備し、コンテンツ配信ネットワーク(CDN)に渡してホストすることです。最終的なマルチバリエーション再生リストは、これらの CDN でホストされているマニフェストへのリンクのセットです。

エンコード プロファイルを反復処理する

エンコード プロファイルごとに、アド マネージャーのレスポンスから、関連する広告連続配信マニフェストと、関連する開始時間をすべて収集します。プレロール広告連続配信の場合は、開始時間を 0 に設定します。ポストロールの場合は、広告連続配信の開始時間としてコンテンツの再生時間を使用します。各エンコード プロファイルの音声と動画の設定に一致するマルチバリアント プレイリストのバリアント ストリームを特定します。

連続配信広告の配列の例
"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
    }
  ]
マルチバリエーション コンテンツ再生リストの例
#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
収集されたバリエーション データの例
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

各バリエーション マニフェストに広告を挿入する

各パターン ストリームについて、コンテンツ マニフェストのセグメントを確認し、経過したコンテンツ時間を合計します。連続配信広告の開始位置に到達したら、連続配信広告のマニフェストからセグメントのリストを抽出し、2 つの #EXT-X-DISCONTINUITY タグでセグメントのリストをラップして、コンテンツ マニフェストの現在の位置にリストを挿入します。すべての広告 Pod とバリエーション ストリームが処理されるまで、このプロセスを続けます。

生成されたマニフェストは HLS 標準に準拠している必要があります。そのため、コンテンツ マニフェストに組み込まれている仕様の機能によっては、統合されたマニフェストを最終的に確認し、メディア シーケンス番号、コンテンツの長さ、不連続シーケンス番号、新しい広告セグメントを考慮して更新が必要なその他のタグを修正する必要があります。標準との不一致を修正したら、各ユーザー固有のバリエーション マニフェストを CDN にプッシュしてホストします。

コンテンツ マニフェストが暗号化されている場合は、現在の連続配信広告の開始前に検出された最後の暗号鍵を #EXT-X-KEY タグに保存する必要があります。次に、各広告 Pod の最初のセグメントの前にタグ #EXT-X-KEY:METHOD=NONE を追加して、暗号化を解除する必要があります。最後に、コンテンツの暗号化を復元するために、各広告連続配信の後のコンテンツの最初のセグメントの前に、保存した #EXT-X-KEY タグのコピーを追加する必要があります。

収集されたバリエーション データの例
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
コンテンツ マニフェストの例

これは、収集されたバリエーション データにリストされている https://{...}/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
#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
{...}
広告連続配信マニフェストの例

これは、収集されたバリエーション データにリストされている https://dai.google.com/{...}/pod/1/profile/1080p.m3u8 マニフェストのコンテンツです。

#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
ステッチされたバリアント マニフェストの例

これが、CDN に渡され、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
{...}

マルチバリエーション再生リストを作成する

完了した各バリエーション マニフェストの CDN アドレスと、一致するエンコード プロファイルの詳細を収集し、結果を新しいマルチバリエーション マニフェストにまとめます。このユーザー固有のマニフェストは、ステップ 1 で受け取ったマニフェスト リクエストに対するレスポンスとして返されます。

最終的なマルチバリエーション再生リストの例
#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

MPEG DASH ストリーム

MPEG DASH 形式でストリームをステッチする場合は、1 つのファイルのみを生成する必要があります。これにより、DASH ストリームを HLS よりも簡単にステッチできます。

適切に準備された MPEG DASH メディア プレゼンテーション記述(MPD)ファイルは、複数の期間で構成され、それぞれに複数のレプリケーションが含まれている必要があります。各表現は、エンコード プロファイルのいずれかと一致する必要があります。アド マネージャーから返される各広告 Pod は、一致する表現を含む期間のシーケンスを含む MPD ファイルでもあります。

これらの MPD ファイルをつなぎ合わせるには、まず各広告連続配信の開始時間をメモします。プレロールの場合は、コンテンツの期間の前にプレロール広告の連続配信期間を挿入します。ポストロールの場合は、すべてのコンテンツ期間の後にポストロール広告連続配信の期間を挿入します。コンテンツ MPD の期間を反復処理し、処理されたすべてのコンテンツ期間の経過時間を記録します。連続配信広告の開始時間に対応する期間の境界に達したら、その境界に一致するミッドロール広告の MPD ファイルの期間を挿入します。

最終的なステッチされた MPD ファイルは MPEG_DASH 仕様に完全に準拠している必要があります。そのため、最終的なファイルをもう一度反復処理して、期間の開始時間を修正し、新しく挿入された広告期間を考慮してメディア プレゼンテーションの時間を修正し、ステッチ プロセスで発生した可能性のある他の競合を解決することが必要になる場合があります。

コンテンツ MPD の例

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

広告連続配信の JSON の例

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

広告連続配信の MPD の例

上記の広告連続配信の JSON の mpd_uri の内容は次のとおりです。

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

連結 MPD の例

これを最初のストリーム マニフェスト リクエストに対するレスポンスとして提供します。

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

参考情報