Overview
The Brightcove SDK offers a plugin to interact with the Google IMA-DAI library for multimedia ads playback in your application, and abstracts the setup and basic interaction with the Google IMA-DAI library so you can focus on requesting video streams.
The recommended way to add the DAI plugin to your project is the Swift Package Manager. CocoaPods is also supported, but is deprecated.
Cocoapods Implementation (deprecated)
You can use CocoaPods to add the DAI Plugin for Brightcove Player SDK to your project. You can find the latest Brightcove-Player-DAI podspec here. The pod incorporates the correct version of IMA automatically.
CocoaPod podfile snippet:
source 'https://github.com/CocoaPods/Specs'
source 'https://github.com/brightcove/BrightcoveSpecs.git'
platform :ios, '14.0'
use_frameworks!
target 'MyDAIPlayer' do
pod 'Brightcove-Player-DAI'
end
Manual Implementation
The SDK and plugin downloads contain dynamic XCFrameworks. The legacy universal framework and its strip-frameworks.sh run script were removed in SDK 7.2.13, so do not add either one.
- Download the Brightcove Player SDK for iOS, the DAI plugin, and the Google IMA SDK.
- On the General tab of your application target, add
BrightcovePlayerSDK.xcframework,BrightcoveDAI.xcframework, andGoogleInteractiveMediaAds.xcframeworkto Frameworks, Libraries, and Embedded Content. - Set Embed & Sign for all three XCFrameworks.
- On the Build Settings tab, ensure that Framework Search Paths include the directories that contain the XCFrameworks. Xcode normally does this when the frameworks are inside the project directory.
- Add
-ObjCto Other Linker Flags.
Swift Package Manager Implementation
Add the DAI Plugin for Brightcove Player SDK to your project with Swift Package Manager following these steps:
- Add the unified Brightcove Swift Package.
- Select the "Package Dependencies" tab for your Project
- Click the "+" button
In the "Search or Enter Package URL" field enter:
https://github.com/brightcove/brightcove-player-sdk-ios- When the UI updates click the "Add Package" button
- After Xcode processes the repo you are prompted to "Choose Package Products"
- Select the
BrightcoveDAIproduct (this automatically includes the Core SDK, so you do not need to add Core separately), ensure that your app target is selected, and click the "Add Package" button.
The Brightcove Swift Package resolves the matching Google IMA SDK automatically; you do not need to add it separately.
Quick Start
Create the player view, the DAI playback controller and the Playback Service request in one view controller. Replace the account, policy key and video ID values with your own.
BCOVDAIAdsRequestPolicy provides methods to specify DAI streams for VOD and live. The example uses videoPropertiesAdsRequestPolicy. BrightcoveDAI adds the createDAIPlaybackControllerWithSettings:adsRenderingSettings:adsRequestPolicy:adContainer:viewController:companionSlots:viewStrategy: method to BCOVPlayerSDKManager.
@import UIKit;
@import BrightcovePlayerSDK;
@import BrightcoveDAI;
@import GoogleInteractiveMediaAds;
@interface DAIViewController : UIViewController <BCOVPlaybackControllerDelegate>
@property (nonatomic, strong) id<BCOVPlaybackController> playbackController;
@property (nonatomic, strong) BCOVPlaybackService *playbackService;
@property (nonatomic, strong) BCOVPUIPlayerView *playerView;
@end
@implementation DAIViewController
- (void)viewDidLoad
{
[super viewDidLoad];
BCOVPUIPlayerViewOptions *options = [BCOVPUIPlayerViewOptions new];
options.presentingViewController = self;
options.automaticControlTypeSelection = YES;
self.playerView = [[BCOVPUIPlayerView alloc] initWithPlaybackController:nil
options:options
controlsView:nil];
self.playerView.frame = self.view.bounds;
self.playerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:self.playerView];
IMASettings *settings = [IMASettings new];
IMAAdsRenderingSettings *renderingSettings = [IMAAdsRenderingSettings new];
BCOVDAIAdsRequestPolicy *policy = [BCOVDAIAdsRequestPolicy videoPropertiesAdsRequestPolicy];
self.playbackController = [[BCOVPlayerSDKManager sharedManager]
createDAIPlaybackControllerWithSettings:settings
adsRenderingSettings:renderingSettings
adsRequestPolicy:policy
adContainer:self.playerView.contentOverlayView
viewController:self
companionSlots:nil
viewStrategy:nil];
self.playbackController.delegate = self;
self.playbackController.autoAdvance = YES;
self.playbackController.autoPlay = YES;
self.playerView.playbackController = self.playbackController;
self.playbackService = [[BCOVPlaybackService alloc] initWithAccountId:@"YOUR_ACCOUNT_ID"
policyKey:@"YOUR_POLICY_KEY"];
NSDictionary *configuration = @{ BCOVPlaybackService.ConfigurationKeyAssetID: @"YOUR_VIDEO_ID" };
__weak DAIViewController *weakSelf = self;
[self.playbackService findVideoWithConfiguration:configuration
queryParameters:nil
completion:^(BCOVVideo *video, id jsonResponse, NSError *error) {
if (!video) {
NSLog(@"Error retrieving video: %@", error);
return;
}
[weakSelf.playbackController setVideos:@[video]];
}];
}
@end
Play and Pause
The Brightcove DAI Plugin implements custom play and pause. Use the play method on the BCOVPlaybackController or the -[BCOVSessionProviderExtension dai_play] or -[BCOVSessionProviderExtension dai_pause] (BCOVSessionProviderExtension), and not the AVPlayer.
Using the Built-In PlayerUI
-
In your
UIViewController, create aBCOVPUIPlayerViewproperty called the player view, to contain the playback controls, the video content view, and a special view where DAI can display its ads// PlayerUI's player view @property (nonatomic) BCOVPUIPlayerView *playerView; Create your player view
Supply a nil playback controller. This player view contains both the video content view and the view that displays playback controls and ad controls. Set up the player view to match the video container from your layout ( videoView ) when it resizes
// Create and configure Control View. BCOVPUIBasicControlView *controlView = [BCOVPUIBasicControlView basicControlViewWithVODLayout]; // Create the player view with a nil playback controller. self.playerView = [[BCOVPUIPlayerView alloc] initWithPlaybackController:nil options:nil controlsView:controlView]; // Add BCOVPUIPlayerView to your video view. [self.videoView addSubview:self.playerView];Set up the layout for the player view
Do this with Auto Layout or the older Springs & Struts method.
Springs & Struts
self.playerView.frame = self.videoView.bounds; self.playerView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;Auto Layout
self.playerView.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ [self.playerView.topAnchor constraintEqualToAnchor:self.videoView.topAnchor], [self.playerView.rightAnchor constraintEqualToAnchor:self.videoView.rightAnchor], [self.playerView.leftAnchor constraintEqualToAnchor:self.videoView.leftAnchor], [self.playerView.bottomAnchor constraintEqualToAnchor:self.videoView.bottomAnchor], ]];
Create the Content Overlay View
The
contentOverlayViewis a special view used for overlaying views on the main video content.// Create the playback controller. id<BCOVPlaybackController> controller = [manager createDAIPlaybackControllerWithSettings:imaSettings adsRenderingSettings:adsRenderingSettings adsRequestPolicy:adsRequestPolicy adContainer:playerView.contentOverlayView viewController:self companionSlots:nil viewStrategy:nil]; controller.delegate = self; // Assign new playback controller to the player view. // This associates the playerController's session with the PlayerUI. // You can keep this player view around and assign new // playback controllers to it as they are created. self.playbackController = controller; self.playerView.playbackController = controller;
Now, when playing video with ads, you will see the PlayerUI controls while playing video content, plus ad markers on the timeline scrubber.
The playerUI is highly customizable. For more info and sample code, see the Custom Layouts section in the README.md file of the Brightcove Native Player SDK repository.
Seek without Ads
For ordinary seeking, use BCOVPlaybackController's seekToTime:completionHandler: method. The DAI plugin can return playback to an unplayed ad break before continuing to the requested position, so an ordinary seek is not a way to bypass ads.
Customizing Plugin Behavior
You can combine BCOVDAI with another plugin for the Brightcove Player SDK for iOS to create a custom view strategy and supply a custom ads request policy.
Ads Request Policy for VOD and Live
BCOVDAIAdsRequestPolicy has two factory methods to generate ads request policy; one for VOD and one for Live.
Method for VOD
The method +videoPropertiesAdsRequestPolicy : returns an ads request policy which looks for the kBCOVDAIVideoPropertiesKeySourceId and kBCOVDAIVideoPropertiesKeyVideoId in each BCOVVideo's properties to determine the DAI Stream.
Method for Live
The method +videoPropertiesAssetKeyAdsRequestPolicy : returns an ads request policy that checks each BCOVVideo's properties for the key kBCOVDAIVideoPropertiesKeyAssetKey to determine the DAI Live Stream.
Add properties to a video
You can add properties to a video by using the update: method on the BCOVVideo object. The following example adds the properties needed for VOD:
// Objective-C
- (BCOVVideo *)updateVideo:(BCOVVideo *)video
{
return [video update:^(BCOVMutableVideo *mutableVideo) {
NSMutableDictionary *properties = [mutableVideo.properties mutableCopy];
properties[kBCOVDAIVideoPropertiesKeySourceId] = @"YOUR_DAI_SOURCE_ID";
properties[kBCOVDAIVideoPropertiesKeyVideoId] = @"YOUR_DAI_VIDEO_ID";
mutableVideo.properties = properties;
}];
}
// Swift
func updateVideo(_ video: BCOVVideo) -> BCOVVideo {
return video.update { mutableVideo in
var properties = mutableVideo.properties
properties[kBCOVDAIVideoPropertiesKeySourceId] = "YOUR_DAI_SOURCE_ID"
properties[kBCOVDAIVideoPropertiesKeyVideoId] = "YOUR_DAI_VIDEO_ID"
mutableVideo.properties = properties
}
}
View Strategy
With a custom view strategy, the ad container view and ad companion slots can be tied with the video content view. This is an example of custom view strategy
BCOVPlaybackControllerViewStrategy customViewStrategy =
^UIView *(UIView *view, id<BCOVPlaybackController> playbackController) {
[self.videoView addSubview:view];
return self.videoView;
};
Composing Session Providers
If you are using more than one plugin to the Brightcove Player SDK for iOS that needs to create a customized playback controller, you must compose a chain of session providers and pass the final session provider to the -[BCOVPlayerSDKManager createPlaybackControllerWithSessionProvider:viewStrategy:] method.
When composing session providers, the session preloading can be enabled from BCOVBasicSessionProvider.
Registering Ad Overlays
If you are placing any views over ads while they are playing, it is necessary to register those views with the IMA SDK. Learn more.
To get the current IMAAdDisplayContainer object necessary to register your overlays from the playbackController:playbackSession:didEnterAdSequence: delegate method of your BCOVPlaybackController instance. Follow the next example:
- (void)playbackController:(id<BCOVPlaybackController>)controller playbackSession:(id<BCOVPlaybackSession>)session
didEnterAdSequence:(BCOVAdSequence *)adSequence
{
NSDictionary *props = session.video.properties;
IMAAdDisplayContainer *adDisplayContainer = props[kBCOVDAIVideoPropertiesKeyAdDisplayContainer];
IMAFriendlyObstruction *obstruction = [[IMAFriendlyObstruction alloc]
initWithView:self.adOverlayView
purpose:IMAFriendlyObstructionPurposeMediaControls
detailedReason:@"Custom playback controls"];
[adDisplayContainer registerFriendlyObstruction:obstruction];
}
To unregister the obstructions when the ad sequence is finished, the playbackController:playbackSession:didExitAdSequence: delegate method of your BCOVPlaybackController instance. Follow the next example:
- (void)playbackController:(id<BCOVPlaybackController>)controller playbackSession:(id<BCOVPlaybackSession>)session
didExitAdSequence:(BCOVAdSequence *)adSequence
{
NSDictionary *props = session.video.properties;
IMAAdDisplayContainer *adDisplayContainer = props[kBCOVDAIVideoPropertiesKeyAdDisplayContainer];
[adDisplayContainer unregisterAllFriendlyObstructions];
}
AirPlay
To use this functionality in your apps set enableBackgroundPlayback to YES on IMASettings along with enabling AirPlay on your BCOVPlaybackController. Learn more.
AVPlayerViewController Support
Displaying Ad UI
To display your own Ad UI during ad playback you can use the playbackController:playbackSession:didReceiveLifecycleEvent: delegate method. Here is an example:
#pragma mark BCOVPlaybackControllerDelegate
- (void)playbackController:(id<BCOVPlaybackController>)controller
playbackSession:(id<BCOVPlaybackSession>)session
didReceiveLifecycleEvent:(BCOVPlaybackSessionLifecycleEvent *)lifecycleEvent
{
if (![lifecycleEvent.eventType isEqualToString:kBCOVDAILifecycleEventAdsManagerDidReceiveAdEvent])
{
return;
}
IMAAdEvent *adEvent = lifecycleEvent.properties[kBCOVDAILifecycleEventPropertyKeyAdEvent];
switch (adEvent.type)
{
case kIMAAdEvent_STARTED:
[self displayAdUI];
break;
case kIMAAdEvent_COMPLETE:
[self hideAdUI];
break;
default:
break;
}
}
Limitations
- The use of Brightcove VOD Streams are limited.
- DRM is not supported.