ios AVPlayerLayer 사용해보기
import UIKit
import AVFoundation
class ViewController: UIViewController {
@IBOutlet weak var videoView: UIView!
var player = AVPlayer()
var playerLayer = AVPlayerLayer()
var isVideoPlaying = false
@IBOutlet weak var playButton: UIButton!
@IBOutlet weak var currentTimeLabel: UILabel!
@IBOutlet weak var durationLabel: UILabel!
@IBOutlet weak var timeSlider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
//재생할 파일 URL
guard let url = URL(string:"https://file-examples.com/storage/fef1706276640fa2f99a5a4/2017/04/file_example_MP4_640_3MG.mp4") else {
return
}
///AVPlayer 초기화
self.player = AVPlayer(url: url)
self.player.volume = 0.0
self.timeSlider.value = 0
self.timeSlider.minimumValue = 0
self.playerLayer = AVPlayerLayer(player: player)
self.playerLayer.videoGravity = .resizeAspectFill
videoView.layer.addSublayer(playerLayer)
/// 재생준비 완료를 위한 옵저버
if let curItem = self.player.currentItem{
curItem.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: [.old, .new], context: nil)
}
/// AVPlayer는 시간 변화를 관찰하기 위해 addPeriodicTimeObserver 메소드를 제공한다.
let interval = CMTime(seconds: 0.01, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
self.player.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main) { [weak self] currentTime in
/// 재생 후 0.01초 간격으로 Slider를 업데이트 함.
if let curTime = self?.player.currentItem?.currentTime(){
self?.updateSlider(curTime)
self?.updateCurrentTimeText(curTime)
}
}
/// 비디오 종료 체크를 위한 콜백 함수 등록
NotificationCenter.default.addObserver(self, selector: #selector(videoFinish), name: .AVPlayerItemDidPlayToEndTime, object: nil)
}
//MARK: 슬라이더 이동
/// 슬라이더 이동 시키기
func updateSlider(_ currentTime:CMTime){
if let currentItem = self.player.currentItem{
let duration = currentItem.duration
self.timeSlider.value = Float(CMTimeGetSeconds(currentTime))
self.timeSlider.maximumValue = Float(CMTimeGetSeconds(duration))
}
}
//MARK: 진행시간표시
/// 진행시간 표시
func updateCurrentTimeText(_ currentTime:CMTime){
/// 현재시간 구하기
self.currentTimeLabel.text = self.getTimeString(roundedSeconds: CMTimeGetSeconds(currentTime))
}
//MARK: 준비
/// 준비완료 체크 옵저버
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == #keyPath(AVPlayerItem.status) {
let status: AVPlayerItem.Status
if let statusNumber = change?[.newKey] as? NSNumber {
status = AVPlayerItem.Status(rawValue: statusNumber.intValue)!
} else {
status = .unknown
}
switch status {
case .readyToPlay:
print("readyToPlay")
/// 전체 시간 구하기
if let currentItem = self.player.currentItem{
let duration = currentItem.duration
self.durationLabel.text = self.getTimeString(roundedSeconds: CMTimeGetSeconds(duration))
}
case .failed:
print("Fail")
case .unknown:
print("unknown")
@unknown default:
fatalError()
}
}
}
//MARK: 비디오 재생끝
@objc func videoFinish(_ notification: Notification){
print("비디오 재생 끝")
let seekTime = CMTimeMake(value: Int64(0.0) * 1000, timescale: 1000)
self.player.seek(to: seekTime)
self.player.pause()
self.currentTimeLabel.text = "00:00"
playButton.setTitle("재생", for: .normal)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.playerLayer.frame = self.videoView.bounds
}
//MARK: 슬라이더 이벤트
/// 슬라이더 이벤트
@IBAction func didChangedProgressBar(_ sender: UISlider) {
/// 재생이 안되어 있는 상태에서 슬라이드 이동시 재생 처리
if !isVideoPlaying {
self.player.play()
playButton.setTitle("정지", for: .normal)
isVideoPlaying = true
}
let seekTime = CMTimeMake(value: Int64(sender.value) * 1000, timescale: 1000)
self.player.seek(to: seekTime)
}
//MARK: 재생버튼
@IBAction func playAction(_ sender: UIButton) {
if isVideoPlaying {
self.player.pause()
sender.setTitle("재생", for: .normal)
}else{
self.player.play()
sender.setTitle("정지", for: .normal)
}
isVideoPlaying.toggle()
}
//MARK: 시간->문자
func getTimeString(roundedSeconds:Float64) -> String{
var hours: Int { return Int(roundedSeconds / 3600) }
var minute: Int { return Int(roundedSeconds.truncatingRemainder(dividingBy: 3600) / 60) }
var second: Int { return Int(roundedSeconds.truncatingRemainder(dividingBy: 60)) }
var positionalTime: String {
return hours > 0 ?
String(format: "%d:%02d:%02d",
hours, minute, second) :
String(format: "%02d:%02d",
minute, second)
}
return positionalTime
}
}
//참고
https://qteveryday.tistory.com/188
https://velog.io/@wannabe_eung/iOS-AVFoundation%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EC%98%81%EC%83%81-%EC%A7%84%ED%96%89%EB%B0%94UISlider-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0
https://wlgusdn700.tistory.com/82
'아이폰 개발 > ios 개념&튜토리얼' 카테고리의 다른 글
ios AVCaptureSession 예제 (0) | 2023.03.20 |
---|---|
ios UIBezierPath 연습 2 (파이차트 그리기) (0) | 2023.03.08 |
ios UIBezierPath 연습 1 (원그리기, 호그리기,선그리기) (0) | 2023.03.07 |
ios 코어 그래픽 1 (1) | 2023.03.04 |
ios 아날로그 시계 만들기 3 (0) | 2023.03.03 |