逐步:簡單的電視視頻應用程序

在本主題中,您將學習如何使用可在蘋果 TV 或 Xcode 模擬器上播放的 TVOS 專用的 Brightcove 播放器 SDK 構建一個簡單的視頻播放應用程序。您將使用 Swift 編程語言構建它。

概覽

此示例播放從Brightcove 回放 API,這是最新推薦的 API,用於從您的視頻雲庫中檢索內容。

此範例會從內部視訊檔案陣列中播放視訊。

要使用Playback API,您需要一個策略密鑰。如果您不熟悉策略密鑰,請參閱策略 API 概述 .

開始使用

請依照下列步驟熟悉設定使用適用於 tvOS 的 Brightcove 播放程式 SDK 的應用程式專案。您可以檢視下列各項的完整程式碼:

  1. 應用程式代表
  2. 檢視控制器

有兩種方法可以嘗試這個範例:

下載範例

下載整個 Xcode 項目進行實驗。

  1. 克隆或下載適用於 iOS 示例的本機 SDK到您的本地系統。
  2. 導航到播放器/AppleTV/swift示例應用程序。
  3. 跑過pod install命令。
  4. 開啟並執行新建立的工作區。

有關詳細信息,請參閱為適用於 iOS/tvOS 的本機 SDK 運行示例應用程序文檔。

依照本指南中的步驟建置應用程式

請依照下列步驟熟悉設定使用適用於 tvOS 的 Brightcove 播放程式 SDK 的應用程式專案。您可以檢視下列各項的完整程式碼:

  1. 應用程式代表
  2. 檢視控制器

建立專案

在 Xcode 中設置一個項目。然後將 SDK 以及任何依賴項添加到項目中。

設置 Xcode 項目

為應用程序創建一個新的 Xcode 項目。

  1. 在Xcode中開始創建新的tvOS項目。選擇創建一個新的 Xcode 項目 .

    建立專案
    建立專案
  2. 為模板選擇 tvOS ,然後選擇 App 。點擊下一個 .

    選擇專案範本
    選擇專案範本
  3. 設定專案資訊,如下所示:

    • 產品名稱:簡單影片播放
    • 團隊:沒有任何

      [專案團隊] 欄位是選擇性的。如果你想在 App Store 發佈你的應用程式,你需要透過 Apple 開發者計劃選擇你屬於的團隊。程式碼簽署需要群組名稱。在此範例中,我們將選取「無」。

    • 組織標識符: com.your-company-name
      這使得產品名稱對於應用程序商店是唯一的。
    • 界面:故事板

      使用 Storyboard 或 SwiftUI 界面。

    • 語言:迅速
    加入專案資訊
    加入專案資訊

    點擊下一個 .

  4. 選擇您要保存項目的位置,然後單擊 創建

    建立專案
    建立專案
  5. 現在關閉項目(是的,關閉它-這很重要!)

將 SDK 及其依賴項添加到您的項目

將 SDK 及其依賴項添加到您的項目中的最簡單方法是使用 Cocoapods。

Cocoapods 是一個依賴管理器,將庫添加到您的項目中。它不是必需的,但使安裝更容易。要安裝 CocoaPods,請參閱可可豆地點。

  1. 在您的項目文件夾中,創建一個名為播客文件(沒有文件擴展名)。

  2. 使用文本編輯器,將以下代碼行添加到 Podfile 並保存它。此程式碼會執行下列作業:

    • 第 1 行:指向 CocoaPods pod 規範的 GitHub 位置
    • 第 2 行:指向 Brightcove pod 規範的 GitHub 位置
    • 第4行:將 Pod 設置為使用框架而不是靜態庫
    • 第 6 行:定義tvOS平台版本。
    • 第 8-10 行:安裝布萊特灣原生播放器 SDK。

    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
  3. 打開終端會話並導航到您的簡單視頻回放 Xcode 項目文件夾。

    終端工作階段
    終端工作階段
  4. 在終端機工作階段中,輸入命令

      pod install

    並按下返回運行它。

    如果CocoaPods找不到該Pod的兼容版本,或者它不是最新版本,請嘗試在終端應用程序中運行以下命令:

      pod update

    您應該會在終端中看到一系列訊息,指出 Brightcove 播放程式 SDK 已新增至您的專案。

  5. pod install命令創建.xcworkspace文件為您的項目。

    請注意最後一行,這很重要 — 從這一點開始,您必須執行以下操作:

    • 在 Xcode 中打開 Simple-Video-Playback.xcworkspace 文件
    • 不要 使用 Simple-Video-Playback.xcodeproj 文件
    工作區
    工作區

編寫視訊應用程式

為簡單的視訊播放應用程式建立程式碼。

設定應用程式的音訊行為

音訊工作階段會處理應用程式層級的音訊行為。了解更多關於AVAudioSession班級。

對於這個示例,我們將使用回放類別。即使螢幕鎖定且「鈴聲/靜音」開關設定為靜音,也會播放音訊。由於我們正在播放視頻,我們將使用電影回放模式。為了保持簡單,我們將把這段代碼在應用程序委託。

  1. 在您的項目中,打開 App Delegate 文件 ( AppDelegate.swift ).

  2. 在裡面didFinishLaunchingWithOptions功能,添加代碼以設置音頻會話類別。確保你導入AVFoundation框架。

    //
    //  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:.
      }
    
    }

