Brightcove provides active support for the latest iOS SDK on the latest public release of the following iOS versions:
Brightcove provides passive support for the following iOS versions:
The Core SDK is localized for Arabic (ar), English (en), French (fr), German (de), Japanese (ja), Korean (ko), Spanish (es), Simplified Chinese (zh-Hans) and Traditional Chinese (zh-Hant). To gain the benefit of a localization, your app must also be localized for the same language and locale. See the Custom Localization section for additional information.
All SDK components - the core and plugin frameworks - are released with the same version number. When upgrading any single component, upgrade all components to the same version.
For projects using Xcode 12 on Apple Silicon M1 and Universal Frameworks (.framework) a build error is returned when building the project for the arm64 simulator.
*ld: building for iOS Simulator, but linking in dylib built for iOS, file for architecture arm64*
To build for an arm64 simulator, ensure that arm64
has been added to your "Excluded Architectures" build setting for Any iOS Simulator SDK
in the "Build Settings" tab of your application target.
Release 6.10.0 of the Brightcove Player SDK adds subspecs for core and each plugin to support XCFrameworks. The default value for each subspec is /XCFramework
.
Podspec Name | Subspec Names |
---|---|
Brightcove-Player-Core | Brightcove-Player-Core/Framework Brightcove-Player-Core/XCFramework |
Brightcove-Player-DAI | Brightcove-Player-DAI/Framework Brightcove-Player-DAI/XCFramework |
Brightcove-Player-FreeWheel | Brightcove-Player-FreeWheel/Framework Brightcove-Player-FreeWheel/XCFramework |
Brightcove-Player-GoogleCast | Brightcove-Player-GoogleCast/Framework Brightcove-Player-GoogleCast/XCFramework |
Brightcove-Player-IMA | Brightcove-Player-IMA/Framework Brightcove-Player-IMA/XCFramework |
Brightcove-Player-Omniture | Brightcove-Player-Omniture/Framework Brightcove-Player-Omniture/XCFramework |
Brightcove-Player-Pulse | Brightcove-Player-Pulse/Framework Brightcove-Player-Pulse/XCFramework |
Brightcove-Player-SSAI | Brightcove-Player-SSAI/Framework Brightcove-Player-SSAI/XCFramework |
Brightcove-Player-OpenMeasurement | - |
Release 6.12.0 of the Brightcove Player SDK updates the Brightcove-Player-FreeWheel
and Brightcove-Player-Omniture
podspecs to install the dynamic version of BrightcovePlayerSDK
.
Podspec Name | Framework Type | Dependency |
---|---|---|
Brightcove-Player-Core | dynamic | - |
Brightcove-Player-DAI (available since 6.12.7) | dynamic | Brightcove-Player-Core |
Brightcove-Player-FreeWheel | dynamic | Brightcove-Player-Core for iOS, Brightcove-Player-Core for tvOS |
Brightcove-Player-GoogleCast | static | Brightcove-Player-Core |
Brightcove-Player-IMA | dynamic | Brightcove-Player-Core |
Brightcove-Player-Omniture | dynamic | Brightcove-Player-Core |
Brightcove-Player-Pulse | dynamic | Brightcove-Player-Core |
Brightcove-Player-SSAI | dynamic | Brightcove-Player-Core, Brightcove-Player-OpenMeasurement (only for Open Measurement) |
Brightcove-Player-OpenMeasurement (available since 6.10.0) | dynamic | - |
Support for FairPlay-protected videos is integrated into the core BrightcovePlayerSDK framework. Refer to the FairPlay guide for full details about using FairPlay with the Brightcove Native Player SDK.
Support for Sidecar Subtitles is integrated into the core BrightcovePlayerSDK framework. For full details about using Sidecar Subtitles with the Brightcove Native Player SDK, refer to the Sidecar Subtitles guide.
Since release 6.0.0, the Brightcove Native Player SDK allows you to download HLS videos, including those protected with FairPlay encryption, for playback later, whether online or offline. Refer to the app developer's guide for full details:
iOS App Developer's Guide to Video Downloading and Offline Playback with FairPlay
The Brightcove Player SDK provides installation packages for iOS and tvOS as dynamic libraries packaged as Frameworks and XCFrameworks. Deployment is supported on iOS 12.0 and above.
You can use CocoaPods to add the Brightcove Player SDK to your project. You can find the latest Brightcove-Player-Core
podspec here. The podspec supports both iOS and tvOS.
When using Brightcove CocoaPods in your project, add source 'https://github.com/brightcove/BrightcoveSpecs.git'
to the start of your Podfile.
name.
source 'https://github.com/CocoaPods/Specs'
source 'https://github.com/brightcove/BrightcoveSpecs.git'
platform :ios, '12.0'
use_frameworks!
target 'MyVideoPlayer' do
pod 'Brightcove-Player-Core'
end
The Framework can be installed by appending the /Framework
subspec to the pod.
source 'https://github.com/CocoaPods/Specs'
source 'https://github.com/brightcove/BrightcoveSpecs.git'
platform :ios, '12.0'
use_frameworks!
target 'MyVideoPlayer' do
pod 'Brightcove-Player-Core/Framework'
end
When updating your installation, it's a good idea to refresh the local copy of your BrightcoveSpecs repository so that you have the latest podspecs locally, just as you would update your CococaPods master repository. Typically if you run pod update
in Terminal this will happen automatically, or alternatively you can update explicitly with pod repo update
.
To add the Brightcove Player SDK to your project manually:
BrightcovePlayerSDK.framework
or BrightcovePlayerSDK.xcframework
to your project. Be sure to use the version corresponding to your target, iOS or tvOS.BrightcovePlayerSDK.framework
/ BrightcovePlayerSDK.xcframework
bash ${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/BrightcovePlayerSDK.framework/strip-frameworks.sh
. Check "Run script only when installing". This will remove unneeded architectures from the build, which is important for App Store submission. This step is no longer necessary when using XCFramework.bash ${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/BrightcovePlayerSDK.framework/strip-frameworks.sh
. Check "Run script only when installing". This will remove unneeded architectures from the build, which is important for App Store submission.arm64
has been added to your "Excluded Architectures" build setting for Any iOS Simulator SDK
.For reference, here are all the SDK components and corresponding URLs to help you locate and download the latest releases:
Component | URL |
---|---|
Brightcove-Player-Core | https://github.com/brightcove/brightcove-player-sdk-ios/tags |
Brightcove-Player-DAI | https://github.com/brightcove/brightcove-player-sdk-ios-dai/tags |
Brightcove-Player-FreeWheel | https://github.com/brightcove/brightcove-player-sdk-ios-fw/tags |
Brightcove-Player-GoogleCast | https://github.com/brightcove/brightcove-player-sdk-ios-googlecast/tags |
Brightcove-Player-IMA | https://github.com/brightcove/brightcove-player-sdk-ios-ima/tags |
Brightcove-Player-Omniture | https://github.com/brightcove/brightcove-player-sdk-ios-omniture/tags |
Brightcove-Player-Pulse | https://github.com/brightcove/brightcove-player-sdk-ios-pulse/tags |
Brightcove-Player-SSAI | https://github.com/brightcove/brightcove-player-sdk-ios-ssai/tags |
To add the Brightcove Player SDK to your project with Swift Package Manager:
https://github.com/brightcove/brightcove-player-sdk-ios.git
Note: Only the dynamic XCFramework is supported for Swift Package Manager.
The Brightcove Player SDK for iOS can be imported using:
import BrightcovePlayerSDK;
Playing video with the Brightcove Player SDK for iOS:
// ** Customize these values with your own account information **
let kAccountId = "..."
let kPolicyKey = "..."
let kVideoId = "..."
let sdkManager = BCOVPlayerSDKManager.sharedManager()
let playbackController = sdkManager.createPlaybackController()
self.playbackController = playbackController // store this to a strong property
view.addSubview(playbackController.view)
let playbackService = BCOVPlaybackService(withAccountId: kAccountId,
policyKey: kPolicyKey)
let configuration = [
BCOVPlaybackService.ConfigurationKeyAssetID: kVideoId
]
playbackService.findVideo(withConfiguration: configuration,
queryParameters: nil) { (video: BCOVVideo?,
jsonResponse: Any?,
error: Error?) in
if let video {
self.playbackController?.setVideos([video])
self.playbackController?.play()
}
}
You need to keep the controller from being automatically released at the end of the method. A common way to do this is to store a reference to the controller in a strong instance variable.
Since version 5.1.0, the Brightcove PlayerUI is fully integrated into the Core SDK framework. PlayerUI provides a fully-featured set of controls for playback and advertising, right out of the box.
The PlayerUI is quick to set up, displays ad controls for SSAI, Pulse and FreeWheel, and can be customized by creating your own layouts.
Follow the guidelines below for setting up the PlayerUI controls.
Create a property in your UIViewController to keep track of the BCOVPUIPlayerView. The BCOVPUIPlayerView will contain both the Playback Controller's view, and the controls view.
// PlayerUI's Player View
var playerView: BCOVPUIPlayerView?
Create the BCOVPUIBasicControlView, and then the BCOVPUIPlayerView. This is where we associate the Playback Controller (and thus all the videos it plays) with the controls.
// Create and configure Control View.
let controlView = BCOVPUIBasicControlView.withVODLayout()
playerView = BCOVPUIPlayerView(playbackController: self.playbackController, options: nil)
// Add BCOVPUIPlayerView to your video view.
if let playerView {
videoView.addSubview(playerView)
}
You'll need to set up the layout for the player view, you can do this with Auto Layout or the older Springs & Struts approach.
Set the player view to match the video container from your layout (videoView
) when it resizes.
playerView.frame = videoView.bounds
playerView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
Set the translatesAutoresizingMaskIntoConstraints
on BCOVPUIPlayerView to false
.
playerView.translatesAutoresizingMaskIntoConstraints = false
Then add the constraints for the layout; setting the top, right, left and bottom anchors of your BCOVPUIPlayerView to equal that of videoView
NSLayoutConstraint.activate([
playerView.topAnchor.constraint(equalTo: videoView.topAnchor),
playerView.rightAnchor.constraint(equalTo: videoView.rightAnchor),
playerView.bottomAnchor.constraint(equalTo: videoView.bottomAnchor),
playerView.leftAnchor.constraint(equalTo: videoView.leftAnchor)
])
The BCOVPUIPlayerViewOptions
class allows you to customize some BCOVPlayerUI behavior at initialization. You can customize the following:
jumpBackInterval
The time in seconds the player will seek back when the jump back button is pressed.
hideControlsInterval
The time in seconds after the last touch event, before the controls are hidden.
hideControlsAnimationDuration
The time in seconds it takes for the controls to animate to hidden.
showControlsAnimationDuration
The time in seconds it takes for the controls to animate to visible.
learnMoreButtonBrowserStyle
Setting that determines if tapping the "Learn More" button on an ad will display the clickthrough link in an external browser (default setting) or an internal browser.
presentingViewController
The UIViewController subclass to use for presenting other view controllers (like the closed caption selection view controller).
automaticControlTypeSelection
Whether or not you want the BCOVPUIPlayerView
to pick a BCOVPUIBasicControlView
type automatically based on the media type. When this value is set to true
the BCOVPUIBasicControlView
property passed into the BCOVPUIPlayerView
initializer will be ignored.
Video + Audio Streams
basicControlViewWithVODLayout
basicControlViewWithLiveLayout
basicControlViewWithLiveDVRLayout
Audio-Only Streams
basicControlViewWithAODLayout
basicControlViewWithLiveAudioLayout
basicControlViewWithLiveDVRAudioLayout
NOTE: automaticControlTypeSelection
chooses layouts from those provided by BCOVPlayerUI, and so, custom controls and layouts will be overwritten; automaticControlTypeSelection
and player UI customization are incompatible.
Options can be set using the following method:
let manager = BCOVPlayerSDKManager.sharedManager()
let playbackController = manager.createPlaybackController()
let options = BCOVPUIPlayerViewOptions()
options.jumpBackInterval = 5
let playerView = BCOVPUIPlayerView(playbackController: playbackController,
options: options)
Three layouts are provided to support different types of video:
BCOVPUIControlLayout basicVODControlLayout
is a basic layout for general on-demand video streams.
BCOVPUIControlLayout basicLiveControlLayout
is a layout for live video.
BCOVPUIControlLayout basicLiveDVRControlLayout
is a layout for live video streams with DVR controls.
You typically set a new layout immediatley after your BCOVPUIPlayerView
is created, but you can also set a new layout at any time. For example, you can set a new VOD layout like this:
playerView?.controlsView.layout = BCOVPUIControlLayout.basicVOD()
In addition to the default layouts, you can create your own highly customized layouts by instantiating a new BCOVPUIControlLayout
with your own design. Note, however, that automaticControlTypeSelection
chooses layouts from those provided by BCOVPlayerUI, and so, custom controls and layouts will be overwritten; automaticControlTypeSelection
and player UI customization are incompatible.
First, create the controls that will go in your layout using BCOVPUIBasicControlView layoutViewWithControlFromTag:width:elasticity:
. Each control is packaged in a BCOVPUILayoutView
that determines the control spacing.
You can set the width
of each layout view to the default width (which is based on the type of control), or you can specify your own width.
Use the elasticity
argument to determine how much the layout view containing the control reizes its width to fill the control bar.
Here are examples of creating a variety of basic controls.
// Create various standard layout views
// Standard play/pause button
let playbackLayoutView = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.buttonPlayback,
width: kBCOVPUILayoutUseDefaultValue,
elasticity: 0.0)
// Standard jump back button
let jumpBackButtonLayoutView = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.buttonJumpBack,
width: kBCOVPUILayoutUseDefaultValue,
elasticity: 0.0)
// Current time indicator
let currentTimeLayoutView = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.labelCurrentTime,
width: kBCOVPUILayoutUseDefaultValue
elasticity: 0.0)
// Time separator - typically the '/' character
let timeSeparatorLayoutView = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.labelTimeSeparator,
width: kBCOVPUILayoutUseDefaultValue,
elasticity: 0.0)
// Video duration label
let durationLayoutView = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.labelDuration,
width: kBCOVPUILayoutUseDefaultValue,
elasticity: 0.0)
// Slider bar used for seeking through the video
// The elasticity is set to 1 so that it can resize to fill available space
let progressLayoutView = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.sliderProgress,
width: kBCOVPUILayoutUseDefaultValue,
elasticity: 1.0)
// Closed caption button
// This button is initially hidden ('removed'), and will be shown
// if closed captions or audio tracks are available.
let closedCaptionLayoutView = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.buttonClosedCaption,
width: kBCOVPUILayoutUseDefaultValue,
elasticity: 0.0)
closedCaptionLayoutView?.isRemoved = true
// The full-screen button
let screenModeLayoutView = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.buttonScreenMode,
width: kBCOVPUILayoutUseDefaultValue,
elasticity: 0.0)
// AirPlay button
// This button is initially hidden ('removed'), and will be shown
// if AirPlay devices are available.
let externalRouteLayoutView = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.viewExternalRoute,
width: kBCOVPUILayoutUseDefaultValue,
elasticity: 0.0)
externalRouteLayoutView?.isRemoved = true
// Empty view - used as a spacer
let spacerLayoutView1 = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.viewEmpty,
width: 1.0,
elasticity: 1.0)
// Empty view - used as a spacer
let spacerLayoutView2 = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.viewEmpty,
width: 1.0,
elasticity: 1.0)
// Empty view - will have a custom UIImageView added as a subview
let logoLayoutView1 = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.viewEmpty,
width: 88.0,
elasticity: 1.0)
// Empty view - will have a custom UIImageView added as a subview
let logoLayoutView2 = BCOVPUIBasicControlView.layoutViewWithControl(from: BCOVPUIViewTag.viewEmpty,
width: 36.0,
elasticity: 1.0)
Note that you can also create an empty layout view, into which you can place your own view (logo, control, nothing, etc.). This code shows how to place a UIImage
logo inside the logoLayoutView1 we created above.
// Create logo image inside an image view for display in control bar.
let logoImage1 = UIImage(named: "myLogo")
let logoImageView1 = UIImageView(image: logoImage1)
logoImageView1.autoresizingMask = [.flexibleWidth, .flexibleHeight]
logoImageView1.contentMode = .scaleAspectFit
logoImageView1.frame = logoLayoutView1.frame
// Add image view to our empty layout view.
logoLayoutView1.addSubview(logoImageView1)
Now that there are various controls packaged in layout views, they are ordered into arrays, each of wihch represents a single line of controls, i.e. a control bar. Note that you can have different layouts for portrait and landscape orientations, so you will typically set up two different arrays of control bars.
In the standard layout for landscape orientation, controls are arranged in a single array, and then that array is stored in another array representing the entire set of controls.
let standardLayoutLine1 = [
playbackLayoutView,
jumpBackButtonLayoutView,
currentTimeLayoutView,
timeSeparatorLayoutView,
durationLayoutView,
progressLayoutView,
spacerLayoutView1,
logoLayoutView1,
spacerLayoutView2,
closedCaptionLayoutView,
screenModeLayoutView,
externalRouteLayoutView
]
let standardLayoutLines = [ standardLayoutLine1 ]
In the compact layout for portrait orientation, two arrays of controls are created, one for each line. These arrays are packaged into another array representing the compact layout.
Note that the exact same objects are used for most of the controls in each layout. When this is done, and you switch between portrait and landscape orientations, the object will be moved to its new position using smooth animation.
let compactLayoutLine1 = [
currentTimeLayoutView,
progressLayoutView,
durationLayoutView
]
let compactLayoutLine2 = [
playbackLayoutView,
jumpBackButtonLayoutView,
spacerLayoutView1,
closedCaptionLayoutView,
screenModeLayoutView,
externalRouteLayoutView,
logoLayoutView2
]
let compactLayoutLines = [
compactLayoutLine1,
compactLayoutLine2
]
Finally, now that there are two layout configurations (one for full width, and one for compact width), you can create a new BCOVPUIControlLayout
object, and set it in the player's control view.
let customLayout = BCOVPUIControlLayout.init(standardControls: standardLayoutLines,
compactControls: compactLayoutLines)
playerView?.controlsView.layout = customLayout
If you have controls that you need to show or hide frequently, you can set the removed
property on that control's layout view. When you have changed your controls, call setNeedsLayout
on the playerView's controlView:
logoLayoutView1?.isRemoved = true
playerView?.controlsView.setNeedsLayout()
You can also customize several general BCOVPUIControlLayout
properties:
controlBarHeight
sets the size of each row of controls.horizontalItemSpacing
sets the spacing between each BCOVPUILayoutView
in each control bar.compactLayoutMaximumWidth
determines which set of controls is used. If the control view is smaller than compactLayoutMaximumWidth
, the compact control set will be used, otherwise the standard controls will be used.To change the set of controls that are displayed, you must create and install a new BCOVPUIControlLayout
. New controls can be installed at any time.
For more examples of PlayerUI customization, you can look at the sample code in the PlayerUI folder of the BrightcoveOS GitHub repository:
https://github.com/BrightcoveOS/ios-player-samples
The Brightcove Native Player SDK includes built-in controls for playback in tvOS on Apple TV. For full details about using the built-in TV Player UI with the Brightcove Native Player SDK, see our TV Player guide.
Enable AirPlay functionality by setting the setAllowsExternalPlayback
property on your BCOVPlaybackController
to true
. The AirPlay button will be displayed in the playback controls if AirPlay devices are found on your network.
Currently, IMA is the only ad plugin that supports AirPlay and only when using pre-roll and/or post-roll ads. Using AirPlay with the Pulse, SSAI or FreeWheel ad plugins may result in unexpected behavior.
If you also want to support AirPlay 2 and allow for multiple devices to be selected for audio output you will have to do a few additional things. First, you'll need to configure AVAudioSession so that you can set the routeSharingPolicy
. For example:
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback, policy: .longFormVideo)
} catch {
print("Error setting AVAudioSession category")
}
You will also need to configure at least one playback command via MPRemoteCommandCenter
. At the very least you'll want to configure both the pauseCommand
and playCommand
. For Example:
let center = MPRemoteCommandCenter.shared()
center.pauseCommand.addTarget { _ in
playbackController.pause()