본문 바로가기

IOS

[IOS] AVPlayer

AVFoundation Framework를 기반으로

MP3파일을 재생하는 과정에 대해 포스팅하겠다.

 

이번 편은 AVPlayer에 대해 다룰것이며 

그 전에 AVFoundation에 대해 먼저 알아보겠다.

 

AVFounation

Apple의 미디어 Framework인 AVFoundation은 
지금 설명하려는 audio playback 기능 말고도
많은 미디어 처리 작업을 제공한다.( video, 카메라, 편집 등등)

또한 이 Framework를 사용하여
HTTP Live Streaming을 통해 
실시간으로 mp3파일을 재생하고 제어할 수 있다.

하지만 AVFoundation은 하단 이미지와 같이 
UIKit Framework보다 Low한 level에 위치해 있어
재생에 관련된 UI를 제공해줄 수 없다. 

 

그리하여 Apple은 
player Interface를 제공하며
보다 빠른 player 프로세스 구축을 마련할수있는
AVKit Framework를 
UIKit 상단에 마련해두었다.

그리고 AVKit의 AVPlayerViewController 사용 코드를 보자면 하단과 같다.

@objc private func didTapButton() {
        var player: AVPlayer?
        let playerController = AVPlayerViewController()
        guard let url = URL(string: "https://......") else {
            print("wrong url")
            return
        }
        player = AVPlayer(url: url)
        playerController.player = player
        playerController.player?.play()
        present(playerController, animated: true, completion: nil)
    }

 

AVKit을 import 한 후 AVPlayerViewController로 MP3 play 구현


개발자가 직접 UI에 관여하지 않아도 

오디오 제어에 대해 접근성이 굉장히 뛰어난걸 볼 수 있다.
하지만 대부분 player를 구현할때

이런 심플한 모습은 원하지 않았을것이다.

 

그리하여 AVPlayerViewController보다 신경써야 할게 많지만 
보다 low한 level인
AVFoundation Framework의 
AVPlayer를 사용하여 
원하는 UI로 player를 커스텀해보겠다.

 

일단 기능구현에 앞서 
mp3URL, button, slider를 준비하고

(필자는 본인 Firebase에 업로드 되어있는 mp3 URL을 사용했다.)
player와 playerItem을 만들도록 하겠다.

let player = AVPlayer()
    
var playerItem: AVPlayerItem?

 

그리고 stream을 진행할 URL을 사용하여 

AVPlayerItem을 만들고

player의 playerItem으로 할당해준다

guard let url = URL(string: "https:......") else {
        print("wrong url")
        return
    }
    playerItem = AVPlayerItem(url: url)
    player.replaceCurrentItem(with: playerItem)
}


다음은 버튼을 터치했을때 Action이다.

이제 해당 URL이 가진 음원이 재생되는걸 볼 수 있을것이다.

@objc private func didTapButton() {
    // timeControlStatus에 따른 분기
    if player.timeControlStatus == .paused {
        player.play()
    } else {
        player.pause()
    }
    button.isSelected.toggle()
}

 

총 재생 시간 표기와 currentTimeLabel, currentTimeSlider의 value set은 아래와 같다.

// duration 
guard let durationTime = self?.player.currentItem?.duration else { return }
let totalSeconds = Int(CMTimeGetSeconds(durationTime))
let seconds = totalSeconds % 60
let minutes = totalSeconds / 60
let timeFormatString  = String(format: "%02d:%02d", minutes, seconds)
self?.durationLabel.text = timeFormatString
// 미디어의 재생시간의 흐름을 알고 싶거나 현재 재생시간에 따라 인터페이스를 변경하고 싶을때
// time은 CMTime 타입의 값으로, 입력한 interval 주기를 가진채로 completion으로 나오게 된다.
let interval = CMTimeMakeWithSeconds(1, preferredTimescale: Int32(NSEC_PER_SEC)) // 1초
player.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self](time) in
    // update currentLabel
    let totalSeconds = Int(CMTimeGetSeconds(time))
    let seconds = totalSeconds % 60
    let minutes = totalSeconds / 60
    let timeFormatString  = String(format: "%02d:%02d", minutes, seconds)
    self?.currentTime.text = timeFormatString

    // update slider
    let currentTimeSeconds = CMTimeGetSeconds(self?.player.currentTime()) // 현재 진행 위치
    let durationSeconds = CMTimeGetSeconds(self?.player.currentItem?.duration ??
                                            CMTimeMake(value: 1, timescale: 1)) // 총 길이
    let percentage = currentTimeSeconds / durationSeconds // 현재 위치 / 총 길이
    self?.songSlider.value = Float(percentage) // set slider value
}

 

 

 

지금까지 AVPlayer로 audio stream을 하는 기본적인 방법에 대해서 알아봤다.

 

다음 포스팅에서는 AVAudioPlayer를 사용한 

audio 재생에 대해 알아보겠다.

'IOS' 카테고리의 다른 글

[IOS] TableView (with Storyboard)  (0) 2021.02.21
[IOS] TableView (with Code)  (0) 2021.02.20
[IOS] Timer  (0) 2021.01.07
[IOS] UserDefaults  (0) 2021.01.05
[IOS] UserInterfaceStyle (2)  (0) 2021.01.04