構建視圖控制器

更新View Controller類以播放Brightcove Playback API中的視頻。

更新View Controller類以從遠程URL播放視頻。

  1. 在您的項目中,打開視圖控制器文件 ( 視圖控制器.swift ).

匯入原生 SDK

雖然 iOS 的布萊特灣本機播放器 SDK 是用 Obj-C 編寫的,我們可以簡單地導入框架模塊到我們的 Swift 項目。

  1. 低於現有的import指令,添加以下內容以導入 Brightcove Native Player SDK:

    import BrightcovePlayerSDK

使用您的價值自訂專案

新增值以存取您的視訊雲端帳戶。

  1. 以下import指令,為以下內容添加您自己的值:

    • 第 12 行:定義您的布萊特灣播放 API 原則金鑰。此示例播放從Brightcove 回放 API,這是最新推薦的 API,用於從您的視頻雲庫中檢索內容。如果您不熟悉策略密鑰,請參閱策略 API 概述 .

    • 第 13 行:定義您的視訊雲端帳戶 ID
    • 第 14 行:定義您的視訊雲端視訊 ID

    fileprivate struct playbackConfig {
      static let policyKey = "your policy key"
      static let accountID = "your account id"
      static let videoID = "your video id"
    }

建立視圖變數

  1. 在裡面ViewController類,為視圖添加一個變量。

    class ViewController: UIViewController {
      @IBOutlet weak var videoContainerView: UIView!

創建播放服務

  1. 創建一個變量,該變量使用您的帳戶ID和策略密鑰定義Brightcove回放服務。它將在第一次調用時初始化。

    如果您是 swift 的新手,請查看有關的指南惰性存儲屬性 .

    lazy var playbackService: BCOVPlaybackService = {
      return BCOVPlaybackService(accountId: playbackConfig.accountID, policyKey: playbackConfig.policyKey)
    }()

建立播放控制器

  1. 建立定義 Brightcove 播放控制器的變數。這將在第一次被調用時創建。

    • 第28-30行:設置代表並打開自動前進和自動播放功能。

    lazy var playbackController: BCOVPlaybackController? = {
      guard let _playbackController = BCOVPlayerSDKManager.shared().createPlaybackController() else {
        return nil
      }
      _playbackController.delegate = self
      _playbackController.isAutoAdvance = true
      _playbackController.isAutoPlay = true
    
      return _playbackController
    }()

定義播放器檢視

  1. 創建一個名為createTVPlayerView如下:

    • 38-39行:定義播放器視圖,以便標籤欄面板可以呈現其他視圖控制器。
    • 第42-44行:創建播放器視圖並將其添加到視頻容器視圖。
    • 第47行:將播放器視圖與播放控制器產生關聯。
    • 第 49 行:添加播放器視圖作為主視圖的子視圖。
    • 第51行:關自動調整掩碼 .
    • 第52-57行:使用「自動佈局」來定義播放器視圖的動態約束。

    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
    }()

創建一個初創函數

  1. 創建一個init功能如下:
    • 第64行:調用 init()函數的超類實現。
    • 第 65 行:選用性:將您的視訊雲端帳號 ID 傳送至分析。僅當您覆蓋BCOVVideo類或不使用 Brightcove 回放服務或目錄。

    required init?(coder aDecoder: NSCoder)
    {
      super.init(coder: aDecoder)
      playbackController?.analytics.account = playbackConfig.accountID;
    }

加載視圖後的處理

  1. 在裡面viewDidLoad方法添加以下內容:

    • 第72行:調用requestContentFromPlaybackService函數,我們將在下一步中定義。

    override func viewDidLoad() {
      super.viewDidLoad()
      // Do any additional setup after loading the view, typically from a nib.
    
      requestContentFromPlaybackService()
    }

向布萊特灣圖書館索取內容

為了播放視頻內容,您將從目錄服務請求播放列表

  1. 創建一個名為requestContentFromPlaybackService如下:

    • 第75-76行:根據給定的視頻ID,從Playback API返回視頻對象。
    • 第80行:將視頻添加到播放控制器。
    • 第82行:如果未返回播放列表,則會寫入錯誤消息。
    private func requestContentFromPlaybackService() {
      playbackService.findVideo(withVideoID: playbackConfig.videoID, parameters: nil) { [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")")
        }
      }
    }

延伸播放控制器

這可讓您的應用程式聆聽和回應視訊播放事件。

  1. 擴展視圖控制器以包含 Brightcove 播放控制器委託,並監聽播放事件。如果您是 swift 的新手,請查看有關的指南擴展 .

    // 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)
      }
    }

剩下的

  1. 建立功能來處理舊版 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! ] : [])
      }
    }

檢視程式碼

視圖控制器現在已完成。這是完整的代碼:

//
//  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(withVideoID: playbackConfig.videoID, parameters: nil) { [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! ] : [])
  }
}

