본문 바로가기
모바일 APP

음성 번역기 만들기 (Speech To Text)

by 살길바라냐 2023. 7. 31.

0 개요

 

출처 : meta team blog

 

출처 :  apple

 

애플의 비전프로, 메타의 AR 글래스처럼
AR 글래스(glasses)에 번역기능(translator)을
넣는(porting)것을 약 한달간 R&D(Research and Development )를 하게 되었다.  

 

현재는 글래스 제품은 보안 사항이라 상세하게 밝힐수 없으며
모바일에서 사용하는 안드로이드(Android) OS(operating system)
탑재가 가능해 

 

안드로이드  OS를 기준으로 기능 개발에 들어갔다. 

출처 : NetMag

 

1 기능 설계

 

기능 개발의 주안점을
크게 2가지로 나누었다

 

 


1. 음성을 텍스트 형태로 변환 (speech-to-text)

2. 변환된 텍스트를 한국어로 번역하여 글래스에 표시

 

3 기능 구현 방법

 

음성을 텍스트 형태로 변환 (speech-to-text) 기능을 어떻게
구현할까 고민하다가 

2가지 방법이 있었다.

android에서 제공하는 내장 API 또는  외부업체서 제공하는 STT API 사용
아무래도 네트워크를 이용해 사용하는 api를 사용할 경우 네트워크 환경에
영향을 많이 받을것이고,

내장API보다는 당연히 지연시간(latency)이 더소요 될 것이라 판단하여  
내장API 사용을 0순위로 두고 먼저 기능 테스트를 시작 하였다. 

 

3-1 내장 API  Speech Recognizer 사용

안드로이드에서 제공하는 내장 API는  Speech Recognizer
별도의 gradle 선언없이 import 만으로도 바로 사용이 가능하다. 

 

https://learn.microsoft.com/ko-kr/dotnet/api/android.speech.speechrecognizer?view=xamarin-android-sdk-13 

 

SpeechRecognizer 클래스 (Android.Speech)

이 클래스는 음성 인식 서비스에 대한 액세스를 제공합니다.

learn.microsoft.com

 

AndroidManifest.xml에
인터넷과 오디오녹음 권한을 설정해줘야 한다.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

 

필요한 객체 import

import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;

 

권한 확인

  if ( Build.VERSION.SDK_INT >= 23 ){
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.INTERNET,
                    Manifest.permission.RECORD_AUDIO},PERMISSION);
        }

 

객체 생성

    intent=new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,getPackageName());
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE,"en-US");

 

Context와 listner 할당

   recognizerInstance =SpeechRecognizer.createSpeechRecognizer(this);
            recognizerInstance.setRecognitionListener(listener);
            recognizerInstance.startListening(intent);

 

객체에 할당할 리스너 할당

private RecognitionListener listener = new RecognitionListener() {

      @Override
        public void onReadyForSpeech(Bundle params) {
            Toast.makeText(getApplicationContext(),"음성인식을 시작합니다.",Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onBeginningOfSpeech() {}

        @Override
        public void onRmsChanged(float rmsdB) {}

        @Override
        public void onBufferReceived(byte[] buffer) {}

        @Override
        public void onEndOfSpeech() {}

        @Override
        public void onError(int error) {
            String message;

            switch (error) {
                case SpeechRecognizer.ERROR_AUDIO:
                    message = "오디오 에러";
                    break;
                case SpeechRecognizer.ERROR_CLIENT:
                    message = "클라이언트 에러";
                    break;
                case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS:
                    message = "퍼미션 없음";
                    break;
                case SpeechRecognizer.ERROR_NETWORK:
                    message = "네트워크 에러";
                    break;
                case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
                    message = "네트웍 타임아웃";
                    break;
                case SpeechRecognizer.ERROR_NO_MATCH:
                    message = "찾을 수 없음";
                    break;
                case SpeechRecognizer.ERROR_RECOGNIZER_BUSY:
                    message = "RECOGNIZER가 바쁨";
                    break;
                case SpeechRecognizer.ERROR_SERVER:
                    message = "서버가 이상함";
                    break;
                case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
                    message = "말하는 시간초과";
                    break;
                default:
                    message = "알 수 없는 오류임";
                    break;
            }

            Toast.makeText(getApplicationContext(), "에러가 발생하였습니다. : " + message,Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onResults(Bundle results) {
            // 말을 하면 ArrayList에 단어를 넣고 textView에 단어를 이어줍니다.
            ArrayList<String> matches =
                    results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);

            for(int i = 0; i < matches.size() ; i++){
                textView.setText(matches.get(i));
            }
        }

        @Override
        public void onPartialResults(Bundle partialResults) {}

        @Override
        public void onEvent(int eventType, Bundle params) {}
}

[출처 : https://ebbnflow.tistory.com/188 블로그]

 

구현은 어렵지 않은데 몇가지 단점들이 있었다.

1. 텍스트의 변환이 완벽하지 않다는점

2. 긴 문장을 보낼수 없는점

3. 각각 문장을 분별할 옵션이 따로 없다는점

 

번역결과가 좋으려면 좋은문장을 정리해서 
번역기에 잘보내야 하는데
그것을 판단한 기준이 명확하지 않았다.

사용자가 해당 문장끝을 인지하고 끊던가 

아니면 AI로 자동 판단해서 끊어주어야 하는데 

이 두가지를 제공하지 않아서 결국 외부 STT API로
방향을 전환하게 되었다. 

참고로 IOS의경우 녹음간 침묵시간을 감지해서
문장을 판단 하는 방법이 있지만

안드로이드 녹음간 침묵시간을 인지하는 기능이 없었다. 

 

-2. 외부 STT API 사용

STT API 제공하는 여러 업체들이 있었지만
차후 유지 보수와 다양한 옵션 처리가능한 부분을 고려하여

어느정도 규모가 있는 업체를 찾게 되었고

최종 구글의 Google cloud platform과  
네이버의 nCloud를 선택하여 테스트를 진행 하였다.  

 

Google cloud platform

-Speech-to-Text v1,
-Speech-to-Text v2

https://cloud.google.com/speech-to-text?hl=ko 

 

Speech-to-Text: 자동 음성 인식  |  Google Cloud

사용하기 쉬운 API로 Google의 강력한 머신러닝 모델을 적용하여 125개 이상의 언어 및 방언으로 된 음성을 텍스트로 정확하게 변환할 수 있습니다.

cloud.google.com

 

nCloud

-Clova Speech Recognition
https://www.ncloud.com/product/aiService/csr

 

NAVER CLOUD PLATFORM

cloud computing services for corporations, IaaS, PaaS, SaaS, with Global region and Security Technology Certification

www.ncloud.com


-Clovar speech

https://www.fin-ncloud.com/product/aiService/clovaSpeech

 

네이버 클라우드 플랫폼 금융기관용 NAVER CLOUD PLATFORM for Financial Cloud

네이버 금융 클라우드, 금융보안원 안정성 평가 100% 충족, 글로벌 리전 및 보안기술 인증 보유

www.fin-ncloud.com

 

 

728x90
반응형

'모바일 APP' 카테고리의 다른 글

not found file libarclite_iphoneos.a (Xcode 14.3)  (0) 2023.05.10
TDD 개발 환경 설정  (0) 2021.05.06
FCM 웹 브라우저 푸시 보내기  (0) 2020.09.01