관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 4. AVFoundation 개념 - AVPlayer, AVPlayerLayer로 동영상 재생 방법 본문

iOS 기본 (swift)

[iOS - swift] 4. AVFoundation 개념 - AVPlayer, AVPlayerLayer로 동영상 재생 방법

jake-kim 2022. 4. 10. 23:05

1. AVFoundation 개념 - 구조, AVAsset, AVKit

2. AVFoundation 개념 - AVPlayer, AVPlayerItem

3. AVFoundation 개념 - AVPlayer 오디오 재생, 일시정지, 재생구간 이동 구현 (play, pause, seek)

4. AVFoundation 개념 - AVPlayer, AVPlayerLayer로 동영상 재생 방법

5. AVFoundation 개념 - AVAudioSession 개념 (오디오 활성화, 입출력 변경, 잠금화면 재생, 재생 중 전화가 온 경우 처리)

AVPlayerLayer

https://developer.apple.com/documentation/avfoundation/avplayerlayer

  • CALayer의 서브클래스이고, 동영상을 재생시킬 수 있는 layer
  • 보통 AVPlayerLayer의 인스턴스를 AVPlayer를 생성자로하여 만든 후, 표현하려는 뷰에 layer.addSublayer로 삽입하여 사용

* 로컬에서 다운받아서 재생하고 싶은 경우에는 AVAudioPlayer 사용 (관련 개념 참고)

사용 방법

  • 비디오 화면이 위치할 커스텀 뷰 VideoView 정의
    • 비디오의 총 길이를 알기 위해서 AVAsset인스턴스 생성
    • AVPlayer 인스턴스 생성
    • AVPlayer 인스턴스를 사용하여 AVPlayerLayer 인스턴스 생성
    • AVPlayerLayer를 view의 layer에 삽입
final class VideoView: UIView {
  // View 생략

 private let url: String
 private var player = AVPlayer()
  
  init(url: String) {
    self.url = url
    super.init(frame: .zero)
    
    // layout 생략
    
    guard let url = URL(string: self.url) else { return }
    let item = AVPlayerItem(url: url)
    self.player.replaceCurrentItem(with: item)
    let playerLayer = AVPlayerLayer(player: self.player)
    playerLayer.frame = self.videoBackgroundView.bounds
    playerLayer.videoGravity = .resizeAspectFill
    self.playerLayer = playerLayer
    self.videoBackgroundView.layer.addSublayer(playerLayer)
    self.player.play()
    
    if self.player.currentItem?.status == .readyToPlay {
      self.slider.minimumValue = 0
      self.slider.maximumValue = Float(CMTimeGetSeconds(item.duration))
    }
    self.slider.addTarget(self, action: #selector(changeValue), for: .valueChanged)
    
    let interval = CMTimeMakeWithSeconds(1, preferredTimescale: Int32(NSEC_PER_SEC))
    self.player.addPeriodicTimeObserver(forInterval: interval, queue: .main, using: { [weak self] elapsedSeconds in
      let elapsedTimeSecondsFloat = CMTimeGetSeconds(elapsedSeconds)
      let totalTimeSecondsFloat = CMTimeGetSeconds(self?.player.currentItem?.duration ?? CMTimeMake(value: 1, timescale: 1))
      print(elapsedTimeSecondsFloat, totalTimeSecondsFloat)
    })
  }
}
  • AVPlayerLayer의 frame 사이즈를 정해주어야 하므로, layoutSubviews에서 frame 정의
override func layoutSubviews() {
  super.layoutSubviews()

  playerLayer.frame = self.videoBackgroundView.bounds
}
  • UISlide를 통해 재생구간을 설정할 수 있도록 구현
    • 재생구간은 AVPlayer의 seek(to:preferredTimescale:) 메소드 사용
@objc private func changeValue() {
  self.player?.seek(to: CMTime(seconds: Double(self.slider.value), preferredTimescale: Int32(NSEC_PER_SEC)), completionHandler: { _ in
  })
}

* 전체 코드: https://github.com/JK0369/ExAVPlayerLayer

 

* 참고

https://developer.apple.com/documentation/avfoundation/avplayerlayer

 

 

Comments