-
AVPlayerLayer 로 영상 재생 (커스터마이즈)카테고리 없음 2023. 5. 9. 00:00
mp4와 같은 영상을 재생할때는 AVPlayer를 사용해야 하는데, 이걸 커스터마이즈 하려면 AVPlayerLayer위에서 작업을 해야함.
이걸로 당연히 유튜브 영상을 재생할거라 생각하고 커스터마이즈를 했는데..... iOS에서 제공해주는 API는 영상 파일의 URL을 받아서 영상을 실행시켜주는 방식인데, 유튜브에서 제공하는 URL은 영상 파일이 아니고 단순한 페이지 라고 한다...
그래서 공식 라이브러리 (youTube-player-ios-helper)나 외부 라이브러리 (youTubePlayer-in-WKWebView)를 사용해서 id값으로 영상을 재생해야 한다...
괜히 작업함 ㅠ아까워서 기록해두기
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 보여지기 직전에 플레이 시킴으로써 뷰에 올라옴과 동시에 보여지게끔 setupVideoPlay(urlString: "https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/m3u8s/11331.m3u8") } // MARK: Extension extension ExerciseContentView { func setupVideoPlay(urlString: String) { let url = URL(string: urlString)! let playerItem = AVPlayerItem(url: url) playerItem.preferredForwardBufferDuration = TimeInterval(1.0) exerciseVideoView.layer.cornerRadius = 8 self.exerciseVideoView.player = AVPlayer(playerItem: playerItem) self.exerciseVideoView.player?.play() } ... } final class customVideoView: UIView { // 해당 뷰의 layer 자체를 속성을 AVPlayerLayer로 변경 override class var layerClass: AnyClass { return AVPlayerLayer.self } // playerLayer에 접근하면 AVPlayerLayer 반환 // layer속성 변경을 위해 한번 더 감싸기 var playerLayer: AVPlayerLayer { let layer = layer as! AVPlayerLayer layer.videoGravity = .resizeAspectFill layer.cornerRadius = 8 return layer } var player: AVPlayer? { get { return playerLayer.player } set { playerLayer.player = newValue } } //----------- 재생/일시정지 버튼 -----------// var playBtn = UIButton() var backBtn = UIButton() var forwardBtn = UIButton() var isPlaying = true override init(frame: CGRect) { super.init(frame: frame) playBtn.setImage(UIImage(named: "play"), for: .normal) backBtn.setImage(UIImage(named: "back"), for: .normal) forwardBtn.setImage(UIImage(named: "forward"), for: .normal) [playBtn, backBtn, forwardBtn].forEach { self.addSubview($0) $0.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) $0.isHidden = true } playBtn.snp.makeConstraints { $0.centerX.centerY.equalToSuperview() $0.height.equalTo(100) } backBtn.snp.makeConstraints { $0.centerY.equalToSuperview() $0.leading.equalToSuperview().inset(20) $0.width.height.equalTo(70) } forwardBtn.snp.makeConstraints { $0.centerY.equalToSuperview() $0.trailing.equalToSuperview().inset(20) $0.width.height.equalTo(70) } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { isPlaying = !isPlaying // false [playBtn, backBtn, forwardBtn].forEach { $0.isHidden = isPlaying } playBtn.setImage(UIImage(named: "pause"), for: .normal) } @objc func buttonTapped(_sender: UIButton) { // isPlaying: false로 시작 isPlaying = !isPlaying let img = isPlaying ? UIImage(named: "play") : UIImage(named: "pause") playBtn.setImage(img, for: .normal) if isPlaying { player?.pause() } else { player?.play() } if _sender == backBtn { seekPlayback(isForward: false) } else if _sender == forwardBtn { seekPlayback(isForward: true) } } let seekDuration: Float64 = 5 private func seekPlayback(isForward: Bool) { guard let player = player, let duration = player.currentItem?.duration else { return } let currentElapsedTime = player.currentTime().seconds var destinationTime = isForward ? (currentElapsedTime + seekDuration) : (currentElapsedTime - seekDuration) if destinationTime < 0 { destinationTime = 0 } if destinationTime < duration.seconds { let newTime = CMTime(value: Int64(destinationTime * 1000 as Float64), timescale: 1000) player.seek(to: newTime) } } }