티스토리 뷰
그동안 궁금했었던 부분들에 대해 공부하는 시간을 가져보던 중 평소 관심있었던 부분인 뮤직 플레이어를 만들어 보고 싶었다.
FLO의 플레이어 뷰를 보면 기능 요구사항은 다음과 같다.
- 플레이어 컨트롤 버튼
- 시간에 따른 가사 자동 스크롤
- 가사를 탭 했을 때 해당 부분으로 이동
- 음악 정보(이미지, 곡 정보 등)
사용한 프레임워크와 앱의 구조를 살펴보자
1. AVFoundation
AVFoundation은 [ CoreAudio / CoreVideo / CoreMedia / CoreAnimation ] 위에 있는 프레임워크다.
Core 패밀리들은 iOS 혹은 MacOS 등에서 하드웨어와 함께 Low-Level 로 동작하는 프레임워크들이고(C 기반),
AVFoundation은 Core 패밀리 위에서 멀티미디어 등에서의 동작을 추상화하여 제공한다.
몰랐던 사실인데, AVKit은 UIKit/AppKit 위에서 동작한다. 즉, Player의 UI까지 제공하는 프레임워크이다.
FLO 앱 같은 경우는 커스텀한 플레이어기 때문에 AVFoundation을 활용한다.
2. AVPlayer vs AVAudioPlayer 어떤걸로 플레이 할까?
이전에 간단한 효과음 재생에 AVAudioPlayer를 사용했던 적이 있다.
간단한 코드만으로 재생을 했었던 기억이 있는데, 이번 기회에 조금 더 자세히 알아보았다.
- AVAudioPlayer
AVAudioPlayer는 'An object that plays audio data from a file or buffer' 라고 공식문서에서 설명하고 있다.
즉, 파일이나 버퍼에서 오디오 데이터를 읽어서 플레이 하는 객체다.
파일 기반의 오디오를 재생하는데 최적화 되어 있으며, 오디오를 메모리에서 재생하는 방식이므로 짧은 오디오 파일에 적합하다.
- AVPlayer
AVPlayer는 AVAudioPlayer에서 제공하는 파일 기반 오디오 재생을 포함하여 스트리밍 오디오의 플레이도 제공한다(비디오도 가능)
콘텐츠 전체를 메모리에 올리는 방식이 아닌 필요한 부분만을 올리며 관리한다.
--
AVAudioPlayer는 AVPlayer에 비교해 더욱 간단하게 사용 가능한 메소드를 제공하고 있었다. 하지만
1. 메모리 관리 측면
2. 추후 앱 확장시 실시간 스트리밍 추가될 경우
3. AVAudioPlayer는 파일 재생에 최적화
등을 보았을 때 AVPlayer가 더욱 적합하다고 판단했다.
3. Application 구조
- MusicPlayer
앱에서 음악 재생을 단 하나여야만 한다. 또한, 여러 뷰를 왔다갔다 할 때도 상관없이 그대로 재생이 되어야 한다.
그렇기 때문에 음악 재생을 담당하는 MusicPlayer 객체는 단 하나만 존재하도록 했다.
- 애플리케이션 아래에 앱의 핵심 기능인 MusicPlayer을 싱글톤으로 구현했다.
- MusicPlayer 내부의 AVPlayer 에서는 음악을 재생하지만, 단독으로 파일을 가져오거나 재생을 할 수는 없으며 외부에서 파일을 넣어서 재생시켜주어야 한다.
- AVPlayer에서는 KVO(Key-Value-Object) 를 통해 상태값과 플레이중인 타임코드를 옵저빙 하고, 이는 RxSwift를 활용한 Observable로 들어가게 된다.
- 이후, 각 뷰에서는 MusicPlayer의 Observable들을 각각 subscribe 하여 뷰에 표시한다.
- Player & Lyric View
구현할 뷰는 플레이어 뷰와 가사 뷰로 두가지다. 해당 뷰에서는 유저에게 음악의 정보를 알려주는 것과 함께 유저 인터랙션을 통해 MusicPlayer를 조작할 수 있도록 구현했다.
- MusicPlayer의 Observable을 각각 subscribe 하여 뷰에 표시한다. (현재 시간, 타임라인, 가사 등)
- SeekBar를 통해 유저가 의도하는 타임라인으로 음악 재생 타이밍 이동 (Seek 기능)
소스코드: https://github.com/jisu15-kim/FloMusicPlayer
FLO 앱을 만들면서 했던 고민, 구현했던 내용들을 추후 작성해보려고 한다.
'iOS' 카테고리의 다른 글
[iOS] FLO 앱 만들기(3) - AVPlayer의 상태값 받아오기(KVO) (0) | 2023.10.16 |
---|---|
[iOS] FLO 앱 만들기(2) - 재사용을 고려한 플레이어 버튼 만들기 (0) | 2023.10.14 |
[iOS] URL과 전화번호를 인식하는 Label View 만들기(TextView, dataDetectorTypes, LineBreakStrategy) (0) | 2023.10.13 |
[iOS] 함수형 프로그래밍을 클로저로 적용한 간단한 UI 만들어보기 (0) | 2023.10.13 |
[iOS] Push Notification으로 화면 전환하기 (0) | 2023.10.13 |
- Total
- Today
- Yesterday
- SwiftUI
- 2024년
- Xcode
- avplayer
- musicplayer
- auth
- AVFoundation
- watchOS
- easy cue
- demical
- keyboardtype
- 애플워치 데이터 전송
- KVO
- swift날짜
- 회고
- DateFormatter
- IOS
- OAS
- open-api-generator
- 토큰
- watch connectivity
- TextField
- retry
- 애플워치
- openapi-generator
- 소수점
- flo
- Xcode15
- locale
- Swift
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |