swift로 녹음기능 구현하기 - avaudioSession 설정하기

나우리·2024년 10월 29일

Swift

목록 보기
10/13

AVaudioSession의 종류와 녹음을 위한 오디오 세션 설정에 대해 알아보자

AVaudioSession은 설정을 할 때 다양한 카테고리를 제공한다.
각 카테고리에 따라서 녹음이 가능하거나, 불가능하고 이에 맞춘 추가 옵션들을 설정할 수 있다.

AVaudioSession은 AVAudioApplication과 비슷하게 sharedInstance()를 통해 싱글톤 객체를 제공해준다.
이 sharedInstance를 활용하여 setCategory를 통해 카테고리와 모드, policy와 옵션을 설정 가능하다.

  • 카테고리는 오디오 세션의 활용 범주라고 생각하면 되고,
  • 모드는 어떤 기능을 수행하고 있는지,
  • policy는 오디오 경로 공유 정책을,
  • 옵션은 말그대로 선택적 오디오 동작을 설정해주는 값이라고 생각할 수 있다.

Category

오디오세션의 카테고리는 7종류이다.

이 중 무선연결 장치에서 화면 공유없이 미디어를 재생하는 기술인 airplay를 활용하여 미러링, 혹은 미러링되지 않은 airplay을 사용하는 경우 재생 전용 카테고리인 세 종류만 설정이 가능하다.

  • ambient : 사운드 재생이 주요 목적이 아닌 앱에 대한 카테고리. 사운드를 끈 상태에서도 앱이 작동함
    (백그라운드 작동 노이즈나 다른 음악과 섞이는 음악)
  • soloAmbient : 기본 오디오 세션 카테고리
  • playback : 앱을 설공적으로 사용하는 데 중요한 녹음된 음악이나 기타 사운드를 재생하기 위한 카테고리
    특히 playback의 경우는 대부분 음악 재생에 주로 쓰인다.

녹음에 활용 가능한 카테고리는 두 종류이다.

  • playAndRecord : VOIP앱과 같은 오디오를 녹음하고 재생하기 위한 카테고리
  • record: 재생 오디오를 음소거하면서 오디오를 녹음하는 카테고리
    재생과 record가 바로바로 바뀔 경우에는 playAndRecord를, 그 외에는 record를 설정하면 된다.
    playAndRecord 카테고리를 설정할 경우에도 airplay 사용은 가능하지만, 이 때 기기가 반드시 녹음도 가능한 객체와 연결이 되어야 한다고 한다.

그 외
-multiRoute : 동시에 여러 출력 장치로 다양한 오디오 데이터 스트림을 라우팅하기 위한 카테고리

요 airplay 미러링과 미러링되지 않은 airplay에 대해 궁금한 분은 다음 게시글을 참조해도 좋을듯하다
스택오버플로우 Differnce between airplay mirroring vs without mirroring

mode

  • default: 기본 (별도 설정 없을 시 기본)
  • gameChat: gameKit프레임워크가 gameKit음성채팅서비스를 사용하는 앱을 대신하여 설정하는 모드
  • measurement: 앱이 오디오 입력 또는 출력을 측정하고 있음을 나타내는 모드
  • spokenAudio: 다른 앱에서 짧은 오디오 메시지를 재생할 때 오디오를 일시 정지하기 위해 연속적인 음성 오디오에 사용되는 모드
    • 다른 앱에서 음성 오디오 프롬프트를 재생하는 경우 앱이 오디오를 낮추는 대신 일시 중지해야 함을 나타냄.
    • 방해하는 앱의 오디오가 끝나면 앱의 오디오 재생을 재개할 수 있음
  • videoChat: 앱이 온라인 화상 회의 참여 안내 모드
  • videoRecording: 앱이 영화 녹화
  • voiceChat : 양방량 음성 통신을 수행하고 있음을 나타내는 모드
  • voicePrompt: 앱이 텍스트 - 음성을 사용하여 오디오를 재생하고 있음을 나타내는 모드

policy

  • default: 표준 규칙
  • longFormAudio : 공유된 장문 오디오 출력으로 출력을 라우팅
  • longFormVideo: 공유된 장편 비디오 출력으로 출력을 라우팅
  • independent : 경로 선택기 UI가 비디오를 무선 경로로 전달하는 정책

