AVPlayerViewController를 이용하면 너무나도 쉽고 간편하게 영상을 재생시킬 수 있지만, 우리는 커스텀을 해서 앱에 적용시켜야 하기 때문에 AVPlayerLayer를 사용할 것이다.
// 먼저 AVPlayerLayer가 있는 VideoView class를 만들어준다.
// AVPlayerLayer는 VideoView에 가득차게 만들어 질 것이다.
final class VideoView: UIView {
private let playerLayer: AVPlayerLayer = AVPlayerLayer()
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = .systemBlue
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func layoutSubviews(_ view: UIView) {
super.layoutSubviews()
playerLayer.frame = view.bounds
}
func setLayoutSubViews(_ view: UIView) {
playerLayer.frame = view.bounds
}
func setLayout() {
self.layer.addSublayer(playerLayer)
}
func setPlayer(_ player: AVPlayer) {
playerLayer.player = player
playerLayer.videoGravity = .resizeAspectFill
}
func playVideo() {
playerLayer.player?.play()
}
}
위와 같은 방식으로 AVPlayerLayer를 VideoView라는 Class에 넣어 관리한다.
final class ViewController: UIViewController {
private var video: Video!
private var videoView: VideoView = VideoView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(videoView)
videoView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
videoView.topAnchor.constraint(equalTo: view.topAnchor),
videoView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
videoView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
videoView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
override func viewDidAppear(_ animated: Bool) {
setVideoView()
videoView.playVideo()
}
func createVideo() -> Video {
let url: URL = URL(string: "<https://devstreaming-cdn.apple.com/videos/wwdc/2018/103zvtnsrnrijr/103/hls_vod_mvp.m3u8>")!
return Video(hlsURL: url, title: "테스트")
}
// AVPlayerItem에 영상 URL을 담아준 후 이 AVPlayerItem을 담은 AVPlayer를 넣어주면 끝!
func setVideoView() {
let video: Video = createVideo()
let item: AVPlayerItem = AVPlayerItem(url: video.hlsURL)
let player: AVPlayer = AVPlayer(playerItem: item)
videoView.setLayout()
videoView.setPlayer(player)
videoView.layoutSubviews(view)
}
}
위와 같은 과정을 거치면
옆에 보이는 그림과 같이 AVPlayerLayer가 올바르게 삽입된 것을 알 수 있다.
이렇게 AVPlayerLayer를 사용하여 영상을 재생할 수 있다.
대신 AVPlayerViewController에 비하면 허전한 감을 지울 수 없는데, 이는 개발자가 스스로 원하는 요소들을 넣어 완성할 수 있다.
영상에 필요한 재생바를 넣으려면, UISlider를 이용할 수 있다.
UISlider는 위와 같은 구조로 이루어져 있는데, Thumb를 기준으로 Track의 컬러나 ThumbImage등을 변경할 수 있다.
UISlider와 동영상을 동기화시키면 동영상 재생의 위치에 따라 Thumb도 같이 움직일 수 있을 것이다.
UISlider와 AVPlayer를 동기화시키기 위해서는 addPeriodicTimeObserver
가 필요하다.
addPeriodicTimeObserver는 “재생 중에 지정된 블록의 주기적 호출을 요청하여 변경 시간을 보고합니다.”
라고 되어 있다.
func addPeriodicTimeObserver() {
// Invoke callback every half second
let interval = CMTime(seconds: 0.5,
preferredTimescale: CMTimeScale(NSEC_PER_SEC))
// Add time observer. Invoke closure on the main queue.
timeObserverToken =
player.addPeriodicTimeObserver(forInterval: interval, queue: .main) {
[weak self] time in
// update player transport UI
}
}