IMA DAI SDK スタートガイド

IMA SDK を使用すると、マルチメディア広告をウェブサイトやアプリに簡単に統合できます。IMA SDK は、 VAST 準拠の任意の広告サーバーから広告をリクエストし、アプリ内の広告再生を管理できます。IMA DAI SDK を使用すると、アプリは広告とコンテンツ動画(VOD またはライブ コンテンツ)のストリーム リクエストを行います。SDK は統合された動画ストリームを返すため、アプリ内で広告動画とコンテンツ動画の切り替えを管理する必要はありません。

関心のある DAI ソリューションを選択する

フルサービス DAI

このガイドでは、IMA DAI SDK をシンプルな動画プレーヤー アプリに統合する方法について説明します。統合済みのサンプルを表示または確認するには、GitHub から BasicExample をダウンロードしてください。

IMA DAI の概要

IMA DAI の実装には、このガイドで説明するように、3 つの主要な SDK コンポーネントが関与します。

  • IMAAdDisplayContainer: 動画再生要素の上に配置され、広告 UI 要素を格納するコンテナ オブジェクト。
  • IMAAdsLoader: ストリームをリクエストし、ストリーム リクエスト レスポンス オブジェクトによってトリガーされたイベントを処理するオブジェクト。インスタンス化すべき広告ローダは 1 つだけです。この広告ローダは、アプリの存続期間中ずっと再利用できます。
  • IMAStreamRequest - IMAVODStreamRequest または IMALiveStreamRequest: ストリーム リクエストを定義するオブジェクト。ストリーム リクエストは、ビデオ オンデマンドまたはライブ配信のいずれかです。リクエストでは、コンテンツ ID のほか、API キーまたは認証トークンなどのパラメータを指定します。
  • IMAStreamManager: ダイナミック広告挿入ストリームと DAI バックエンドとのインタラクションを処理するオブジェクト。ストリーム マネージャーは、トラッキング ピングも処理し、ストリーム イベントと広告イベントをパブリッシャーに転送します。

前提条件

始める前に、次のものが必要になります。

  • Xcode 13 以降
  • CocoaPods(推奨)、Swift パッケージ マネージャー、または tvOS 用 IMA DAI SDK のダウンロード コピー

新しい Xcode プロジェクトを作成する

Xcode で、Objective-C を使用して新しい tvOS プロジェクトを作成します。プロジェクト名には BasicExample を使用します。

IMA DAI SDK を Xcode プロジェクトに追加する

次の 3 つの方法のいずれかを使用して IMA DAI SDK をインストールします。

CocoaPods を使用して SDK をインストールする(推奨)

