概要
IMA DAI SDK は、Web ページやアプリに依存することなく、動画コンテンツと広告を単一のストリームに結合し、SDK から広告リクエストおよび広告レスポンスの処理を排除します。これにより、クライアントサイドでのエラー発生の可能性が低減され、コンテンツと広告の間に遅延やバッファリングのない、シームレスでテレビのような視聴体験を実現します。
IMA DAI SDK を使用すると、ライブのリニア配信やオンデマンド動画に対して個別の広告をターゲティングでき、幅広いデバイスサポートによるマルチスクリーンでのリーチを実現できます。また、Ad Exchange for Video を活用し、すべてのデバイスでプログラマティックなマネタイズを行うことができます。
コンテンツの元の形式に関係なく、デジタル化されると、DAI はそのコンテンツを視聴している個々のユーザーに基づいて、カスタムでターゲティングされた動画広告をストリームに挿入できます。
これにより、バッファリングや遅延が最小限に抑えられ、広告が適切な形式でレンダリングされるため、視聴者は期待どおりの放送品質の体験を得ることができます。
要件
- Ad Manager 360 Advanced アカウントを保有していること。
特長
- シームレスで放送品質に近い視聴体験を提供します。
- 広告がどのネットワークでホストされているかに関係なく、Ad Manager サーバー上でストリームが結合されます。
Players モジュール - プラグイン セクションを使用した実装
DAI プラグインの追加
- PLAYERS モジュールを開き、新しいプレーヤーを作成するか、プラグインを追加したい既存のプレーヤーを選択します。
- プレーヤー名をクリックして、プレーヤーのプロパティを開きます。
- 左側のナビゲーションメニューで プラグイン をクリックします。
-
プラグインの追加 ドロップダウンから カスタム プラグイン を選択します。
- プラグイン名 には
imaDaiと入力します。 - JavaScript URL には次を入力します。
https://players.brightcove.net/videojs-ima-dai/1/videojs-ima-dai.min.js - CSS には次を入力します。
https://players.brightcove.net/videojs-ima-dai/1/videojs-ima-dai.css - 保存 をクリックします。
- プレーヤーを公開するには、公開と埋め込み > 変更の公開 をクリックします。
- 開いているダイアログを閉じるには、閉じる をクリックします。
コードを使用した実装
IMA DAI プラグインを初期化するには、次の手順に従ってください。
IMA DAI プラグインのクラスを取得します。
const ImaDaiPlugin = videojs.getPlugin('imaDai');bc プレーヤーを初期化します。
const videoId = 'ima-dai-player'; const player = bc(videoId);IMA DAI プラグインを初期化します。
const imaDai = player.imaDai();IMA_DAI_SDK_LOADEDイベントをリッスンします。imaDai.one(ImaDaiPlugin.EVENTS.IMA_DAI_SDK_LOADED, ({ imaDaiSdk }) => { // IMA DAI SDK が使用可能になり、ストリームリクエストを送信できます。 });StreamRequest インスタンスを作成します。
streamRequestには、LiveStreamRequest、VODStreamRequest、PodStreamRequestのいずれかのクラスを使用します。const streamRequest = new VODStreamRequest();フォールバック ストリームを指定します。フォールバックは、すべての IMA DAI ストリーム リクエストに必須です。IMA DAI SDK がストリームを取得できなかった場合、プレーヤーはこのフォールバック ストリームを使用します。
const fallback = { type: 'your-fallback-type', src: 'your-fallback-src' };プレーヤーのソースを設定します。
player.src({ type: fallback.type, src: fallback.src, imaDai: { streamRequest } });VOD ストリーム リクエスト:
// ... imaDai.one(ImaDaiPlugin.EVENTS.IMA_DAI_SDK_LOADED, ({ imaDaiSdk }) => { const { VODStreamRequest } = imaDaiSdk; const streamRequest = new VODStreamRequest(); streamRequest.videoId = 'tears-of-steel'; streamRequest.contentSourceId = '2528370'; const fallback = { type: 'application/x-mpegURL', src: 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8' }; player.src({ type: fallback.type, src: fallback.src, imaDai: { streamRequest } }); }); // ...ライブストリーム リクエスト:
// ... imaDai.one(ImaDaiPlugin.EVENTS.IMA_DAI_SDK_LOADED, ({ imaDaiSdk }) => { const { LiveStreamRequest } = imaDaiSdk; const streamRequest = new LiveStreamRequest(); streamRequest.assetKey = 'c-rArva4ShKVIAkNfy6HUQ'; const fallback = { type: 'application/x-mpegURL', src: 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8' }; player.src({ type: fallback.type, src: fallback.src, imaDai: { streamRequest } }); }); // ...Pod 配信ストリーム リクエスト:
// ... imaDai.one(ImaDaiPlugin.EVENTS.IMA_DAI_SDK_LOADED, ({ imaDaiSdk }) => { const { PodStreamRequest } = imaDaiSdk; const streamRequest = new PodStreamRequest(); streamRequest.networkCode = '51636543'; streamRequest.customAssetKey = 'google-sample'; streamRequest.apiKey = ''; // Pod ストリーム リクエストには podSourceResolver が必要です const podStreamUrl = 'https://encodersim.sandbox.google.com/masterPlaylist/9c654d63-5373-4673-8c8d-6d92b66b9d46/master.m3u8?gen-seg-redirect=true&network=51636543&event=google-sample&pids=devrel4628000,devrel896000,devrel3528000,devrel1428000,devrel2628000,devrel1928000&seg-host=dai.google.com&stream_id=[[STREAMID]]'; const podSourceResolver = (streamId) => { const src = podStreamUrl.replace('[[STREAMID]]', streamId); const type = 'application/x-mpegURL'; return { src, type }; }; const fallback = { type: 'application/x-mpegURL', src: 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8' }; player.src({ type: fallback.type, src: fallback.src, imaDai: { streamRequest, podSourceResolver } }); }); // ...
最終コード
const ImaDaiPlugin = videojs.getPlugin('imaDai');
const videoId = 'ima-dai-player';
const player = bc(videoId);
const imaDai = player.imaDai();
imaDai.one(ImaDaiPlugin.EVENTS.IMA_DAI_SDK_LOADED, ({ imaDaiSdk }) => {
const streamRequest = new VODStreamRequest();
const fallback = { type: 'your-fallback-type', src: 'your-fallback-src' };
player.src({
type: fallback.type,
src: fallback.src,
imaDai: { streamRequest }
});
});
ストリーム リクエストの例:
Open Measurement
HTML5 用 IMA SDK には、サードパーティによる視認性測定および検証を可能にするため、Interactive Advertising Bureau(IAB)によって策定された業界標準である Open Measurement(OM)SDK が含まれています。HTML5 用 IMA SDK を使用すると、同梱されている OM SDK が VAST 広告タグ内のタグを自動的に解析し、OMID API を介して指定された測定ベンダーに視認性データを送信します。各リクエストごとにアクセスモードのルールを任意で設定し、検証スクリプトがアクセスできるコンテンツを制御することも可能です。詳細はこちら
アクセスモード Open Measurement SDK は、検証スクリプトを異なるアクセスモードで実行することをサポートしており、これにより検証スクリプトがどこまでアクセスできるかを制御できます。4 つのアクセスモードは次のとおりです。
FULL: 検証スクリプトは、クリエイティブおよびパブリッシャーページの両方に直接アクセスできます。CREATIVE: 検証スクリプトおよびクリエイティブはパブリッシャーページからサンドボックス化されますが、スクリプトはクリエイティブに直接アクセスできます。DOMAIN: 検証スクリプトはサンドボックス化され、クリエイティブやパブリッシャーページにはアクセスできませんが、どのパブリッシャー ドメイン上で実行されているかを直接確認できる形で読み込まれます。LIMITED: 検証スクリプトはサンドボックス化され、クリエイティブやパブリッシャー ページにアクセスできず、どのパブリッシャー ドメイン上で実行されているかも直接確認できません。
以下は、異なる検証スクリプト プロバイダーに対して、リクエストごとにアクセスモードのルールを設定する例です。
// ...
imaDai.one(ImaDaiPlugin.EVENTS.IMA_DAI_SDK_LOADED, ({ imaDaiSdk }) => {
const { LiveStreamRequest } = imaDaiSdk;
const streamRequest = new LiveStreamRequest();
streamRequest.assetKey = 'c-rArva4ShKVIAkNfy6HUQ';
streamRequest.omidAccessModeRules = {};
// Google に対してフルアクセスモードを設定:
streamRequest.omidAccessModeRules[google.ima.OmidVerificationVendor.GOOGLE] = google.ima.OmidAccessMode.FULL;
// その他の検証スクリプト プロバイダーに対してドメイン アクセスモードを設定:
streamRequest.omidAccessModeRules[google.ima.OmidVerificationVendor.OTHER] = google.ima.OmidAccessMode.DOMAIN;
const fallback = {
type: 'application/x-mpegURL',
src: 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8'
};
player.src({
type: fallback.type,
src: fallback.src,
imaDai: { streamRequest }
});
});
// ...
プライバシー
CCPA
カリフォルニア州消費者プライバシー法(CCPA)への対応を支援するため、Google Interactive Media Ads SDK では、制限付きデータ処理(RDP)を有効にするかどうかを示すための 2 種類のパラメーターを使用できます。この SDK では、以下のパラメーターを使用して、広告リクエスト単位で RDP を設定することが可能です。
- RDP シグナル
- IAB シグナル
RDP シグナル
Google のシグナルを使用して RDP を有効にすることを Google に通知するには、次の例のように広告タグのパラメーターに rdp=1 を追加します。
// ...
imaDai.one(ImaDaiPlugin.EVENTS.IMA_DAI_SDK_LOADED, ({ imaDaiSdk }) => {
const { LiveStreamRequest } = imaDaiSdk;
const streamRequest = new LiveStreamRequest();
streamRequest.assetKey = 'c-rArva4ShKVIAkNfy6HUQ';
// RDP シグナル:
streamRequest.adTagParameters = {"rdp": 1};
const fallback = {
type: 'application/x-mpegURL',
src: 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8'
};
player.src({
type: fallback.type,
src: fallback.src,
imaDai: { streamRequest }
});
});
// ...
IAB シグナル
IAB のシグナルを使用して RDP を有効にすることを Google に通知するには、広告タグパラメーター us_privacy を使用します。以下のスニペットは、IAB パラメーター "1YNN" を使用して広告リクエストを作成する方法を示しています。
// ...
imaDai.one(ImaDaiPlugin.EVENTS.IMA_DAI_SDK_LOADED, ({ imaDaiSdk }) => {
const { LiveStreamRequest } = imaDaiSdk;
const streamRequest = new LiveStreamRequest();
streamRequest.assetKey = 'c-rArva4ShKVIAkNfy6HUQ';
// IAB シグナル:
streamRequest.adTagParameters = {"us_privacy": "1YNN"};
const fallback = {
type: 'application/x-mpegURL',
src: 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8'
};
player.src({
type: fallback.type,
src: fallback.src,
imaDai: { streamRequest }
});
});
// ...
GDPR
Google の更新された EU ユーザー同意ポリシーに基づき、欧州経済領域(EEA)のユーザーに対しては、法的に必要な場合に Cookie やその他のローカル ストレージの使用について開示し、広告のパーソナライズを目的とした個人データの収集、共有、利用について同意を取得する必要があります。このポリシーは、EU ePrivacy 指令および一般データ保護規則(GDPR)の要件を反映しています。詳細はこちら。
非パーソナライズド広告を強制する
非パーソナライズド広告コンテンツのみを配信するよう指定するには、広告タグに npa=1 を追加します。
// ...
imaDai.one(ImaDaiPlugin.EVENTS.IMA_DAI_SDK_LOADED, ({ imaDaiSdk }) => {
const { LiveStreamRequest } = imaDaiSdk;
const streamRequest = new LiveStreamRequest();
streamRequest.assetKey = 'c-rArva4ShKVIAkNfy6HUQ';
// 非パーソナライズド広告を強制:
streamRequest.adTagParameters = {"npa": 1};
const fallback = {
type: 'application/x-mpegURL',
src: 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8'
};
player.src({
type: fallback.type,
src: fallback.src,
imaDai: { streamRequest }
});
});
// ...
同意年齢未満のユーザーとしてタグ付けする
このパラメーターは、リマーケティングを含むパーソナライズド広告を、その広告リクエストに対して無効にします。また、広告測定ピクセルやサードパーティ広告サーバーなど、第三者広告ベンダーへのリクエストも無効にします。このタグを実装から送信されるすべての広告リクエストに含めるには、広告タグに tfua=1 を追加します。
// ...
imaDai.one(ImaDaiPlugin.EVENTS.IMA_DAI_SDK_LOADED, ({ imaDaiSdk }) => {
const { LiveStreamRequest } = imaDaiSdk;
const streamRequest = new LiveStreamRequest();
streamRequest.assetKey = 'c-rArva4ShKVIAkNfy6HUQ';
// 同意年齢未満のユーザーとしてタグ付け:
streamRequest.adTagParameters = {"tfua": 1};
const fallback = {
type: 'application/x-mpegURL',
src: 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8'
};
player.src({
type: fallback.type,
src: fallback.src,
imaDai: { streamRequest }
});
});
// ...
主要な概念
ストリーム時間と相対時間
サーバーサイド広告挿入(SSAI)を使用する場合、広告とコンテンツは単一のストリームとして結合されます。
ストリームが 1 つしか存在しないため、時間を把握するための仕組みが必要になります。
- ストリーム時間(または絶対時間): ストリーム全体における時間を指します。
- 相対時間: 現在再生されているもの(広告またはコンテンツ)に依存します。
- 広告を再生している場合、相対時間はその広告内での時間になります。
- コンテンツを再生している場合、相対時間はコンテンツ内での時間になります。
例:
この 70 秒のストリームでは、広告が最大 30 秒、コンテンツが最大 40 秒を占めています。
- 絶対時間 の長さ = 70 秒
- 相対時間 の長さ(コンテンツ) = 40 秒
- 相対時間 の長さ(各広告) = 各広告の個別の長さ(10 秒、5 秒など)
スナップバック
スナップバックとは、ユーザーがシーク操作で広告ブレークを飛ばした場合に、その広告ブレークの先頭にユーザーを戻し、広告ブレークの再生終了後に元のシーク位置へ戻す機能です。詳細はこちら。
オプション
| オプション | 説明 | デフォルト値 |
|---|---|---|
debug |
true の場合、デバッグ メッセージを有効にし、追加の情報をログに出力します。 | false |
sdkUrl |
セルフ ホストされた IMA DAI SDK の URL です。 | //imasdk.googleapis.com/js/sdkloader/ima3_dai.js |
hideOverlays |
true の場合、広告再生中にオーバーレイを非表示にします。 | false |
静的メンバー
| メンバー | 説明 | 型 | 使用例 |
|---|---|---|---|
DEFAULTS |
利用可能なプラグイン オプションと、それぞれのデフォルト値を含むオブジェクトです。 | Record<string, any> |
console.log(ImaDaiPlugin.DEFAULTS); |
VERSION |
現在のプラグインのバージョンです。 | string |
console.log(ImaDaiPlugin.VERSION); |
EVENTS |
利用可能なプラグイン イベントをまとめたオブジェクトです。 | Record<string, string> |
console.log(ImaDaiPlugin.EVENTS); |
SOURCE_TYPES |
利用可能なプラグインのソースタイプをまとめたオブジェクトです。 | Record<string, string> |
console.log(ImaDaiPlugin.SOURCE_TYPES); |
インスタンス ゲッター
| ゲッター | 説明 | 型 | 使用例 |
|---|---|---|---|
options |
IMA DAI プラグイン インスタンスにおける現在のオプションを取得します。 | Options |
console.log(imaDai.options); |
isImaDaiStream |
IMA DAI ストリームが再生中かどうかを確認します。再生中の場合は true、それ以外の場合は false を返します。 | boolean |
console.log(imaDai.isImaDaiStream); |
contentDuration |
コンテンツの再生時間(広告を除く)を取得します。 | number |
console.log(imaDai.contentDuration); |
relativeDuration |
広告再生中の場合は現在の広告の長さを、それ以外の場合は広告を除いたコンテンツの長さを取得します。 | number |
console.log(imaDai.relativeDuration); |
canSeekNow |
現在シーク操作が可能かどうかを確認します。 | boolean |
console.log(imaDai.canSeekNow); |
relativeCurrentTime |
広告再生中の場合は現在の広告内の再生位置を、それ以外の場合は広告を除いたコンテンツの現在時刻を取得します。 | number |
console.log(imaDai.relativeCurrentTime); |
totalAdsDuration |
認識されているすべての広告の合計再生時間を取得します(VOD のみ適用されます)。 | number |
console.log(imaDai.totalAdsDuration); |
インスタンス メソッド
| メソッド | 説明 | 型 | 使用例 |
|---|---|---|---|
updateOptions |
プラグインのオプションを更新します。 | (receivedOptions: Record<string, any>) => void |
imaDai.updateOptions({}); |
streamTimeForContentTime |
指定したコンテンツ時間を、広告を含むストリーム時間に変換します。 | (contentTime: number) => number |
console.log(imaDai.streamTimeForContentTime(contentTime)); |
contentTimeForStreamTime |
指定したストリーム時間を、広告を除いたコンテンツ時間に変換します。 | (streamTime: number) => number |
console.log(imaDai.contentTimeForStreamTime(streamTime)); |
replaceAdTagParameters |
ライブストリームにおける、今後の広告リクエストで使用されるすべての広告タグパラメーターを置き換えます。 | (adTagParameters: Object|null) => void/code> |
imaDai.replaceAdTagParameters(new_adTagParameters) |
イベント
| イベント | 説明 | 値 | 使用例 |
|---|---|---|---|
IMA_DAI_SDK_LOADED |
IMA DAI SDK の読み込みが完了したときに発火するイベントです。 | 'imaDai:imaDaiSdkLoaded' |
imaDai.on(ImaDaiPlugin.EVENTS.IMA_DAI_SDK_LOADED, ({ imaDaiSdk }) => { ... }); |