-
AVFoundation (feat. AVAudio)Swift 2023. 8. 25. 09:12
안녕하세요. 그린입니다 🍏
이번 포스팅에서는 AVFoundation에 대해 기초를 알아보며 AVAudio 부분을 조금 더 개념적으로 파보려합니다 🙌
이전 포스팅에서 음성을 녹음하고 플레이하는 AVAudio를 실제 코드로 구현하면서 다룬적이 있어요!
거기서 AVFoundation을 조금 더 딥하게 다음 포스팅에서 얘기해본다고 했습니다.
그날이 오늘입니다!!!!!
AVFoundation
우선 AVFoundation이 뭐하는 녀석인지부터 공식문서를 보면서 살펴볼께요.
AVFoundation은 시청각 asset으로 작업하고, 카메라 장치를 컨트롤하며, 오디오를 처리하고, 시스템 오디오 인터랙션을 구성합니다.
iOS에서의 AVFoundation은 Core 프레임워크쪽에 속해있습니다.
보시면 오늘 다뤄볼 Audio-only classes가 보이는데요.
여기서 오디오를 실제로 녹음하거나 재생하고 컨트롤 하는 등의 역할을 하는 AVAudioRecorder와 AVAudioPlayer가 포함되어있죠!
그런데 저기 보시면 AVKit이라는것도 UIKit의 상위로 존재하게 됩니다.
AVFoundation은 코어쪽에 속하니 사실 이를 가지고 화면을 구현하기란 여간 어려운게 아닙니다.
그렇기에 AVKit이 이러한 UI 구현을 위해 인터페이스를 제공해줘요.
즉, 우리가 보다 편리하게 미디어를 화면에서 다룰 수 있도록 도와주는 역할을 해줍니다.
자 그럼 이어서 이런 시청각 Asset들로 작업을 해야한다고 했습니다.
그렇기에 이러한 미디어를 객체화 시켜주는 AVAsset에 대해 한번 볼께요!AVAsset
공식문서에서는 시간이 지정된 시청각 미디어를 모델링하는 객체라고 합니다.
class AVAsset : NSObject
이러한 선언을 가지구요.
Asset은 QuickTime 동영상이나 MP3 오디오 파일과 같은 파일 기반 미디어와 HLS (HTTP Live Streaming)을 사용해 스트리밍된 미디어를 모델링합니다.
Asset은 균일하게 입력된 미디어 트랙을 모델링하는 하나 이상의 AVAssetTrack 인스턴스에 대한 컨테이너 객체에요.
아래와 같이 말이죠!
보시면 가장 일반적으로 사용되는 트랙은 비디오나 오디오지만 캡션이라던지 자막 및 시간 등과 같은 보충 트랙도 포함할 수 있습니다.
쉽게 정리하자면 비디오, 오디오와 같은 즉 미디어라 불릴 것들에 대한 데이터의 부분들을 트랙이라고 하죠.
Asset의 트랙 속성을 비동기적으로 로드해 Asset의 트랙을 로드할 수 있습니다.
여기서 비동기적으로 로드하는 이유는 미디어 파일이기에 사이즈가 크기 때문입니다.
이렇게 AVAsset을 알아봤으면 다음으로 이 asset을 실제 재생하고 컨트롤해주는 AVPlayer를 살펴봐야 합니다 🙌
AVPlayer
AVPlayer는 플레이어의 전송 동작을 제어하기 위한 인터페이스를 제공하는 객체입니다.
class AVPlayer : NSObject
이런 선언을 가지구요.
플레이어는 미디어 Asset의 재생 및 타이밍을 관리하는 컨트롤러 객체에요.
즉, AVPlayerQuickTime 동영상, MP3 오디오 파일 등의 로컬 및 원격 파일 기반 미디어 및 HLS를 사용해 제공되는 미디어까지 재생할때 사용되는 플레이어입니다.
해당 플레이어를 사용하면 한번에 하나의 미디어 Asset을 재생합니다.
그렇기에 동일 해당 플레이어 인스턴스를 재사용할 수 있지만 한번에 하나의 미디어만 재생 관리합니다.
AVPlayer 자체는 비시각적인 객체로 화면에 그대로 표시할 수 없죠.
그렇기에 우리는 이를 이용해 화면에 표시하기 위해서는 AVKit이나 AVPlayerLayer 방식을 통해 시각적으로 표현할 수 있습니다.
즉 구성은 이렇게 되어 있는것을 확인할 수 있는데요.
여기서 소개를 안한 부분이 AVPlayerItem입니다.
바로 AVPlayerItem 알아보시죠!
AVPlayerItem
AVPlayerItem은 재생 중 Asset의 타이밍 및 프레젠테이션 상태를 모델링하는 객체입니다.
class AVPlayerItem : NSObject
선언은 이러하며, 쉽게 말해서 시간과 그에 따른 현재 미디어의 상태 정보를 가지고 있는 객체라고 볼 수 있습니다.
AVAsset은 그 자체로 미디어가 가진 모든 정보가 포함되어 있다면, AVPlayerItem은 시간 경과에 따라 현재 상태 정보를 담고 있습니다.
자 그럼 AVFoundation에서는 이정도로 개념을 잡고 다음 스텝인 실제 로컬에서 오디오를 녹음하고 재생하는 등의 기능을 관장할 AVAuidoRecorder와 AVAudioPlayer에 대해 알아보시죠!
참고로 녹음 및 재생에 관해서는 아래 포스팅에서 실제 구현부를 다뤘습니다.
여기서는 개념적인 설명이니 실제 구현이 궁금하신분들은 아래 포스팅을 참고해주세요!
먼저 재생을 하기 위해서는 녹음을 해야하죠?
AVAudioRecorder부터 알아보겠습니다.
AVAudioRecorder
오디오 데이터를 파일에 녹음하는 객체입니다.
class AVAudioRecorder : NSObject
선언은 요러하며, 해당 객체를 사용하면 아래와 같은 작업들을 할 수 있어요.
1️⃣ 시스템의 입력 장치를 통해 오디오 녹음
2️⃣ 사용자가 중지하거나 지정된 시간이 될 때까지 녹음
3️⃣ 녹음 일시 정지 및 재개
4️⃣ 녹음 수준 측정 데이터에 액세스
만약 녹음된 오디오에 신호 처리를 적용하거나 조금 더 고급화된 녹음 기능을 사용하고 싶다면 AVAudioEngine을 사용할 수 있습니다.
예를들어, 목소리 변조 등과 같은 기능을 제공해주죠!
실제 아래 메서드와 프로퍼티를 이용해 녹음을 제어할 수 있습니다.
아래 소개드리는것은 거의 필수로 사용되는 중요한 기능들이며 이 외 더 많은 메서드 및 프로퍼티들이 있으니 공식문서를 참고해보시길 권장합니다 🙋🏻
오디오 파일 생성 및 녹음을 위한 시스템 준비
func prepareToRecord() -> Bool
오디오 녹음 시작 및 재개
func record() -> Bool
특정 시간부터 오디오 녹음 시작
func record(atTime: TimeInterval) -> Bool
표시된 시간 동안 오디오 녹음
func record(forDuration: TimeInterval) -> Bool
표시된 기간 동안 특정 시간부터 오디오 녹음
func record(atTime: TimeInterval, forDuration: TimeInterval) -> Bool
오디오 녹음 일시 중지
func pause()
오디오 녹음 중지
func stop()
녹음된 오디오 파일 삭제
func deleteRecording() -> Bool
녹음 중 여부 판별 변수
var isRecording: Bool
이제 그럼 녹음을 해봤으니, 재생을 해봐야겠죠??
AVAudioPlayer
파일이나 버퍼에서 오디오 데이터를 재생하는 객체입니다.
class AVAudioPlayer : NSObject
해당 오디오 플레이어에서는 아래와 같은 기능들을 수행할 수 있어요.
1️⃣ 파일이나 버퍼에서 원하는 기간의 오디오 재생
2️⃣ 재생되는 오디오의 볼륨, 패닝, 속도 및 반복 동작 등을 제어
3️⃣ 재생 수준 측정 데이터에 액세스
4️⃣ 여러 플레이어의 재생을 동기화하여 여러 사운드를 동시에 재생
녹음과 마찬가지로 스트리밍 재생이나 positional 오디오와 같은 고급 기능을 사용하려면 AVAudioEngine을 사용할 수 있습니다.
대게 보통은 실시간으로 스트리밍하는 오디오는 AVPlayer를 이용하며, 우리가 레코딩을 통해 녹음한 로컬 파일의 재생들은 AVAudioPlayer를 이용할 수 있습니다.
그럼 실제 오디오 재생 및 컨트롤을 위한 메서드 및 프로퍼티를 살펴볼께요!
아래 소개드리는것은 거의 필수로 사용되는 중요한 기능들이며 이 외 더 많은 메서드 및 프로퍼티들이 있으니 공식문서를 참고해보시길 권장합니다 🙋🏻
오디오 재생을 위해 플레이어 준비
func prepareToPlay() -> Bool
오디오 비동기적으로 재생
func play() -> Bool
오디오를 지정된 지점에서 시작해 비동기적 재생
func play(atTime: TimeInterval) -> Bool
오디오 재생 일시 정지
func pause()
오디오 재생 중지
func stop()
오디오가 현재 재생되고 있는지에 대한 여부 변수
var isPlaying: Bool
마무리
자 이렇게 알아봤씁니다!
물론 더 더 알아볼것이 많지만 일단 1페이즈 입니다.
AVFoundation을 톺아보면서 어떻게 구성되어 있고 대략적인 플로우를 파악해보면서 사실 관심 있었던 AVAudio 파트에 대해 다가가는 첫걸음이 되었어요!
다음 페이즈도 기대해주세요 😉
참고 레퍼런스
https://developer.apple.com/documentation/avfoundation/
https://developer.apple.com/documentation/avfoundation/avasset
https://developer.apple.com/documentation/avfoundation/avplayer/
https://developer.apple.com/documentation/avfoundation/avplayeritem
https://developer.apple.com/documentation/avfaudio/avaudiorecorder
https://developer.apple.com/documentation/avfaudio/avaudioplayer
'Swift' 카테고리의 다른 글
Debouncer 만들기 (No Combine, No RxSwift) (48) 2023.10.09 Colletcion은 Struct 타입인데 Heap에 저장되는 이유? (55) 2023.09.25 Swift HTTP Types 찍먹하기 (4) 2023.07.31 available 심층 탐구하기 (16) 2023.07.17 Expand on Swift macros (feat. WWDC 2023) (6) 2023.06.10