단계별: 스위프트를 사용하여 간단한 TV 비디오 앱

이 주제에서는 Apple TV 또는 Xcode 시뮬레이터에서 재생할 수 있는 tvOS용 브라이트코브 플레이어 SDK를 사용하여 간단한 비디오 재생 앱을 빌드하는 방법을 배웁니다. 당신은 스위프트 프로그래밍 언어를 사용하여 구축 할 것입니다.

개요

이 예는 Brightcove 재생 API , Video Cloud 라이브러리에서 콘텐츠를 검색하기 위한 최신 권장 API입니다.

이 예제에서는 비디오 파일의 내부 배열에서 비디오를 재생합니다.

Playback API를 사용하려면 정책 키가 필요합니다. 정책 키에 익숙하지 않은 경우정책 API 개요를 참조하십시오 .

시작하기

다음 단계에 따라 tvOS용 브라이트코브 플레이어 SDK를 사용하는 앱 프로젝트를 설정하는 방법을 익힐 수 있습니다. 다음 각 항목에 대한 전체 코드를 볼 수 있습니다.

  1. 앱델리게이트
  2. ViewController

이 샘플을 시험해보는 방법에는 두 가지가 있습니다.

샘플 다운로드

실험을 위해 전체 Xcode 프로젝트를 다운로드하십시오.

  1. iOS용 Native SDK 샘플을로컬 시스템에 복제하거나 다운로드합니다.
  2. 플레이어/애플TV/Swift샘플 앱으로 이동합니다.
  3. pod install명령을 실행합니다.
  4. 새로 만든 작업공간을 열고 실행합니다.

자세한 내용은 iOS/tvOS용 네이티브 SDK용 샘플 앱실행문서를 참조하십시오.

이 가이드의 단계에 따라 앱 빌드

다음 단계에 따라 tvOS용 브라이트코브 플레이어 SDK를 사용하는 앱 프로젝트를 설정하는 방법을 익힐 수 있습니다. 다음 각 항목에 대한 전체 코드를 볼 수 있습니다.

  1. 앱델리게이트
  2. 뷰 컨트롤러

프로젝트 만들기

Xcode에서 프로젝트를 설정하십시오. 그런 다음 프로젝트에 종속성과 함께 SDK를 추가하십시오.

Xcode 프로젝트 설정

앱을위한 새 Xcode 프로젝트를 만듭니다.

  1. Xcode에서 새 tvOS 프로젝트 생성을 시작합니다. 새 Xcode 프로젝트만들기를 선택합니다 .

    프로젝트 만들기
    프로젝트 만들기
  2. 선택하다 tvOS그런 다음템플릿을 위해. 다음을 클릭합니다 .

    프로젝트 템플릿 선택
    프로젝트 템플릿 선택
  3. 프로젝트 정보를 다음과 같이 설정합니다.

    • 제품 이름: 간단한 비디오 재생
    • 팀:없음

      팀 필드는 선택 사항입니다. App Store에 앱을 배포하려면 Apple 개발자 프로그램을 통해 자신이 속한 팀을 선택해야 합니다. 팀 이름은 코드 서명에 필요합니다. 이 예에서는 없음을 선택합니다.

    • 조직 식별자: com.your-company-name
      이렇게 하면 앱 스토어의 제품 이름이 고유해집니다.
    • 상호 작용: 스토리 보드

      Storyboard 또는 SwiftUI 인터페이스를 사용합니다.

    • 언어: 스위프트
    프로젝트 정보 추가
    프로젝트 정보 추가

    다음을 클릭합니다 .

  4. 프로젝트를 저장할 위치를 선택하고 만들기를 클릭합니다.

    프로젝트 만들기
    프로젝트 만들기
  5. 이제 프로젝트를 닫습니다 (예, 닫으세요. 중요합니다!)

SDK 및 해당 종속성을 프로젝트에 추가하십시오.

SDK 및 해당 종속성을 프로젝트에 추가하는 가장 쉬운 방법은 CocoaPod를 사용하는 것입니다.

CocoaPods는 프로젝트에 라이브러리를 추가하는 종속성 관리자입니다. 필수는 아니지만 설치가 더 쉽습니다. CocoaPods를 설치하려면 CocoaPods사이트의 지침을 참조하십시오.

  1. 프로젝트 폴더에서 Podfile이라는 일반 텍스트 파일을 생성합니다 (파일 확장자 없음).

  2. 텍스트 편집기를 사용하여 Podfile에 다음 코드 줄을 추가하고 저장합니다. 이 코드는 다음을 수행합니다.

    • 라인 1: CocoaPods 포드 사양의 GitHub 위치를 가리킵니다.
    • 라인 2: Brightcove 포드 사양에 대한 GitHub 위치를 가리킵니다.
    • 4번째 줄: 정적 라이브러리 대신 프레임워크를 사용하도록 포드를 설정합니다.
    • 라인 6: tvOS 플랫폼 버전을 정의합니다.
    • 8-10행: 브라이트코브 네이티브 플레이어 SDK를 설치합니다.

      • 종속성 관리에 대한 자세한 내용은 CocoaPods로 종속성을 관리하는방법문서를 참조하십시오.
    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

    Return 키를눌러 실행하십시오.

    CocoaPods가 포드와 호환되는 버전을 찾을 수 없거나 최신 버전이 아닌 경우 터미널 앱에서 다음을 실행 해보십시오.

      pod update

    터미널에 브라이트코브 플레이어 SDK가 프로젝트에 추가되었음을 나타내는 일련의 메시지가 표시됩니다.

  5. pod install명령은 프로젝트의.xcworkspace파일을 만듭니다.

    중요한 마지막줄에 주목하세요. 이 시점부터 다음을 수행해야 합니다.

    • Xcode에서 Simple-Video-Playback.xcworkspace 파일 열기
    • 하다 ~ 아니다사용단순 비디오 재생.xcodeproj파일
    작업공간
    작업공간

비디오 앱 코딩

간단한 비디오 재생 앱의 코드를 만듭니다.

앱의 오디오 비헤이비어 설정

오디오 세션은 앱 수준에서 오디오 동작을 처리합니다. AVAudioSession클래스에 대해 자세히 알아보십시오.

이 샘플에서는재생범주를 사용합니다. 화면이 잠겨 있고 링/무음 스위치가 무음으로 설정된 경우에도 오디오가 재생됩니다. 비디오를 재생하고 있으므로 MoviePlayback모드를 사용합니다. 간단하게 유지하기 위해, 우리는 응용 프로그램 대리자에이 코드를 넣을 것입니다.

  1. 프로젝트에서 앱 델리게이트 파일 ( 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:.
      }
    
    }

뷰 컨트롤러 빌드

Brightcove Playback API에서 비디오를 재생하려면 View Controller 클래스를 업데이트하십시오.

원격 URL에서 비디오를 재생하려면 View Controller 클래스를 업데이트하십시오.

  1. 프로젝트에서 뷰 컨트롤러 파일 ( ViewController.swift ) 을 엽니다.

네이티브 SDK 가져오기

iOS용 브라이트코브 네이티브 플레이어 SDK는 Obj-C로 작성되었지만 프레임워크 모듈을 Swift 프로젝트로 간단히 가져올 수 있습니다.

  1. 기존import디렉티브 아래에 다음을 추가하여 브라이트코브 네이티브 플레이어 SDK를 임포트하십시오.

    import BrightcovePlayerSDK

가치로 프로젝트를 사용자 정의하십시오.

값을 추가하여 Video Cloud 계정에 액세스합니다.

  1. import지시문 아래에 다음과 같은 값을 직접 추가하십시오.

    • 라인 12: 브라이트코브 재생 API 정책 키를 정의합니다. 이 예는 Brightcove 재생 API , Video Cloud 라이브러리에서 콘텐츠를 검색하기 위한 최신 권장 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. 브라이트코브 재생 컨트롤러를 정의하는 변수를 만듭니다. 이것은 처음 호출 될 때 생성됩니다.

    • 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 Playback 서비스 또는 카탈로그를 사용하지 않는 경우에만 필요합니다.

    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를 기반으로 재생 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. 뷰 컨트롤러를 확장하여 브라이트코브 재생 컨트롤러 대리자를 포함시키고 재생 이벤트를 수신합니다. 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디렉티브 아래에 다음을 추가하여 브라이트코브 네이티브 플레이어 SDK를 임포트하십시오.

    import BrightcovePlayerSDK

가치로 프로젝트를 사용자 정의하십시오.

Video Cloud 계정 ID의 값을 추가하십시오.

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

뷰 변수 만들기

  1. ViewController클래스에서 뷰의 변수를 추가합니다.

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

재생 제어기 만들기

  1. 브라이트코브 재생 컨트롤러를 정의하는 변수를 만듭니다. 이것은 처음 호출 될 때 생성됩니다.

    • 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. 뷰 컨트롤러를 확장하여 브라이트코브 재생 컨트롤러 대리자를 포함시키고 재생 이벤트를 수신합니다. 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 (앱 전송 보안) 는 앱과 웹 서비스 간에 보안 연결을 적용합니다. Apple이 iOS 9 SDK를 출시하면서앱 전송 보안 (ATS) 이라는 새로운 기능이추가되었습니다.

  1. 다음 상황 중 하나가 앱에 적용됩니다.

    • 기본적으로 iOS용 브라이트코브 네이티브 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에서 빌드하고 실행할 준비가되었습니다. 리모컨을 사용하여 지정된 비디오를 재생하고 탐색 할 수 있어야합니다.

애플 TV 샘플
애플 TV 샘플

Apple TV UI 컨트롤

이제 비디오 정보, 자막 및 오디오에 대한 상단 표시 줄보기를 포함하여 Apple TV 재생 컨트롤에 대해 자세히 알아볼 준비가되었습니다. 자세한 내용은 tvOS용 네이티브 SDK가 포함된 Apple TV UI 컨트롤문서를 참조하십시오.

사용자 지정 상단 막대 항목 보기를 만드는 방법에 대한 자세한 내용은 Apple TV 플레이어 샘플을 참조하십시오 .