Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
29 | 30 | 31 |
Tags
- Clean Code
- Refactoring
- UICollectionView
- 애니메이션
- RxCocoa
- rxswift
- HIG
- 클린 코드
- ios
- Xcode
- swift documentation
- 리팩토링
- 리펙터링
- UITextView
- Human interface guide
- tableView
- collectionview
- swiftUI
- 스위프트
- SWIFT
- uitableview
- combine
- uiscrollview
- ribs
- Observable
- MVVM
- Protocol
- 리펙토링
- map
- clean architecture
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 5. AVFoundation 개념 - AVAudioSession, 녹음기능 구현 방법 (오디오 활성화, 입출력 변경, 잠금화면 재생, 재생 중 전화가 온 경우 처리) 본문
iOS 기본 (swift)
[iOS - swift] 5. AVFoundation 개념 - AVAudioSession, 녹음기능 구현 방법 (오디오 활성화, 입출력 변경, 잠금화면 재생, 재생 중 전화가 온 경우 처리)
jake-kim 2022. 4. 11. 23:291. AVFoundation 개념 - 구조, AVAsset, AVKit
2. AVFoundation 개념 - AVPlayer, AVPlayerItem
3. AVFoundation 개념 - AVPlayer 오디오 재생, 일시정지, 재생구간 이동 구현 (play, pause, seek)
4. AVFoundation 개념 - AVPlayer, AVPlayerLayer로 동영상 재생 방법
5. AVFoundation 개념 - AVAudioSession 개념 (오디오 활성화, 입출력 변경, 잠금화면 재생, 재생 중 전화가 온 경우 처리)
* 번외) 오디오 처리 - AVPlayer, AVAudioPlayer 개념 (실시간 스트리밍, 로컬 파일 재생)
AVAudioSession
- AVAudioSession라는 싱글톤이 있고, 이 싱글톤을 통해 OS에서 마이크, 오디오 설정등이 가능
- background에서 스피커 활성화
- 잠금화면에서도 스피커 활성화
- 앱간의 오디오 우선순위 설정, 확성화 설정
- 에어팟을 갑자기 뺀 경우, 입출력장치가 변경되는 경우의 처리
- AVAudioSession의 라이프 사이클은 앱의 라이프사이클과 일치
- AVAudioSession을 가지고 사용할 수 있는 기능
- 지금 앱에서 오디오를 활성화 / 비활성화 (active, deactive)
- 오디오 모드 설정
- 다른 앱들과 지금 앱의 오디오를 어떻게 호환할 것인지
AVAudioSession.sharedInstance().setActive(true)
AVAudioSession.sharedInstance().setMode(.gameChat)
- AVAudioSession은 앱에게 이벤트도 전달
- Audio Interrupt 발생
- Audio Route Change 발생
오디오 활성화 동작
- 내비게이션앱에서 "좌회전입니다" 음성이 나올 때 음악소리가 줄어드는 것처럼, "좌회전입니다"를 사용할 때 enabled 된 것
- "좌회전입니다" 소리가 줄어들고 다시 외부 앱의 소리가 커지는 시점이 음성이 disabled된 것
- enabled를 아래처럼 실행해도 더 높은 오디오 세션이 active되어 있다면, active 요청은 실패
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let audioSession = AVAudioSession.sharedInstance()
try? audioSession.setCategory(.soloAmbient)
try? audioSession.setActive(true, options: .notifyOthersOnDeactivation)
return true
}
Audio Route
- 오디오 입력 소스로부터 오디오 출력 소스까지의 path를 의미 (n/w에서의 라우팅과 동일한 개념)
- 연결중인 에어팟이 제거가 된 경우, 오디오 입력 소스에서는 reroute하여 오디오 입출력의 path를 재정의
- OS에서 Audio Route가 변경되었다는 신호를 줄 때, 앱에서는 Notification을 통해 확인이 가능
ex) reroute 되는 그림
- AVAudioSession.routeChangeNotification을 observe하여 이벤트처리
NotificationCenter.default.addObserver(
self,
selector: #selector(handleRouteChanged),
name: AVAudioSession.routeChangeNotification,
object: AVAudioSession.sharedInstance
)
@objc private func handleRouteChanged(notification: Notification) {
guard
let info = notification.userInfo,
let reason = info[AVAudioSessionRouteChangeReasonKey] as? AVAudioSession.RouteChangeReason
else { return }
if reason == .oldDeviceUnavailable {
let lastRoute = info[AVAudioSessionRouteChangePreviousRouteKey] as! AVAudioSessionRouteDescription
let lastOutput = lastRoute.outputs[0]
let port = lastOutput.portType
if port == .headphones {
// 재생 중지
}
}
}
AVAudioSession 다양한 기능
- 아이폰의 좌측 음소거 스위츠를 켜도 재생되도록 설정 방법
- AVAudioSession의 카테고리를 playBack으로 설정
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
try? AVAudioSession.sharedInstance().setCategory(.playBack)
try? AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
return true
}
- 잠금화면에서도 재생되도록 설정 방법
- info.plist에서 Required background modes 키값의 item 0에 App plays audio or streams audio/video using AirPlay으로 설정
- Interrupt 발생 (재생 중 전화가 온 경우)
- 음악이 서서히 볼륨이 정지되면서 정지되게끔 처리
- AVAudioSession.interruptionNotification 이벤트 사용
NotificationCenter.default.addObserver(
self,
selector: #selector(handleInterruptOccured),
name: AVAudioSession.interruptionNotification,
object: AVAudioSession.sharedInstance()
)
@objc private func handleInterruptOccured(notification: Notification) {
guard let interrupt = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? AVAudioSession.InterruptionType else { return }
if interrupt == .began {
print("인터럽트 시작")
} else if
let options = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? AVAudioSession.InterruptionOptions,
options == .shouldResume
{
print("재개")
}
}
* 참고
https://developer.apple.com/documentation/avfaudio/avaudiosession/1616627-setactive
'iOS 기본 (swift)' 카테고리의 다른 글
Comments