options

  • mixWithOthers: 오디오를 다른 오디오앱의 활성 세션의 오디오와 혼합할지 여부를 나타냄
  • duckOthers: 이 세션의 오디오를 재생하는 동안 다른 오디오 세션의 볼륨을 줄이는 옵션
  • interruptSpokenAudioAndMixWithOthers: 앱에서 오디오를 재생할 때 다른 세션의 음성 오디오 콘텐츠를 일시 중지할지 여부를 결정하는 옵션
  • allowBluetooth: 블루투스 핸즈프리 장치를 사용가능한 입력경로로 표시할지 여부를 결정하는 옵션
    • playAndRecord나 record 옵션만 선택가능
  • allowBluetoothA2DP : 이 세션의 오디오를 A2DP를 지원하는 블루투스장치로 스트리밍할 수 있는지 여부를 결정하는 옵션
    • 출력전용 프로필. (출력전용 프로필이라 무시하기)
    • playBack옵션이 경우 자동으로 연결됨
    • playAndRecord도 이쪽으로 선택가능
    • multiRoute나 record의 경우 암묵적으로 이 옵션을 지움
  • allowAirPlay : 이 세션의 오디오를 airPlay 장치로 스트리밍할 수 있는지 여부를 결정
  • defaultToSpeaker: 세션의 오디오를 수신기가 아닌 내장 스피커로 기본적으로 출력할지 여부 결정
  • overrideMutedMicrophoneInterruption : 내장 마이크를 음소거할 때 시스템이 오디오 세션을 중단할지 여부를 나타내는 옵션

나는 폴리시나 모드를 사용하지 않고 카테고리와 옵션만 설정하여 재생 및 녹음 처리를 했다.
재생을 설정한 예시는 이렇다.

do {
try AVAudioSession.sharedInstance().setCategory(.playback, options: .duckOthers)
//재생 설정하기
} catch {
print(error.localizedDescription)
}

setCategory는 에러를 throw 해주는 func이라 do, try, catch로 에러를 잡아줬다.
재생 설정을 하고, duckothers를 통해 다른 오디오는 볼륨을 줄이도록 설정했다.
녹음할 때 예시는 다음과 같다

do {
    try AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: .allowBluetooth)
    //녹음 설정하기
} catch {
    print("녹음 준비 중 오류 발생: \(error.localizedDescription)")
}

재생과 녹음이 둘 다 가능한 객체를 설정하고 블루투스 기기를 통한 입력이 가능하도록 옵션을 설정했다.
audioSession을 활용한 다른 코드를 봤을 때 특이한 점은 setActive를 선언한 코드가 별로 없었다는 점이었다.
오디오 세션은 setActive(Bool)를 통해 active와 deactive를 오갈 수 있다.

[이미지 출처: 오디오 세션 프로그래밍 가이드, the interruption life cycle]

다만 액티브가 선언되면 다른 오디오와의 간섭이 시작된다.
기기의 오디오 세션을 감지하여 옵션이나 모드, 카테고리 설정에 따라 다른 오디오를 막거나, 현재 오디오를 정지한다.
setActive를 기준으로 시작과 정지를 나누는데, 그래서 미리 setActive를 할 경우 오디오가 재생되지 않았음에도 재생이라 설정이 된다.
그리고 AVFaudio의 AVAudioPlayer나 AVAudioRecorder를 통한 재생, 혹은 녹음을 할 경우
시작에서 별도 선언 없이 setActive가 true가 되고, 재생이나 녹음이 정지될 때 자동으로 false가 된다.

그러므로 한 앱에서 audioSession의 카테고리나 모드가 하나일 경우 앱 시작할 때 카테고리 선언만 미리하고,
재생만 설정하기도 한다.
한 앱에서 여러 모드를 번갈아 써야 할 경우 아예 재생이나 녹음 func에 같이 카테고리 설정을 하기도 한다.

참고자료

AVAudioSession Document
Audio Session Programming guide

profile
왕초보 개발일지

0개의 댓글