CocoaPods は Xcode プロジェクトの依存関係マネージャーであり、IMA DAI SDK のインストールに推奨される方法です。CocoaPods のインストールまたは使用の詳細については、CocoaPods のドキュメントをご覧ください。CocoaPods をインストールしたら、次の手順で IMA DAI SDK をインストールします。

  1. BasicExample.xcodeproj ファイルと同じディレクトリに Podfile というテキスト ファイルを作成し、次の構成を追加します。

    source 'https://github.com/CocoaPods/Specs.git'
    platform :tvos, '14'
    target "BasicExample" do
      pod 'GoogleAds-IMA-tvOS-SDK', '~> 4.13.0'
    end
    
  2. Podfile が含まれているディレクトリから、次のコマンドを実行します。

    pod install --repo-update`
  3. BasicExample.xcworkspace ファイルを開き、BasicExamplePods(CocoaPods によってインストールされた依存関係)の 2 つのプロジェクトが含まれていることを確認して、インストールが正常に完了したことを確認します。

Swift Package Manager を使用して SDK をインストールする

Interactive Media Ads SDK はバージョン 4.8.2 から Swift Package Manager に対応しています。Swift パッケージをインポートする手順は次のとおりです。

  1. Xcode で [File] > [Add Packages] を開き、GoogleInteractiveMediaAds の Swift パッケージをインストールします。

  2. 表示されたプロンプトで、GoogleInteractiveMediaAds Swift パッケージの GitHub リポジトリ(下記)を検索します。

    https://github.com/googleads/swift-package-manager-google-interactive-media-ads-tvos
    
  3. 使用する GoogleInteractiveMediaAds Swift パッケージのバージョンを選択します。新しいプロジェクトの場合は [Up to Next Major Version] を選択することをおすすめします。

完了すると、Xcode はパッケージの依存関係を解決し、バックグラウンドでダウンロードします。パッケージの依存関係の追加について詳しくは、Apple の記事を参照してください。

SDK を手動でダウンロードしてインストールする

Swift Package Manager または CocoaPods を使用しない場合は、IMA DAI SDK をダウンロードして、プロジェクトに手動で追加できます。

シンプルな動画プレーヤーを作成する

まず、基本的な動画プレーヤーを実装します。最初、このプレーヤーは IMA DAI SDK を使用しません。また、再生をトリガーするメソッドも含まれていません。

ViewController.m

#import "ViewController.h"

#import <AVKit/AVKit.h>

@interface ViewController ()
@property(nonatomic) AVPlayerViewController *playerViewController;
@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.view.backgroundColor = [UIColor blackColor];

  // Create a stream video player.
  AVPlayer *player = [[AVPlayer alloc] init];
  self.playerViewController = [[AVPlayerViewController alloc] init];
  self.playerViewController.player = player;

  // Attach the video player to the view hierarchy.
  [self addChildViewController:self.playerViewController];
  self.playerViewController.view.frame = self.view.bounds;
  [self.view addSubview:self.playerViewController.view];
  [self.playerViewController didMoveToParentViewController:self];
}

@end

SDK をインポートして IMA インタラクションのスタブを追加する

IMA DAI SDK をプロジェクトに追加したら、SDK をインポートし、IMA インタラクションの主要なポイントのスタブを追加します。

ViewController.m

#import "ViewController.h"

#import <AVKit/AVKit.h>
#import <GoogleInteractiveMediaAds/GoogleInteractiveMediaAds.h>

@interface ViewController ()
@property(nonatomic) IMAAdsLoader *adsLoader;
@property(nonatomic) UIView *adContainerView;
@property(nonatomic) IMAStreamManager *streamManager;
@property(nonatomic) AVPlayerViewController *playerViewController;
@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.view.backgroundColor = [UIColor blackColor];

  [self setupAdsLoader];

  // Create a stream video player.
  AVPlayer *player = [[AVPlayer alloc] init];
  self.playerViewController = [[AVPlayerViewController alloc] init];
  self.playerViewController.player = player;

  // Attach the video player to the view hierarchy.
  [self addChildViewController:self.playerViewController];
  self.playerViewController.view.frame = self.view.bounds;
  [self.view addSubview:self.playerViewController.view];
  [self.playerViewController didMoveToParentViewController:self];

  [self attachAdContainer];
}

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  [self requestStream];
}

- (void)setupAdsLoader {}

- (void)attachAdContainer {}

- (void)requestStream {}

@end

IMAAdsLoader を実装する

次に、IMAAdsLoader をインスタンス化し、広告コンテナ ビューをビュー階層に接続します。

ViewController.m

- (void)setupAdsLoader {
  self.adsLoader = [[IMAAdsLoader alloc] init];
  self.adsLoader.delegate = self;
}

- (void)attachAdContainer {
  self.adContainerView = [[UIView alloc] init];
  [self.view addSubview:self.adContainerView];
  self.adContainerView.frame = self.view.bounds;
}

ストリーム リクエストを行う

ストリーム情報を保持する定数をいくつか作成し、ストリーム リクエスト関数を実装してリクエストを行います。

ViewController.m

#import <GoogleInteractiveMediaAds/GoogleInteractiveMediaAds.h>

static NSString *const kAssetKey = @"sN_IYUG8STe1ZzhIIE_ksA";
static NSString *const kContentSourceID = @"2548831";
static NSString *const kVideoID = @"tears-of-steel";

@interface ViewController ()
...

- (void)requestStream {
  IMAAVPlayerVideoDisplay *videoDisplay =
      [[IMAAVPlayerVideoDisplay alloc] initWithAVPlayer:self.playerViewController.player];
  IMAAdDisplayContainer *adDisplayContainer =
      [[IMAAdDisplayContainer alloc] initWithAdContainer:self.adContainerView];
  IMALiveStreamRequest *request = [[IMALiveStreamRequest alloc] initWithAssetKey:kAssetKey
                                                              adDisplayContainer:adDisplayContainer
                                                                    videoDisplay:videoDisplay];
  // VOD request. Comment out the IMALiveStreamRequest above and uncomment this IMAVODStreamRequest
  // to switch from a livestream to a VOD stream.
  // IMAVODStreamRequest *request =
  //     [[IMAVODStreamRequest alloc] initWithContentSourceId:kContentSourceID
  //                                                  videoId:kVideoID
  //                                       adDisplayContainer:adDisplayContainer
  //                                             videoDisplay:videoDisplay];
  [self.adsLoader requestStreamWithRequest:request];
}

ストリーム イベントを処理する

IMAAdsLoaderIMAStreamManager は、初期化、エラー、ストリーム状態の変化を処理するために使用されるイベントです。これらのイベントは、IMAAdsLoaderDelegate プロトコルと IMAStreamManagerDelegate プロトコルを介して発生します。広告読み込みイベントをリッスンして、ストリームを初期化します。広告の読み込みに失敗した場合は、代わりにバックアップ ストリームを再生します。

ViewController.m

static NSString *const kAssetKey = @"sN_IYUG8STe1ZzhIIE_ksA";
static NSString *const kContentSourceID = @"2548831";
static NSString *const kVideoID = @"tears-of-steel";
static NSString *const kBackupStreamURLString =
    @"https://storage.googleapis.com/interactive-media-ads/media/bbb.m3u8";

@interface ViewController () <IMAAdsLoaderDelegate, IMAStreamManagerDelegate>

...
  [self.adsLoader requestStreamWithRequest:request];
}

- (void)playBackupStream {
  NSURL *backupStreamURL = [NSURL URLWithString:kBackupStreamURLString];
  AVPlayerItem *backupStreamItem = [AVPlayerItem playerItemWithURL:backupStreamURL];
  [self.playerViewController.player replaceCurrentItemWithPlayerItem:backupStreamItem];
  [self.playerViewController.player play];
}

#pragma mark - IMAAdsLoaderDelegate

- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
  // Initialize and listen to stream manager's events.
  self.streamManager = adsLoadedData.streamManager;
  self.streamManager.delegate = self;
  [self.streamManager initializeWithAdsRenderingSettings:nil];
  NSLog(@"Stream created with: %@.", self.streamManager.streamId);
}

- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
  // Fall back to playing the backup stream.
  NSLog(@"Error loading ads: %@", adErrorData.adError.message);
  [self playBackupStream];
}

#pragma mark - IMAStreamManagerDelegate

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdEvent:(IMAAdEvent *)event {}

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdError:(IMAAdError *)error {}

- (void)streamManager:(IMAStreamManager *)streamManager
  adDidProgressToTime:(NSTimeInterval)time
           adDuration:(NSTimeInterval)adDuration
           adPosition:(NSInteger)adPosition
             totalAds:(NSInteger)totalAds
      adBreakDuration:(NSTimeInterval)adBreakDuration {}

@end

ロギング イベントとエラーイベントを処理する

ストリーム マネージャー デリゲートで処理できるイベントはいくつかありますが、基本的な実装では、イベント ロギングを実行すること、広告の再生中にシーク操作を防止すること、エラーを処理することが最も重要です。

ViewController.m

#pragma mark - IMAStreamManagerDelegate

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdEvent:(IMAAdEvent *)event {
  NSLog(@"StreamManager event (%@).", event.typeString);
  switch (event.type) {
    case kIMAAdEvent_STARTED: {
      // Log extended data.
      NSString *extendedAdPodInfo = [[NSString alloc]
          initWithFormat:@"Showing ad %zd/%zd, bumper: %@, title: %@, description: %@, contentType:"
                         @"%@, pod index: %zd, time offset: %lf, max duration: %lf.",
                         event.ad.adPodInfo.adPosition, event.ad.adPodInfo.totalAds,
                         event.ad.adPodInfo.isBumper ? @"YES" : @"NO", event.ad.adTitle,
                         event.ad.adDescription, event.ad.contentType, event.ad.adPodInfo.podIndex,
                         event.ad.adPodInfo.timeOffset, event.ad.adPodInfo.maxDuration];

      NSLog(@"%@", extendedAdPodInfo);
      break;
    }
    case kIMAAdEvent_AD_BREAK_STARTED: {
      // Prevent user seek through when an ad starts and show the ad controls.
      self.adContainerView.hidden = NO;
      break;
    }
    case kIMAAdEvent_AD_BREAK_ENDED: {
      // Allow user seek through after an ad ends and hide the ad controls.
      self.adContainerView.hidden = YES;
      break;
    }
    default:
      break;
  }
}

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdError:(IMAAdError *)error {
  // Fall back to playing the backup stream.
  NSLog(@"StreamManager error: %@", error.message);
  [self playBackupStream];
}

@end

これで、これで、IMA DAI SDK を使用して広告をリクエストして表示できるようになりました。SDK の高度な機能については、他のガイドまたは GitHub のサンプルをご覧ください。