[swift] NotificationBanner 알림창 메시지 음성 인식 DB 설정

앱에서 NotificationBanner를 사용하여 알림 메시지를 표시하는 것은 매우 편리합니다. 그러나 사용자가 앱의 알림 내용을 읽을 수 없는 경우에는 문제가 발생할 수 있습니다.

이 문제를 해결하기 위해 음성 인식을 통해 알림 메시지를 사용자에게 읽어주는 기능을 추가하려고 합니다. 이를 위해 음성 인식 DB를 설정해야합니다.

음성 인식 DB 설정

  1. Speech 프레임워크 추가: 프로젝트를 열고 프로젝트 내비게이터에서 타겟을 선택하여 프로젝트 설정에 들어갑니다. 그런 다음 “Build Phases” 탭으로 이동하고 “Link Binary With Libraries” 섹션에서 “+” 버튼을 클릭합니다. “Speech.framework”를 선택하고 “Add” 버튼을 클릭하여 프로젝트에 추가합니다.

  2. 음성 인식 권한 요청: 음성 인식 기능을 사용하기 위해 사용자에게 권한을 요청해야합니다. Info.plist 파일을 열고 다음 코드를 추가합니다.

     <key>NSMicrophoneUsageDescription</key>
     <string>음성 인식을 위해 마이크 접근 권한이 필요합니다.</string>
    
  3. 음성 인식 기능 구현: NotificationBanner 클래스의 확장을 생성하여 음성 인식 기능을 추가합니다. 아래의 코드는 음성을 인식하고 해당 내용을 읽어주는 기능을 구현한 예시입니다.

import Speech

extension NotificationBanner {
  
  // 음성 인식 요청을 처리하기 위한 객체
  private var speechRecognizer: SFSpeechRecognizer? {
    return SFSpeechRecognizer(locale: Locale.current)
  }

  // 음성 인식 요청 상태
  private var speechRecognitionRequest: SFSpeechAudioBufferRecognitionRequest?

  // 음성 인식 객체
  private var speechRecognitionTask: SFSpeechRecognitionTask?

  // 음성 인식을 위한 오디오 엔진
  private let audioEngine = AVAudioEngine()

  // 음성 인식 결과를 처리하는 메서드
  private func processSpeechRecognitionResult(_ result: SFSpeechRecognitionResult?, error: Error?) {
    if let error = error {
      print("음성 인식 에러: \(error)")
      return
    }

    if let result = result {
      let bestTranscription = result.bestTranscription
      let message = bestTranscription.formattedString
      speakMessage(message)
    }
  }

  // 메시지 음성 출력
  private func speakMessage(_ message: String) {
    let synth = AVSpeechSynthesizer()
    let utterance = AVSpeechUtterance(string: message)
    utterance.voice = AVSpeechSynthesisVoice(language: "ko-KR")
    synth.speak(utterance)
  }

  // 음성 인식 시작
  func startSpeechRecognition() {
    guard let recognizer = speechRecognizer else {
      print("시스템이 지원하지 않는 언어입니다.")
      return
    }
    
    if speechRecognitionTask != nil {
      speechRecognitionTask?.cancel()
      speechRecognitionTask = nil
    }

    let audioSession = AVAudioSession.sharedInstance()
    try? audioSession.setCategory(.record, mode: .default, options: [])
    try? audioSession.setActive(true, options: [])

    speechRecognitionRequest = SFSpeechAudioBufferRecognitionRequest()
    let inputNode = audioEngine.inputNode

    guard let recognitionRequest = speechRecognitionRequest else {
      fatalError("인식 요청을 생성할 수 없습니다.")
    }

    recognitionRequest.shouldReportPartialResults = true
    speechRecognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest) { [weak self] result, error in
      self?.processSpeechRecognitionResult(result, error: error)
    }

    let recordingFormat = inputNode.outputFormat(forBus: 0)
    inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
      self.speechRecognitionRequest?.append(buffer)
    }

    audioEngine.prepare()
    try? audioEngine.start()

    print("음성 인식이 시작되었습니다.")
  }

  // 음성 인식 종료
  func stopSpeechRecognition() {
    audioEngine.stop()
    audioEngine.inputNode.removeTap(onBus: 0)
    speechRecognitionRequest?.endAudio()
    speechRecognitionRequest = nil
    speechRecognitionTask = nil

    let audioSession = AVAudioSession.sharedInstance()
    try? audioSession.setActive(false)
    
    print("음성 인식이 종료되었습니다.")
  }
}

이제 위의 코드를 사용하여 NotificationBanner를 확장하고 음성 인식을 사용할 수 있습니다. 알림 메시지가 나타날 때마다 음성을 인식하고 해당 내용을 사용자에게 읽어주는 기능이 자동으로 실행됩니다.

참고