匯入原生 SDK

雖然 iOS 的布萊特灣本機播放器 SDK 是用 Obj-C 編寫的,我們可以簡單地導入框架模塊到我們的 Swift 項目。

  1. 低於現有的import指令,添加以下內容以導入 Brightcove Native Player SDK:

    import BrightcovePlayerSDK

使用您的價值自訂專案

添加您的視頻雲帳戶ID的值。

fileprivate struct playbackConfig {
    static let accountID = "your account id"
}

建立視圖變數

  1. 在裡面ViewController類,為視圖添加一個變量。

    class ViewController: UIViewController {
      @IBOutlet weak var videoContainerView: UIView!

建立播放控制器

  1. 建立定義 Brightcove 播放控制器的變數。這將在第一次被調用時創建。

    • 第22至24行:設置代理並打開自動前進和自動播放功能。

    lazy var playbackController: BCOVPlaybackController? = {
      guard let _playbackController = BCOVPlayerSDKManager.shared().createPlaybackController() else {
        return nil
      }
      _playbackController.delegate = self
      _playbackController.isAutoAdvance = true
      _playbackController.isAutoPlay = true
    
      return _playbackController
    }()

定義播放器檢視

  1. 創建playerView如下:

    • 第32-33行:定義播放器視圖,以便標籤欄面板可以呈現其他視圖控制器。
    • 第 36-38 行:創建播放器視圖並將其添加到視頻容器視圖。
    • 第41行:將播放器視圖與播放控制器產生關聯。
    • 第 43 行:添加播放器視圖作為主視圖的子視圖。
    • 第 45 行:關自動調整掩碼 .
    • 第 46-51 行:使用「自動佈局」來定義播放器視圖的動態約束。

    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
    }()

創建一個初創函數

  1. 創建一個init功能如下:
    • 第 58 行:調用 init()函數的超類實現。
    • 第 59 行:將您的視訊雲端帳號 ID 傳送至分析。這會向Brightcove註冊您的應用程序。

    required init?(coder aDecoder: NSCoder)
    {
      super.init(coder: aDecoder)
      playbackController?.analytics.account = playbackConfig.accountID;
    }

播放影片

  1. 在裡面viewDidLoad方法添加以下內容:

    • 67-69行:使用 url 路徑創建一個視頻源數組。
    • 第71行:將視頻陣列添加到控制器的播放隊列中,該隊列設置為自動開始播放。

    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);
    }

設定影片來源的傳送方式

  1. 創建一個函數來設置交付方式BCOVSources屬於視頻。

    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!
    }

延伸播放控制器

這可讓您的應用程式聆聽和回應視訊播放事件。

  1. 擴展視圖控制器以包含 Brightcove 播放控制器委託,並監聽播放事件。如果您是 swift 的新手,請查看有關的指南擴展 .

    // 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)
      }
    }

剩下的

  1. 建立功能來處理舊版 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! ] : [])
      }
    }

檢視程式碼

視圖控制器現在已完成。這是完整的代碼:

//
//  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! ] : [])
  }
}

連接故事板檢視

連接Main.storyboard查看與videoContainer財產。

  1. 在 Xcode 中,打開Main.storyboard文件。

  2. 在配套視圖中,展開查看控制器場景然後是視圖控制器菜單顯示看法目的。

    分鏡板檢視
    分鏡板檢視
  3. 點擊在右側添加編輯器,並打開ViewController.swift文件。

    助理編輯器
    助理編輯器
  4. 選擇旁邊的空心圓圈@IBOutlet為了videoContainerView , 並將其拖至看法對象來連接這些組件。

    連接視圖
    連接視圖

管理媒體安全性

應用程式傳輸安全性 (ATS) 會強制您的應用程式和 Web 服務之間的安全連線。隨著 Apple 發布 iOS 9 SDK,一個名為應用程序傳輸安全 (ATS)加入。

  1. 下列其中一種情況將適用於您的應用程式:

    • 根據預設,iOS 版 Brightcove 原生 SDK 會使用來源選擇原則,透過 HTTP 來源選擇 HTTPS,因此您可以在啟用 ATS 的情況下建置應用程式。

      就是這樣,你已經準備好運行你的應用程序。


    • 如果您正在使用 HTTP 來源或應用程式中有其他 HTTP 呼叫,您可能會遇到下列錯誤訊息:

      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.

      這表示 ATS 已啟用,但您的系統未設定為符合 ATS 需求。要解決這種情況,請參閱使用應用程序傳輸安全 (ATS)文檔。

執行應用程式

該應用程序可以在Apple TV或Xcode Simulator上構建並運行。您應該能夠使用遙控器播放和導航指定的視頻。

蘋果電視範例
蘋果電視範例

Apple TV UI控件

現在,您準備好了解有關Apple TV播放控件的更多信息,包括用於視頻信息,字幕和音頻的頂部欄視圖。有關詳細信息,請參閱使用適用於 tvOS 的本機 SDK 的 Apple TV UI 控件文檔。

有關如何構建您自己的自定義頂部欄項目視圖的詳細信息,請參閱Apple TV 播放器示例 .