1. 영상 재생하기

AVPlayerLayer.png

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

위와 같은 과정을 거치면

Simulator Screenshot - iPhone 15 - 2023-12-12 at 01.00.02.png

옆에 보이는 그림과 같이 AVPlayerLayer가 올바르게 삽입된 것을 알 수 있다.

이렇게 AVPlayerLayer를 사용하여 영상을 재생할 수 있다.

대신 AVPlayerViewController에 비하면 허전한 감을 지울 수 없는데, 이는 개발자가 스스로 원하는 요소들을 넣어 완성할 수 있다.

2. 재생 바 넣기

영상에 필요한 재생바를 넣으려면, UISlider를 이용할 수 있다.

UISlider.png

UISlider는 위와 같은 구조로 이루어져 있는데, Thumb를 기준으로 Track의 컬러나 ThumbImage등을 변경할 수 있다.

UISlider와 동영상을 동기화시키면 동영상 재생의 위치에 따라 Thumb도 같이 움직일 수 있을 것이다.

UISlider와 AVPlayer를 동기화시키기 위해서는 addPeriodicTimeObserver 가 필요하다.

스크린샷 2023-12-12 오전 1.18.44.png

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