SpeechRecognizer 음성인식 API 사용하기 - 2탄
1. 서론
https://peaceful-dev.tistory.com/5
SpeechRecognizer 음성인식 API 사용하기
1. 서론내 삶을 더 편리하게 해줄 개인 비서 앱을 만들고 싶다. 그렇지만 버튼을 클릭하기는 너무 귀찮다. 역시 말로 하는 게 편하다. 지금 생각 중인 아키텍처로는1) 클라이언트 앱에서 내 음성
peaceful-dev.tistory.com
위 포스팅에서 만든 앱은 한 호흡의 문장만을 인식한다. 하지만 우리는 원하는 말을 한 호흡에 다 말하지 않는다. 때로는 생각을 하느라 뜸을 들이기도 하고, 상대(AI)가 말하는 걸 끝까지 듣지 않고 중간에 끊기도 한다.
아래 상황을 보자.
주황색: 사용자의 말(음성)
빨간색: 클라이언트의 요청(텍스트)
초록색: 서버의 응답(클라이언트까지 텍스트로 도달, TTS가 음성으로 변환하여 사용자에게 전달)
1번이 가장 기본이 되는 상황이다. 사용자가 '안녕'이라고 말하면, 클라이언트(앱)가 텍스트로 변환 후 서버에 요청을 보낸다. 그러면 서버(AI)는 '안녕하세요! 어떻게 도와드릴까요?'라는 응답을 반환하고, 클라이언트에서 텍스트 응답을 음성으로 변환하여 사용자에게 전달한다.
사용자 > 클라이언트 > 서버 > 클라이언트 > 사용자 순이다.
2번은 사람이 질문을 여러 호흡으로 하는 상황이다. 클라이언트 입장에서 사용자의 발화가 끝나지 않았는데 중간중간 서버로 요청을 보내면 안 된다. 위 예시처럼 발화가 끝날 때까지 기다렸다가 한 번에 모아서 요청을 보내야 올바른 응답을 기대할 수 있다.
3번은 AI가 말하는 도중 말을 끊는 경우이다. 사용자가 말을 시작하면 AI의 음성은 멈춰야 한다.
2. 설계 및 구현
2번을 상황을 위해서, 클라이언트는 음성 녹음이 완료되더라도 바로 서버로 요청을 보내지 않는다. 그리고 발화가 종료되었다고 판단되면 서버에 요청을 보낸다. 이 부분이 굉장히 중요한데 인간은 눈치를 보고 상대방의 말을 끝났는지 알아채지만 (물론 모두가 능숙한 것은 아니다), 프로그램에도 이러한 판단 능력을 부여해야 한다.
발화의 끝을 판단하는 방법
1) Rule-based Approach
마지막 음성 이후 침묵 시간, 완결된 문장 여부, 명령형/의문형 여부 등을 바탕으로 규칙 생성
2) Markov Chain
각 단어의 이전/다음 상태를 기반으로 각 단어가 발화의 끝일 확률 계산
3) RNN 및 LSTM
연속된 데이터 즉, 대화의 흐름을 이해하고 직전 발화의 맥락을 바탕으로 발언이 종료되었는지 판단
4) Transformer Model
BERT, GPT 등의 Transformer 기반 모델을 사용하여 문맥을 이해하고 발언 종료 여부 예측
고민을 좀 했지만, 위 그림처럼 클라이언트 측에서 발화의 끝을 인지하고 모아서 요청을 보내고 싶었고, 프로젝트에서 아주 중요한 부분은 아니라서 우선 규칙 기반으로 발화의 끝을 판단하기로 했다. 실제 사용해보면서 규칙을 추가하다가 규칙 기반 접근 방식의 한계가 느껴지면 변경하려고 한다.
3번을 충족하기 위해서 SpeechRecognizer API의 onPartialResults 메서드를 사용할 것이다. onBeginningOfSpeech 메서드는 주변 소음에 의해서도 호출될 수 있기 때문에 좀 더 보수적인 위 메서드를 선택했다.
3. 결과
한 줄이 한 호흡으로 인식된 문장이고, --- 로 분리된 부분이 하나의 발화이다. 현재는 발언의 마지막이 '~줘'로 끝나면 발화가 종료되었다고 판단한다. 음성 인식이 종료되면 계속해서 다시 음성 인식을 시작하도록 하여 계속해서 대화가 가능하도록 설정하였다. 대화 종료 버튼을 클릭하면 음성 인식을 더 이상 반복하지 않고 종료된다.
개선할 만한 사항
- 요청 전송 후, 또는 AI 응답 중에 '근데~' 등으로 발언이 시작하면 전 요청에 더해서 재요청
ex) 근데 너무 복잡한 건 빼고 알려줘 - AI가 응답하던 중(TTS) 사용자가 말하면 TTS 중단, 그 이후 사용자가 '계속해봐' 등의 발언을 하면 기존 중단된 TTS 이어서 실행
- 대화 종료 버튼 대신 '쉬어' 등의 발언으로 종료 처리