Overview
This example plays a video returned from the Brightcove Playback API, which is the latest and recommended API to retrieve content from your Video Cloud library.
This example plays videos from an internal array of video files.
To use the Playback API, you will need a Policy Key. If you are not familiar with Policy Keys, see the Policy API Overview.
Get started
Follow the steps below to get familiar with setting up an app project that uses the Brightcove Player SDK for tvOS. You can view the complete code for each of the following:
There are two ways to try out this sample:
Download the sample
Download the entire Xcode project for experimentation.
- Clone or download the Native SDK for iOS samples to your local system.
- Navigate to the Player/AppleTV/swift sample app.
- Run the
pod install
command. - Open and run the newly created workspace.
For details, see the Running Sample Apps for the Native SDK for iOS/tvOS document.
Build the app by following the steps in this guide
Follow the steps below to get familiar with setting up an app project that uses the Brightcove Player SDK for tvOS. You can view the complete code for each of the following:
Create the project
Set up a project in Xcode. Then add the SDK along with any dependencies to the project.
Set up the Xcode project
Create a new Xcode project for the app.
-
Start the creation of a new tvOS project in Xcode. Select Create a new Xcode project.
-
Choose tvOS and then App for the template. Click Next.
-
Set the project information as follows:
- Product Name: Simple-Video-Playback
- Team: none
The Team field is optional. If you want to distribute your app on the App Store, you will need to select a team that you belong to through the Apple Developer Program. The team name is required for code signing. In this example, we'll select none.
- Organization Identifier: com.your-company-name
This makes the product name unique for the app store. - Interface: Storyboard
Use either the Storyboard or SwiftUI interface.
- Language: Swift
Click Next.
-
Choose the location where you want to save your project and click Create.
- Now close the project (yes, close it — this is important!)
Add the SDK and its dependencies to your project
The easiest way to add the SDK and its dependencies to your project is to use CocoaPods.
CocoaPods is a dependency manager that adds libraries to your project. It is not required, but makes installation easier. To install CocoaPods, see the instructions on the CocoaPods site.
-
In your project folder, create a plain text file called Podfile (no file extension).
-
Using a text editor, add the following lines of code to the Podfile and save it. This code does the following:
- Line 1: Points to the GitHub location for the CocoaPods pod specs
- Line 2: Points to the GitHub location for the Brightcove pod specs
- Line 4: Sets Pods to use frameworks instead of static libraries
- Line 6: Defines the tvOS platform version.
-
Lines 8-10: Install the Brightcove Native Player SDK.
- For more information about managing dependencies, see the How To Manage Dependencies With CocoaPods article.
source 'https://github.com/CocoaPods/Specs.git' source 'https://github.com/brightcove/BrightcoveSpecs.git' use_frameworks! platform :tvos, '16.0' # (or whatever version you want) target 'Simple-Video-Playback' do pod 'Brightcove-Player-Core/XCFramework' end
-
Open a Terminal session and navigate to your Simple-Video-Playback Xcode project folder.
-
In the Terminal session, type the command
pod install
and press Return to run the it.
If CocoaPods can not find a compatible version for the pod, or it is not the latest version, try running the following in the Terminal app:
pod update
You should see a series of messages in the terminal indicating that the Brightcove Player SDK has been added to your project.
-
The
pod install
command creates the.xcworkspace
file for your project.Notice the last line, which is important — from this point on, you must do the following:
- Open the Simple-Video-Playback.xcworkspace file in Xcode
- Do not use the Simple-Video-Playback.xcodeproj file
Code the video app
Create the code for a simple video playback app.
Set the audio behavior for the app
The audio session handles audio behavior at the app level. Learn more about the AVAudioSession class.
For this sample, we will use the playback category. This plays audio even when the screen is locked and with the Ring/Silent switch set to silent. Since we are playing video, we will use the moviePlayback mode. To keep it simple, we will put this code in the App Delegate.
-
In your project, open the App Delegate file (AppDelegate.swift).
-
In the
didFinishLaunchingWithOptions
function, add code to set the audio session category. Make sure you import theAVFoundation
framework.// // AppDelegate.swift // Simple-Video-Playback // // Copyright © 2018 Brightcove. All rights reserved. // import UIKit import AVFoundation @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. var categoryError :NSError?; var success: Bool; do { try AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback, options: .duckOthers) success = true; } catch let error as NSError { categoryError = error; success = false; } if !success { print("AppDelegate Debug - Error setting AVAudioSession category. Because of this, there may be no sound. \(categoryError!)"); } return true } func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. } func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } }
Build the View Controller
Update the View Controller class to play a video from the Brightcove Playback API.
Update the View Controller class to play a video from a remote URL.
-
In your project, open the View Controller file (ViewController.swift).
Import the Native SDK
Although the Brightcove Native Player SDK for iOS is written in Obj-C, we can simply import the framework modules into our Swift project.
-
Below the existing
import
directive, add the following to import the Brightcove Native Player SDK:import BrightcovePlayerSDK
Customize the project with your values
Add values to access your Video Cloud account.
-
Below the
import
directives, add your own values for the following:-
Line 12: Defines your Brightcove Playback API Policy Key. This example plays a video returned from the Brightcove Playback API, which is the latest and recommended API to retrieve content from your Video Cloud library. If you are not familiar with Policy Keys, see the Policy API Overview.
- Line 13: Defines your Video Cloud Account ID
-
Line 14: Defines your Video Cloud Video ID
fileprivate struct playbackConfig { static let policyKey = "your policy key" static let accountID = "your account id" static let videoID = "your video id" }
-
Create a view variable
-
In the
ViewController
class, add a variable for the view.class ViewController: UIViewController { @IBOutlet weak var videoContainerView: UIView!
Create the playback service
-
Create a variable that defines the Brightcove playback service with your Account ID and Policy Key. This will be initialized the first time it is called.
If you are new to swift, review the guide about Lazy Stored Properties.
lazy var playbackService: BCOVPlaybackService = { return BCOVPlaybackService(accountId: playbackConfig.accountID, policyKey: playbackConfig.policyKey) }()
Create the playback controller
-
Create a variable that defines the Brightcove playback controller. This will be created the first time it is called.
-
Lines 28-30: set the delegate and turn on the auto-advance and autoplay features.
lazy var playbackController: BCOVPlaybackController? = { guard let _playbackController = BCOVPlayerSDKManager.shared().createPlaybackController() else { return nil } _playbackController.delegate = self _playbackController.isAutoAdvance = true _playbackController.isAutoPlay = true return _playbackController }()
-
Define the player view
-
Create a function named
createTVPlayerView
as follows:- Lines 38-39: Define the player view so that the tab bar panels can present other view controllers.
- Lines 42-44: Create the player view and add it to the video container view.
- Line 47: Associate the player view with the playback controller.
- Line 49: Adds the player view as a subview of the main view.
- Line 51: Turn off auto-resizing mask.
-
Lines 52-57: Use Auto Layout to define dynamic contraints for the player view.
lazy var playerView: BCOVTVPlayerView? = { // Set yourself as the presenting view controller // so that tab bar panels can present other view controllers let options = BCOVTVPlayerViewOptions() options.presentingViewController = self // Create and add to the video container view guard let _playerView = BCOVTVPlayerView(options: options) else { return nil } // Link the playback controller to the Player View _playerView.playbackController = playbackController videoContainerView.addSubview(_playerView) _playerView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ _playerView.topAnchor.constraint(equalTo: videoContainerView.topAnchor), _playerView.rightAnchor.constraint(equalTo: videoContainerView.rightAnchor), _playerView.leftAnchor.constraint(equalTo: videoContainerView.leftAnchor), _playerView.bottomAnchor.constraint(equalTo: videoContainerView.bottomAnchor) ]) return _playerView }()
Create an init function
- Create an
init
function as follows:- Line 64: Calls the super class implementation of the init() function.
-
Line 65: Optional: Sends your Video Cloud Account ID to analytics. This is only needed if you override the
BCOVVideo
class or do not use the Brightcove Playback service or catalog.
required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) playbackController?.analytics.account = playbackConfig.accountID; }
Process after loading the view
-
In the
viewDidLoad
method add the following:-
Line 72: Calls the
requestContentFromPlaybackService
function, which we will define in the next step.
override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. requestContentFromPlaybackService() }
-
Request content from the Brightcove library
In order to play back video content, you will request a playlist from the catalog service
-
Create a function named
requestContentFromPlaybackService
as follows:- Lines 75-76: return a video object from the Playback API based on the given video id.
- Line 80: adds the video to the playback controller.
- Line 82: writes an error message if a playlist is not returned.
private func requestContentFromPlaybackService() { playbackService.findVideo(withConfiguration: configuration, queryParameters: nil, completion: { [weak self] (video: BCOVVideo?, jsonResponse: [AnyHashable: Any]?, error: Error?) -> Void in if let _video = video { // since "isAutoPlay" is true, setVideos will begin playing the content self?.playbackController?.setVideos([_video] as NSArray) } else { print("ViewController Debug - Error retrieving video: \(error?.localizedDescription ?? "unknown error")") } } }
Extend the playback controller
This allows your app to listen and respond to video playback events.
-
Extend the view controller to include the Brightcove playback controller delegate, and listen for playback events. If you are new to swift, review the guide about Extensions.
// MARK: - BCOVPlaybackControllerDelegate extension ViewController: BCOVPlaybackControllerDelegate { func playbackController(_ controller: BCOVPlaybackController!, didAdvanceTo session: BCOVPlaybackSession!) { NSLog("ViewController Debug - Advanced to new session.") } func playbackController(_ controller: BCOVPlaybackController!, playbackSession session: BCOVPlaybackSession!, didReceive lifecycleEvent: BCOVPlaybackSessionLifecycleEvent!) { NSLog("Event: %@", lifecycleEvent.eventType) } }
The rest
-
Create functions to handle focus overrides for older versions of tvOS.
// MARK: - UIFocusEnvironment overrides extension ViewController { // Focus Environment override for tvOS 9 override var preferredFocusedView: UIView? { return playerView } // Focus Environment override for tvOS 10+ override var preferredFocusEnvironments: [UIFocusEnvironment] { return (playerView != nil ? [ playerView! ] : []) } }
View the code
The View Controller is now complete. Here is the full code:
//
// ViewController.swift
// Simple-Video-Playback
//
// Copyright © 2018 Brightcove. All rights reserved.
//
import UIKit
import BrightcovePlayerSDK
fileprivate struct playbackConfig {
static let policyKey = "your policy key"
static let accountID = "your account id"
static let videoID = "your video id"
}
class ViewController: UIViewController {
@IBOutlet weak var videoContainerView: UIView!
lazy var playbackService: BCOVPlaybackService = {
return BCOVPlaybackService(accountId: playbackConfig.accountID, policyKey: playbackConfig.policyKey)
}()
lazy var playbackController: BCOVPlaybackController? = {
guard let _playbackController = BCOVPlayerSDKManager.shared().createPlaybackController() else {
return nil
}
_playbackController.delegate = self
_playbackController.isAutoAdvance = true
_playbackController.isAutoPlay = true
return _playbackController
}()
lazy var playerView: BCOVTVPlayerView? = {
// Set yourself as the presenting view controller
// so that tab bar panels can present other view controllers
let options = BCOVTVPlayerViewOptions()
options.presentingViewController = self
// Create and add to the video container view
guard let _playerView = BCOVTVPlayerView(options: options) else {
return nil
}
// Link the playback controller to the Player View
_playerView.playbackController = playbackController
videoContainerView.addSubview(_playerView)
_playerView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
_playerView.topAnchor.constraint(equalTo: videoContainerView.topAnchor),
_playerView.rightAnchor.constraint(equalTo: videoContainerView.rightAnchor),
_playerView.leftAnchor.constraint(equalTo: videoContainerView.leftAnchor),
_playerView.bottomAnchor.constraint(equalTo: videoContainerView.bottomAnchor)
])
return _playerView
}()
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
playbackController?.analytics.account = playbackConfig.accountID; // Optional
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
requestContentFromPlaybackService()
}
private func requestContentFromPlaybackService() {
playbackService.findVideo(withConfiguration: configuration, queryParameters: nil, completion: { [weak self] (video: BCOVVideo?, jsonResponse: [AnyHashable: Any]?, error: Error?) -> Void in
if let _video = video {
// since "isAutoPlay" is true, setVideos will begin playing the content
self?.playbackController?.setVideos([_video] as NSArray)
} else {
print("ViewController Debug - Error retrieving video: \(error?.localizedDescription ?? "unknown error")")
}
}
}
}
// MARK: - BCOVPlaybackControllerDelegate
extension ViewController: BCOVPlaybackControllerDelegate {
func playbackController(_ controller: BCOVPlaybackController!, didAdvanceTo session: BCOVPlaybackSession!) {
NSLog("ViewController Debug - Advanced to new session.")
}
func playbackController(_ controller: BCOVPlaybackController!, playbackSession session: BCOVPlaybackSession!, didReceive lifecycleEvent: BCOVPlaybackSessionLifecycleEvent!) {
NSLog("Event: %@", lifecycleEvent.eventType)
}
}
// MARK: - UIFocusEnvironment overrides
extension ViewController {
// Focus Environment override for tvOS 9
override var preferredFocusedView: UIView? {
return playerView
}
// Focus Environment override for tvOS 10+
override var preferredFocusEnvironments: [UIFocusEnvironment] {
return (playerView != nil ? [ playerView! ] : [])
}
}
Import the Native SDK
Although the Brightcove Native Player SDK for iOS is written in Obj-C, we can simply import the framework modules into our Swift project.
-
Below the existing
import
directive, add the following to import the Brightcove Native Player SDK:import BrightcovePlayerSDK
Customize the project with your values
Add the value for your Video Cloud Account ID.
fileprivate struct playbackConfig {
static let accountID = "your account id"
}
Create a view variable
-
In the
ViewController
class, add a variable for the view.class ViewController: UIViewController { @IBOutlet weak var videoContainerView: UIView!
Create the playback controller
-
Create a variable that defines the Brightcove playback controller. This will be created the first time it is called.
-
Lines 22-24: set the delegate and turn on the auto-advance and autoplay features.
lazy var playbackController: BCOVPlaybackController? = { guard let _playbackController = BCOVPlayerSDKManager.shared().createPlaybackController() else { return nil } _playbackController.delegate = self _playbackController.isAutoAdvance = true _playbackController.isAutoPlay = true return _playbackController }()
-
Define the player view
-
Create the
playerView
as follows:- Lines 32-33: Define the player view so that the tab bar panels can present other view controllers.
- Lines 36-38: Create the player view and add it to the video container view.
- Line 41: Associate the player view with the playback controller.
- Line 43: Adds the player view as a subview of the main view.
- Line 45: Turn off auto-resizing mask.
-
Lines 46-51: Use Auto Layout to define dynamic contraints for the player view.
lazy var playerView: BCOVTVPlayerView? = { // Set yourself as the presenting view controller // so that tab bar panels can present other view controllers let options = BCOVTVPlayerViewOptions() options.presentingViewController = self // Create and add to the video container view guard let _playerView = BCOVTVPlayerView(options: options) else { return nil } // Link the playback controller to the Player View _playerView.playbackController = playbackController videoContainerView.addSubview(_playerView) _playerView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ _playerView.topAnchor.constraint(equalTo: videoContainerView.topAnchor), _playerView.rightAnchor.constraint(equalTo: videoContainerView.rightAnchor), _playerView.leftAnchor.constraint(equalTo: videoContainerView.leftAnchor), _playerView.bottomAnchor.constraint(equalTo: videoContainerView.bottomAnchor) ]) return _playerView }()
Create an init function
- Create an
init
function as follows:- Line 58: Calls the super class implementation of the init() function.
-
Line 59: Sends your Video Cloud Account ID to analytics. This registers your app with Brightcove.
required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) playbackController?.analytics.account = playbackConfig.accountID; }
Play videos
-
In the
viewDidLoad
method add the following:- Lines 67-69: Create an array of video sources using url paths.
-
Line 71: adds the video array to the controller's playback queue, which is set for automatically start playing.
override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. // create an array of videos var videoArray = [AnyObject]() videoArray = [videoWithURL(url: NSURL(string: "https://sdks.support.brightcove.com/assets/videos/hls/laughing_gull/laughing_gull.m3u8")!), videoWithURL(url: NSURL(string: "https://sdks.support.brightcove.com/assets/videos/hls/greatblueheron/greatblueheron.m3u8")!)] playbackController?.setVideos(videoArray as NSFastEnumeration); }
Set the delivery method for video sources
-
Create a function that sets the delivery method for
BCOVSources
that belong to a video.func videoWithURL(url: NSURL) -> BCOVVideo { // set the delivery method for BCOVSources that belong to a video let source:BCOVSource = BCOVSource(url: url as URL?, deliveryMethod: kBCOVSourceDeliveryHLS, properties: nil) let video = BCOVVideo.init(source: source, cuePoints: BCOVCuePointCollection.init(array: []), properties: [NSObject:AnyObject]()) return video! }
Extend the playback controller
This allows your app to listen and respond to video playback events.
-
Extend the view controller to include the Brightcove playback controller delegate, and listen for playback events. If you are new to swift, review the guide about Extensions.
// MARK: - BCOVPlaybackControllerDelegate extension ViewController: BCOVPlaybackControllerDelegate { func playbackController(_ controller: BCOVPlaybackController!, didAdvanceTo session: BCOVPlaybackSession!) { NSLog("ViewController Debug - Advanced to new session.") } func playbackController(_ controller: BCOVPlaybackController!, playbackSession session: BCOVPlaybackSession!, didReceive lifecycleEvent: BCOVPlaybackSessionLifecycleEvent!) { NSLog("Event: %@", lifecycleEvent.eventType) } }
The rest
-
Create functions to handle focus overrides for older versions of tvOS.
// MARK: - UIFocusEnvironment overrides extension ViewController { // Focus Environment override for tvOS 9 override var preferredFocusedView: UIView? { return playerView } // Focus Environment override for tvOS 10+ override var preferredFocusEnvironments: [UIFocusEnvironment] { return (playerView != nil ? [ playerView! ] : []) } }
View the code
The View Controller is now complete. Here is the full code:
//
// ViewController.swift
// Simple-Video-Playback
//
// Copyright © 2018 Brightcove. All rights reserved.
//
import UIKit
import BrightcovePlayerSDK
fileprivate struct playbackConfig {
static let accountID = "1752604059001"
}
class ViewController: UIViewController {
@IBOutlet weak var videoContainerView: UIView!
lazy var playbackController: BCOVPlaybackController? = {
guard let _playbackController = BCOVPlayerSDKManager.shared().createPlaybackController() else {
return nil
}
_playbackController.delegate = self
_playbackController.isAutoAdvance = true
_playbackController.isAutoPlay = true
return _playbackController
}()
lazy var playerView: BCOVTVPlayerView? = {
// Set yourself as the presenting view controller
// so that tab bar panels can present other view controllers
let options = BCOVTVPlayerViewOptions()
options.presentingViewController = self
// Create and add to the video container view
guard let _playerView = BCOVTVPlayerView(options: options) else {
return nil
}
// Link the playback controller to the Player View
_playerView.playbackController = playbackController
videoContainerView.addSubview(_playerView)
_playerView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
_playerView.topAnchor.constraint(equalTo: videoContainerView.topAnchor),
_playerView.rightAnchor.constraint(equalTo: videoContainerView.rightAnchor),
_playerView.leftAnchor.constraint(equalTo: videoContainerView.leftAnchor),
_playerView.bottomAnchor.constraint(equalTo: videoContainerView.bottomAnchor)
])
return _playerView
}()
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
playbackController?.analytics.account = playbackConfig.accountID;
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// create an array of videos
var videoArray = [AnyObject]()
videoArray = [videoWithURL(url: NSURL(string: "https://sdks.support.brightcove.com/assets/videos/hls/laughing_gull/laughing_gull.m3u8")!),
videoWithURL(url: NSURL(string: "https://sdks.support.brightcove.com/assets/videos/hls/greatblueheron/greatblueheron.m3u8")!)]
playbackController?.setVideos(videoArray as NSFastEnumeration);
}
func videoWithURL(url: NSURL) -> BCOVVideo {
// set the delivery method for BCOVSources that belong to a video
let source:BCOVSource = BCOVSource(url: url as URL?, deliveryMethod: kBCOVSourceDeliveryHLS, properties: nil)
let video = BCOVVideo.init(source: source, cuePoints: BCOVCuePointCollection.init(array: []), properties: [NSObject:AnyObject]())
return video!
}
}
// MARK: - BCOVPlaybackControllerDelegate
extension ViewController: BCOVPlaybackControllerDelegate {
func playbackController(_ controller: BCOVPlaybackController!, didAdvanceTo session: BCOVPlaybackSession!) {
NSLog("ViewController Debug - Advanced to new session.")
}
func playbackController(_ controller: BCOVPlaybackController!, playbackSession session: BCOVPlaybackSession!, didReceive lifecycleEvent: BCOVPlaybackSessionLifecycleEvent!) {
NSLog("Event: %@", lifecycleEvent.eventType)
}
}
// MARK: - UIFocusEnvironment overrides
extension ViewController {
// Focus Environment override for tvOS 9
override var preferredFocusedView: UIView? {
return playerView
}
// Focus Environment override for tvOS 10+
override var preferredFocusEnvironments: [UIFocusEnvironment] {
return (playerView != nil ? [ playerView! ] : [])
}
}
Connect the storyboard view
Connect the Main.storyboard
view with the videoContainer
property.
-
In the Xcode, open the
Main.storyboard
file. -
In the companion view, expand the View Controller Scene and then the View Controller menu to expose the View object.
-
Click Add Editor on Right, and open the
ViewController.swift
file. -
Select the open circle next to the
@IBOutlet
for thevideoContainerView
, and drag it to the View object to connect these components.
Manage Media Security
App Transport Security (ATS) enforces secure connections between your app and web services. With Apple's release of the iOS 9 SDK, a new feature called App Transport Security (ATS) was added.
-
One of the following situations will apply to your app:
-
By default the Brightcove Native SDK for iOS uses a source selection policy to choose HTTPS over HTTP sources, so you can build your apps with ATS enabled.
That's it, you are ready to run your app.
-
If you are using HTTP sources or have other HTTP calls in your app, you may encounter the following error message:
App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
This means that ATS is enabled, but your system is not configured to meet the ATS requirements. To fix this situation, see the Working with App Transport Security (ATS) document.
-
Run the app
The app is ready to build and run on an Apple TV or the Xcode Simulator. You should be able to play and navigate the specified video using the remote control.
Apple TV UI controls
Now, you are ready to learn more about the Apple TV playback controls including the top bar view for video info, subtitles and audio. For more information, see the Apple TV UI Controls with the Native SDK for tvOS document.
For details on how to build your own custom top bar item view, see the Apple TV player sample.