AVPlayerLayer이란?
이전 포스팅에서 우리는 AVPlayer라는 것을 학습했다.
AVPlayer는 오직 미디어 데이터를 재생하고 컨트롤 할 수 있는 기능을 담당하고 있다.
즉 유저에게 시각적으로 제공되는 역할을 할 수 없다.
바로 그 역할을 도와주는 것이 AVPlayerLayer다
An object that presents the visual contents of a player object.
class AVPlayerLayer : CALayer
역할
1. 비디오 콘텐츠 렌더링
- AVPlayerLayer는 AVPlayer 객체에서 재생되는 비디오 스트림 화면에 표시하는 역할을 한다.
2.비디오 크기 조절
- videoGravity 속성을 통해 비디오 콘텐츠 크기를 조절할 수 있다.
- resizeAspect , resizeAspectFill, resize와 같은 값으로 비디오의 비율을 유지하면서 크기를 맞추고
꽉차게 표시하는 등 설정이 가능하다.
특징
CALayer의 서브클래스
- AVPlayerLayer는 CALayer의 서브 클래스이므로 다른 CALayer 객체와 동일한 방식으로 레이어 계층 구조에 추가된다.
- 애니메이션, 투명도, 회전 등 CALayer 속성을 적용할 수 있다.
코드
총 4단계의 구성으로 이루워져있다.
- 해당 미디어 데이터를 AVAsset 인스턴스 형태로 만들어 메타 데이터를 이용
- AVPlayer 인스턴스를 생성하여 playback 역할을 위임
- AVPlayerLayer 인스턴스 생성 시 AVPlayer 인스턴스 전달
- AVPlayerLayer를 상위 view layer에 추가
import UIKit
import AVFoundation
final class VideoView: UIView {
// View 생략
private var player = AVPlayer()
private var playerLayer: AVPlayerLayer?
private let url: String
init(url: String) {
self.url = url
super.init(frame: .zero)
// 오토레이아웃 생략
guard let url = URL(string: self.url) else { return }
let item = AVPlayerItem(url: url)
self.player.replaceCurrentItem(with: item) // item 지정
let playerLayer = AVPlayerLayer(player: self.player) // player 지정 및 layer 인스턴스 생성
playerLayer.frame = self.videoBackgroundView.bounds // playLayer frame 지정
playerLayer.videoGravity = .resizeAspectFill
self.playerLayer = playerLayer
self.videoBackgroundView.layer.addSublayer(playerLayer) // layer 추가
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)
// 1초를 나노초 단위로 표현한 CMTime
NSEC_PER_SEC: Int64 = 1,000,000,000
let interval = CMTimeMakeWithSeconds(1, preferredTimescale: Int32(NSEC_PER_SEC))
// AVPlayer에서 특정 시간 간격마다 콜백을 실행 , 현재는 1 초
self.player.addPeriodicTimeObserver(forInterval: interval, queue: .main, using: { [weak self] elapsedSeconds in
CMTimeGetSeconds: CMTime to Double
let elapsedTimeSecondsFloat = CMTimeGetSeconds(elapsedSeconds) // 비디오의 현재 재생 시간
let totalTimeSecondsFloat = CMTimeGetSeconds(self?.player.currentItem?.duration ?? CMTimeMake(value: 1, timescale: 1))
print(elapsedTimeSecondsFloat, totalTimeSecondsFloat)
})
}
required init?(coder: NSCoder) {
fatalError()
}
override func layoutSubviews() { // 프레임 적용
super.layoutSubviews()
self.playerLayer?.frame = self.videoBackgroundView.bounds
}
@objc private func changeValue() {
// CMTime 설정
self.player.seek(to: CMTime(seconds: Double(self.slider.value), preferredTimescale: Int32(NSEC_PER_SEC)), completionHandler: { _ in
print("completion")
})
}
}
결과
많이 허전하긴하지만 잘 활용하면 좋은 커스텀 player를 개발 할 수 있을 것 같다.
참고
'iOS > Framework' 카테고리의 다른 글
[ 부스트 캠프 ] Shook 서비스 플레이어 만들기 (0) | 2024.12.01 |
---|---|
AVFoundation (4) [AVAudioSession] (3) | 2024.10.22 |
AVFoundation (2) [AVPlayer, AVPlayerItem] (0) | 2024.10.21 |
AVKit (4) | 2024.10.21 |
AVFoundation (1) [AVAsset] (1) | 2024.10.21 |