관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 2. 오디오 처리 - AVAudioRecoder 개념 (녹음) 본문

iOS 응용 (swift)

[iOS - swift] 2. 오디오 처리 - AVAudioRecoder 개념 (녹음)

jake-kim 2022. 4. 30. 22:29

1. 오디오 처리 - AVPlayer, AVAudioPlayer 개념 (실시간 스트리밍, 로컬 파일 재생)

2. 오디오 처리 - AVAudioRecoder 개념 (녹음)

비교 (복습)

  • 실시간 스트리밍 -> AVPlayer 사용
  • 로컬 파일 재생 -> AVAudioPlayer 사용
  • 음성 특수 효과 or 변조 -> AVAudioEngine 사용

cf) 녹음 -> AVAudioRecoder 사용

AVAudioRecoder로 녹음하고 AVAudioPlayer로 재생

비동기 처리의 편의를 위해서 사용한 프레임워크

pod 'RxSwift'
pod 'RxCocoa'
pod 'RxAVFoundation'

AVAudioRecoder

  • 녹음기능을 사용하기 위해서 시스템 권한이 필요

	<key>NSMicrophoneUsageDescription</key>
	<string>마이크 이용 권한 요청 메시지</string>
  • MyAudioRecoderView 커스텀 뷰에 AVAudioRecoder 구현
import UIKit
import AVFoundation
import RxSwift
import RxCocoa

final class MyAudioRecoderView: UIView {

}
  • AVAudioRecoder 인스턴스 준비
// MyAudioRecoderView.swift

private var audioRecorder = AVAudioRecorder()
  • 0.5초마다 경과 시간을 구하기위해 구독
// MyAudioRecoderView.swift

Observable<Int>
  .interval(.milliseconds(500), scheduler: MainScheduler.asyncInstance)
  .compactMap { [weak self] _ in self?.audioRecorder.currentTime }
  .bind { print("경과 시간: \($0)") }
  .disposed(by: self.disposeBag)
  • record() 구현
    • FileManger를 통해서 m4a형식의 파일 경로를 생성 (음성 녹음 시 사용)
    • AVAudioSession을 통해서 playAndRecord모드로 바꾸어, 녹음 모드로 세팅
    • AVAudioSession개념은 이전 포스팅 글 참고
// MyAudioRecoderView.swift

func record() {
  let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    .appendingPathComponent("myRecoding.m4a")
  let settings = [
    AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
    AVSampleRateKey: 12000,
    AVNumberOfChannelsKey: 1,
    AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
  ]
  
  do {
    try AVAudioSession.sharedInstance().setCategory(.playAndRecord)
  } catch {
    print("audioSession error: \(error.localizedDescription)")
  }
  
  do {
    self.audioRecorder = try AVAudioRecorder(url: fileURL, settings: settings)
    self.audioRecorder.delegate = self
    self.audioRecorder.record()
  } catch {
    print("occured error in MyAudioRecoderView = \(error.localizedDescription)")
    self.stop()
  }
}

extension MyAudioRecoderView: AVAudioRecorderDelegate {
  func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) {
    self.stop()
  }
  func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    self.stop()
  }
}
  • stop() 구현
    • stopSubject를 만들어서 사용하는 쪽에서 녹음 완료 시 url을 건네받을 수 있도록 구현
// MyAudioRecoderView.swift

let stopSubject = PublishSubject<URL>()
var url: URL {
  return self.audioRecorder.url
}

func stop() {
  self.audioRecorder.stop()
  self.stopSubject.onNext(self.url)
}

사용하는 쪽

* AVAudioPlayer 개념은 이전 포스팅 글 참고

// ViewController.swift

private let audioRecoderView = MyAudioRecoderView()
private let audioPlayerView = MyAudioPlayerView()

self.audioRecoderView.stopSubject
  .bind { [weak self] in
    print("값 \($0)")
    self?.audioPlayerView.url = $0
    self?.audioPlayerView.readyToPlay = true
  }
  .disposed(by: self.disposeBag)

* 전체 코드: https://github.com/JK0369/ExAVAudioRecoder

 

* 참고

https://www.hackingwithswift.com/example-code/media/how-to-record-audio-using-avaudiorecorder

https://developer.apple.com/documentation/avfaudio/avaudiorecorder

Comments