이 문서는 Android 음성 SDK를 사용한 음성 기능 구현 방법을 안내합니다.
카카오 음성 인식 SDK를 사용하려면 Android SDK 사용법을 참고해 Gradle Repository
를 프로젝트 build.gradle 파일에 추가합니다.
dependencies {
compile group: 'com.kakao.sdk', name: 'newtone', version: project.KAKAO_SPEECH_VERSION
}
사람이 말하는 음성 언어를 컴퓨터가 해석해 그 내용을 문자 데이터로 변환하는 음성-문자 변환 시스템 (Speech-to-Text system)입니다.
권한 설정카카오스피치 SDK는 RECORD_AUDIO
, WRITE_EXTERNAL_STORAGE
, ACCESS_NETWORK_STATE
권한을 필요로 합니다. 위 권한들을 다음과 같이 앱의 AndroidManifest.xml 파일에 설정합니다.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
...
<meta-data
android:name="com.kakao.sdk.AppKey"
android:value="@string/kakao_app_key" />
...
</application>
안드로이드 M(API level 23)부터 RECORD_AUDIO
와 WRITE_EXTERNAL_STORAGE
권한은 위험 권한으로 분류되어 AndroidManifest.xml에 권한을 명시하더라도 동적으로 사용자에게 권한 요청을 거쳐야 합니다. 앱의 동선에 맞게 두개의 권한을 동적으로 획득합니다.
// 동적 권한 코드
...
public void onCreate(Bundle savedInstanceState) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO) && ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_AUDIO_AND_WRITE_EXTERNAL_STORAGE);
} else {
// 사용자가 거부하면서 다시 묻지 않기를 클릭.. 권한이 없다고 사용자에게 직접 알림.
}
} else {
startUsingSpeechSDK();
}
}
...
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_AUDIO_AND_WRITE_EXTERNAL_STORAGE:
if (grantResults.length > 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
startUsingSpeechSDK();
} else {
finish();
}
break;
default:
break;
}
}
음성 인식 기능을 이용하려면 먼저 SDK 초기화를 해야 합니다. 음성 인식 기능을 이용하는 Activity
의 onCreate()
에서 라이브러리를 초기화하는 함수인 SpeechRecognizerManager
의 initializeLibrary()
를 호출합니다.
그 후 SpeechRecognizerClient.Builder
를 통하여 다음과 같이 SpeechRecognizerClient
를 생성합니다.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// SDK 초기화
SpeechRecognizerManager.getInstance().initializeLibrary(this);
// 클라이언트 생성
SpeechRecognizerClient.Builder builder = new SpeechRecognizerClient.Builder().
setServiceType(SpeechRecognizerClient.SERVICE_TYPE_WEB).
setUserDictionary(userdict); // optional
SpeechRecognizerClient client = builder.build();
}
// ...
public void onDestroy() {
super.onDestroy();
SpeechRecognizerManager.getInstance().finalizeLibrary();
}
Name | Description | Required |
---|---|---|
setServiceType(String) | 음성 인식에서 지원하는 서비스 타입으로 웹검색/연속어/지도/고립어 인식을 제공 - SpeechRecognizerClient.SERVICE_TYPE_WEB : 웹 검색 키워드 검색어 인식에 최적화. 포탈 검색에 많이 사용되는 텍스트들에 인식 최적화.(default) - SpeechRecognizerClient.SERVICE_TYPE_LOCAL : 지도 검색으로 장소명 검색어 인식에 최적화 - SpeechRecognizerClient.SERVICE_TYPE_DICTATION : 연속어 인식으로 문장 인식에 최적화. 15초 이내의 한 문장 정도 인식에 사용 - ServiceRecognizerClient.SERVICE_TYPE_WORD : 고립어 인식으로 단어 인식에 최적화. UserDictionary 에 설정된 단어들 중에서만 인식. |
X |
setGlobalTimeOut(int) | 녹음에서 인식까지의 전체 세션 타임 아웃으로 default는 30초(sec). | X |
setUserDictionary(String) | 사용자 사전을 정의. 구분자는 '\n'(newline). 예) "다음\n카카오\n음성인식" | X |
음성 인식 중에 발생하는 다양한 이벤트를 callback
메서드를 구현하여 처리할 수 있습니다. callback
메서드를 받기 위해서는 SpeechRecognizeListener
인터페이스를 구현해야 합니다.
SpeechRecognizeListener
는 결과값을 받거나 에러가 발생하는 등의 이벤트가 발생했을 때 해당 상태에 맞는 callback
메서드를 호출해 줍니다. SpeechRecognizeListener
를 추가하는 방법은 SpeechRecognizerClient
의 setSpeechRecognizeListener()
메서드를 이용합니다.
client.setSpeechRecognizeListener(new SpeechRecognizeListener() {
@Override
public void onReady() {
//To change body of implemented methods use File | Settings | File Templates.
}
// ...
});
SpeechRecognizeListener
를 구현하려면 총 7개의 메서드를 구현해야 합니다.
모든 callback
함수는 UI thread
가 아닌 background thread
에서 호출될 수 있기 때문에, UI와 관련된 작업은 Activity.runOnUiThread(Runnable)
나 Handler.post(Runnable)
을 통해 비동기로 호출해야 합니다.
우선 startRecording()
이 실행된 이후에 음성 입력을 감지하면 감지된 음성에 대한 결과를 경우에 따라 두가지 callback
을 통해 얻을 수 있습니다.
onPartialResult
는 완전히 음성이 종료되기 이전에 현재까지 인식된 음성데이터 문자열을 알려줍니다. 이 데이터는 서버에 질의해 데이터를 보정하는 과정을 거치지 않으므로, 다소 부정확할 수 있습니다. 중간 인식 결과에 대한 결과가 발생할 때마다 호출되므로 여러번 호출될 수 있습니다.
@Override
public void onPartialResult(String text) {
//TODO implement interface SpeechRecognizeListener method
}
onResults
는 음성 입력이 종료된 것으로 판단하거나 stopRecording()
을 호출한 후에 서버에 질의하는 과정까지 마치고 나면 호출됩니다. 인식된 문자열은 신뢰도가 높은 값부터 순서대로 Bundle의 SpeechRecognizerClient.KEY_RECOGNITION_RESULTS
값을 통해 ArrayList
로 얻을 수 있습니다.
신뢰도는 Bundle의 SpeechRecognizerClient.KEY_CONFIDENCE_VALUES
값을 통해 ArrayList
로 얻을 수 있으며 높은 값부터 순서대로입니다. 신뢰도 값은 항상 0보다 크거나 같은 정수이며, 문자열 목록과 같은 개수입니다.
@Override
public void onResults(Bundle results) {
//TODO implement interface SpeechRecognizeListener method
ArrayList<String/> texts = results.getStringArrayList(SpeechRecognizerClient.KEY_RECOGNITION_RESULTS);
ArrayList<Integer/> confs = results.getIntegerArrayList(SpeechRecognizerClient.KEY_CONFIDENCE_VALUES);
}
결과를 얻기 위한 callback
말고도 다양한 callback
메서드가 존재합니다. onError callback
은 이름에서 알 수 있듯이 에러가 발생했을 때 호출됩니다. SpeechRecognizerClient
에서 다양한 에러 코드에 대응하는 'ERROR_' 로 시작하는 code
값들을 확인할 수 있습니다.
@Override
public void onError(int errorCode, String errorMsg) {
//TODO implement interface SpeechRecognizeListener method
}
음성 인식 API는 아래와 같은 에러코드를 전달합니다. SpeechRecognizerClient
에서 'ERROR_' 로 시작하는 static int
값들입니다.
Error Code | Description |
---|---|
ERROR_AUDIO_FAIL | 음성입력이 불가능하거나 마이크 접근이 허용되지 않았을 경우. |
ERROR_AUTH_FAIL | apikey 인증이 실패한 경우. |
ERROR_NETWORK_FAIL | 네트워크 오류가 발생한 경우. |
ERROR_NETWORK_TIMEOUT | 네트워크 타임아웃이 발생한 경우. |
ERROR_SERVER_FAIL | 서버에서 오류가 발생한 경우. |
ERROR_SERVER_TIMEOUT | 서버 응답 시간이 초과한 경우. |
ERROR_NO_RESULT | 인식된 결과 목록이 없는 경우. |
ERROR_CLIENT | 클라이언트 내부 로직에서 오류가 발생한 경우. |
ERROR_RECOGNITION_TIMEOUT | 전체 소요시간에 대한 타임아웃이 발생한 경우. |
ERROR_SERVER_UNSUPPORT_SERVICE | 제공하지 않는 서비스 타입이 지정됐을 경우. |
ERROR_SERVER_USERDICT_EMPTY | 입력된 사용자 사전에 내용이 없는 경우. |
ERROR_SERVER_ALLOWED_REQUESTS_EXCESS | 요청 허용 횟수 초과. |
Method Name | Description |
---|---|
onReady | 여러 가지 초기화 작업을 성공적으로 마치고 나면 가장 먼저 호출되는 callback SpeechRecognizerClient 의 startRecording 이 수행된 후에 단말기의 마이크 하드웨어와 OS의 오디오 서비스 등에 대한 초기화 등이 모두 준비되었을 때 호출됩니다. |
onBeginningOfSpeech | 사용자가 말하기 시작하는 것으로 판단될 때 호출되는 callback 사용자가 말을 하지 않은 상태에서 에러가 발생하면 이 callback은 호출되지 않습니다. |
onEndOfSpeech | 사용자가 말하는 것을 끝마친 것으로 판단될 때 호출되는 callback 사용자가 너무 오랜 시간을 말하여 앱이 지정한 시간 내에 음성을 인식하지 못하였거나 인식 중에 오류가 발생했을 때는 호출되지 않습니다. |
onAudioLevel | 음성이 입력되는 도중에 입력되는 음성의 크기를 dB(데시벨)로 판별한 후 재가공을 거친 상대값을 알려주는 callback 0과 1 사이의 float 값 |
onFinished | 인식 종료 후 사용하던 리소스를 모두 해제한 후에 호출되는 callback 음성인식이 성공적으로 종료되었을 때만 호출되며, onError가 발생했을 때는 호출되지 않습니다. |
@Override
public void onReady() {
//TODO implement interface SpeechRecognizeListener method
}
@Override
public void onBeginningOfSpeech() {
//TODO implement interface SpeechRecognizeListener method
}
@Override
public void onEndOfSpeech() {
//TODO implement interface SpeechRecognizeListener method
}
@Override
public void onAudioLevel(float v) {
//TODO implement interface SpeechRecognizeListener method
}
@Override
public void onFinished() {
//TODO implement interface SpeechRecognizeListener method
}
음성 인식을 시작하려면 SpeechRecognizerClient
의 startRecording()
메서드를 호출합니다. 파라미터로 입력하는 boolean 값은 현재 재생되고 있는 음악 등 배경 소리를 음소거(mute)할지 지정하는 값입니다. 값이 true면 음소거를 합니다. 음소거 했을 경우 음성 인식이 종료되면 음소거가 종료됩니다.
client.startRecording(true);
음성 인식을 중지하는 방법은 cancelRecording()
메서드와 stopRecording()
메서드, 두가지가 있습니다.
cancelRecording()
은 음성 인식을 취소하며 이후로 진행되는 동작은 없습니다.
stopRecording()
은 음성 인식을 멈추지만, startRecording()
을 실행한 이후부터 stopRecording()
을 실행할 때까지의 음성데이터를 이용해 음성 인식을 진행합니다.
따라서, stopRecording()
은 실행된 이후에 SpeechRecognizeListener
의 onResults
또는 onError
가 호출되게 됩니다.
client.cancelRecording();
// or
client.stopRecording();
SpeechRecognizerClient
와 SpeechRecognizeListener
를 직접 이용하는 방법 말고도 제공되는 기본 UI를 통해 간편하게 사용자에게 UI를 제공할 수 있습니다.
간결하게 UI를 구성할 수 있도록 샘플 프로젝트의 리소스와 예제 코드를 이용할 수 있습니다. 기본 UI에서 많은 커스터마이징이 필요하다면 별도로 제작하는 것이 바람직합니다.
기본 UI로 이용할 수 있는 음성 인식 기능은 샘플 프로젝트의 VoiceRecoActivity
를 이용합니다. VoiceRecoActivity
은 카카오 스피치 SDK의 SpeechRecognizerActivity
를 상속받아 구현하였습니다.
가장 먼저 할 작업은 압축파일에 포함된 기본 UI를 구현한 VoiceRecoActivity.java를 필요한 프로젝트에 복사합니다. 파일을 복사한 후에 package name
은 그에 맞게 변경합니다.
그리고 activity에서 이용하는 리소스들을 프로젝트의 리소스 경로 위치로 복사합니다. 복사하는 것으로 인해 기존 프로젝트의 리소스를 덮어쓰지 않도록 파일 이름들이 설정되어 있습니다.
activity
등록하기이제 AndroidManifest.xml에 activity
를 등록하면 VoiceRecoActivity
의 이용을 위한 준비는 끝납니다.
<!-- package 이름은 적절히 변경합니다. -->
<activity android:name="com.kakao.sdk.speech.sample.VoiceRecoActivity" />
activity
호출하기VoiceRecoActivity
를 이용하여 호출하기 전에 Intent
로 한 가지 정보는 꼭 넘겨주어야 합니다. 바로 APIKey
입니다.
APIKey
외에 설정할 수 있는 값이나 자세한 내용은 javadoc
을 참고합니다.
Intent i = new Intent(getApplicationContext(), VoiceRecoActivity.class);
i.putExtra(SpeechRecognizerActivity.EXTRA_KEY_API_KEY, apikey);
// apiKey는 신청과정을 통해 package와 매치되도록 발급받은 APIKey 문자열 값.
startActivityForResult(i, 0);
onActivityResult
이용제공된 샘플의 SpeechSampleActivity
의 onActivityResult
메서드를 참고하여 성공과 실패에 대한 결과를 처리할 수 있습니다. 성공 시에는 resultCode
가 RESULT_OK
이며, 에러가 발생하는 등의 실패가 발생했을 땐 RESULT_CANCELED
입니다.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) { // 성공
ArrayList<String> results = data.getStringArrayListExtra(VoiceRecoActivity.EXTRA_KEY_RESULT_ARRAY);
// ....
}
else if (requestCode == RESULT_CANCELED) { // 실패
int errorCode = data.getIntExtra(VoiceRecoActivity.EXTRA_KEY_ERROR_CODE, -1);
String errorMsg = data.getStringExtra(VoiceRecoActivity.EXTRA_KEY_ERROR_MESSAGE);
// ....
}
}
Intent
의 extra
값은 VoiceRecoActivity.java의 상단에서 알 수 있듯이 다음과 같은 key
들로 조회할 수 있습니다.
public static String EXTRA_KEY_RESULT_ARRAY = "result_array"; // 결과값 목록. ArrayList<String>
public static String EXTRA_KEY_MARKED = "marked"; // 첫번째 값의 신뢰도가 현저하게 높은 경우 true. 아니면 false. Boolean
public static String EXTRA_KEY_ERROR_CODE = "error_code"; // 에러가 발생했을 때 코드값. 코드값은 SpeechRecognizerClient를 참조. Integer
public static String EXTRA_KEY_ERROR_MESSAGE = "error_msg"; // 에러 메시지. String
VoiceRecoActivity
의 Override methodsonResourcesWillInitialize
메서드는 UI를 변경하지 않고 이용한다면 sample
의 내용을 그대로 이용할 수 있습니다.
일부 리소스를 변경하고자 할 때는 SpeechRecognizerClient
의 RES_STRINGS와 RES_VIEWID
Enum
과 관련된 문서를 참고하여 어떤 리소스의 ID가 어떤 상황에서 표시되는지 알 수 있습니다.
제공되는 기본 UI에서 리소스나 레이아웃을 변경할 때는 이미지 파일이나 strings 파일, layout xml을 직접 변경하는 것을 권장합니다.
@Override
protected void onResourcesWillInitialize() {
// ....
}
onRecognitionSuccess
메서드는 VoiceRecoActivity
를 통해 음성 인식을 성공했을 때 호출되는 메서드입니다.
샘플 프로젝트에서 오버라이드한 onRecognitionSuccess
메서드는 결과 목록을 호출한 Activity
로 값을 전달하도록 하였습니다.
메서드의 marked
파라미터는 결과목록의 첫번째 값이 신뢰도가 높은 값인지 알려줍니다. 결과 목록에서 첫번째 값의 신뢰도가 SpeechRecognizerClient.CONFIDENCE_PASSING_MARKED(int = 10)
보다 같거나 높으면 높은 신뢰도를 가지는 값으로 간주할 수 있습니다.
이와 별도로 결과 목록의 첫번째 값의 신뢰도가 낮으면 결과 목록을 UI에서 표시하고, 이 목록에서 사용자가 말한 단어를 선택할 수 있도록 도와줍니다.
이 단계를 거쳐서 값이 선택될 때도 marked
값은 true
입니다. marked
값이 false
가 되는 경우는 후보단어 목록 표시 생략하기에서 알 수 있습니다.
@Override
protected void onRecognitionSuccess(List<String> result, boolean marked) {
// ....
}
onRecognitionFailed
메서드는 VoiceRecoActivity
를 통해 수행한 음성 인식이 실패하거나 에러가 발생했을 때 호출되는 메서드입니다.
sample
에서의 기본 동작은 에러코드와 에러 메시지를 호출한 Activity
로 전달합니다.
@Override
protected void onRecognitionFailed(int errorCode, String errorMsg) {
// ....
}
기본 UI를 통한 구현은 기본적으로 높은 신뢰도를 가지지 못한 결과 목록을 얻었을 때 사용자에게 말한 내용을 판단하도록 거치는 과정이 있습니다.
이 과정을 생략하거나 다른 방법으로 안내를 하려면 SpeechRecognizerActivity
를 호출할 때 Intent
의 extra
값으로 SpeechRecognizerActivity.EXTRA_KEY_SHOW_SUGGEST_LIST
키값을 설정하면 됩니다.
설정하지 않으면 기본값은 true
이며, false
면 후보단어 목록 표시를 생략하고 true면 후보단어 목록을 표시합니다. 후보단어 표시를 생략한 채로 onRecognitionSuccess callback
메서드가 호출되면 신뢰도가 높은 결과값인지 판단할 근거가 부족해집니다.
그래서 후보단어 표시를 생략하고 결과 목록의 신뢰도가 낮을 때만 onRecognitionSuccess
메서드의 marked
파라미터 값이 false
가 됩니다.
Intent i = new Intent(getApplicationContext(), VoiceRecoActivity.class);
i.putExtra(SpeechRecognizerActivity.EXTRA_KEY_API_KEY, apikey);
i.putExtra(SpeechRecognizerActivity.EXTRA_KEY_SHOW_SUGGEST_LIST, false); // 후보단어 목록 표시 생략
startActivityForResult(i, 0);
서비스 모드란 음성인식 도메인이고, 각 도메인에 더 특화되어 있습니다.
서비스 모드 도메인 | 설명 |
---|---|
Dictation | 받아쓰기 모드이며 일반적인 문장, 대화체 인식에 사용 |
Local | 주소, 지역명 인식에 사용(예 : 카카오맵 앱 음성 인식) |
Web or Search | 웹 검색에 사용 (예 : 다음 앱 음성 인식) |
Word | 명령어 인식에 사용 |
user dict
(사용자 사전) 에 단어들을 넣어놓고 인식하면 그 단어들중에서만 인식됩니다. user dict
에는 한 단어 이상 반드시 들어가야 하며, user dict
가 비워져 있으면 에러가 반환됩니다. 그 외 서비스 모드에서는 사용자 사전 안에 있는 텍스트들을 좀 더 가중치를 줘서 인식합니다. 최대 허용 사이즈는 약 3000 단어 정도입니다.
message queue
, event handler
등을 사용해 비동기적으로 처리하고 onPartialResult
, onError
등의 이벤트 호출 함수 안에서 또 다시 음성 API 함수를 재호출하지 않습니다.(예 : onInactive
(ios 라이브러리의 경우 onFinished
) 호출 안에서 startListening
재호출하는 경우 지양)
stop(stopRecording 또는 stopListening)과 cancel 호출의 차이
종료시 마지막으로 호출되는 이벤트 함수
이중 실행 금지
음성 합성 API는 문자 데이타를 사람이 이해할 수 있는 음성 언어로 변환하는 문자-음성 변환 시스템 (Text-to-Speech system)입니다. 음성 합성 내부 규칙은 음성 합성 기본 내부 규칙을 참고합니다.
권한 설정앱의 AndroidManifest.xml 파일에는 다음과 같은 권한들을 설정합니다. bluetooth
는 선택사항입니다.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
음성 인식 기능과 마찬가지로 targetSdkVersion이 23(Android M) 이상일 경우에는 동적으로 사용자에게 권한을 받아야 합니다. 음성 인식 권한 설정을 참고하여 사용자에게 동적 권한을 획득해야 합니다.
음성 합성 기능을 이용하려면 먼저 라이브러리 초기화를 해야 합니다. 음성 합성 기능을 이용하는 곳에서 라이브러리를 초기화 하는 함수인 *initializeLibrary()*를 아래와 같이 호출합니다.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextToSpeechManager.getInstance().initializeLibrary(getApplicationContext());
}
// 더 이상 쓰지 않는 경우에는 다음과 같이 해제
public void onDestroy() {
super.onDestroy();
TextToSpeechManager.getInstance().finalizeLibrary();
}
라이브러리 초기화 후에는 TextToSpeechClient.Builder
를 사용하여 클라이언트를 생성합니다.
private TextToSpeechClient ttsClient;
...
ttsClient = new TextToSpeechClient.Builder()
.setSpeechMode(TextToSpeechClient.NEWTONE_TALK_1) // 음성합성방식
.setSpeechSpeed(1.0) // 발음 속도(0.5~4.0)
.setSpeechVoice(TextToSpeechClient.VOICE_WOMAN_READ_CALM) //TTS 음색 모드 설정(여성 차분한 낭독체)
.setListener(this)
.build();
설정 Key | 설명 |
---|---|
setSpeechMode(String) | TextToSpeechClient.NEWTONE_TALK_1 : 통계적 합성 방식 (기존) - 기존에 뉴톤톡 API로 제공되던 통계적 합성 방식은 음성의 통계적 특성을 분석하여 모델을 만들고 이를 이용하여 합성하는 방식으로, 녹음된 데이터에 없는 합성음을 안정적으로 합성해 낼 수 있어서 다양한 분야에 적용되어도 일관된 품질의 합성음을 생성해 낼 수 있고 음색 변환 등 다양한 응용에 적용할 수 있습니다. 일반적으로 편집 합성 방식에 비해 음질이 떨어집니다. TextToSpeechClient.NEWTONE_TALK_2 : 편집 합성 방식 - 새롭게 추가된 편집 합성 방식은 통계적 특성을 이용하는 것이 아니라 녹음된 음성 데이터 자체를 이용하여 필요한 음소들을 발췌하여 합성하는 방식입니다. 장점으로는 데이터 자체를 이용하므로 녹음에 사용된 문장과 동일한 영역의 문장들에 대해서는 통계적 합성 방식보다 자연스러운 음성을 만들어 낼 수 있습니다. 단점으로는 녹음 데이터에 없는 영역의 문장에서는 음질이 저하되는 단점이 있습니다. (예를 들어 대화체 음색을 이용하여 낭독체 문장을 합성하는 경우). 편집 합성 방식에서는 통계적 합성 방식과 달리 합성 속도 변경 기능은 제공하지 않습니다. |
setSpeechSpeed(double) | 발음속도 0.5 ~ 4.0 (1이 보통속도, 크면 빠르게, 작으면 느리게) |
setSpeechVoice(String) | TextToSpeechClient.VOICE_WOMAN_READ_CALM : 여성 차분한 낭독체 TextToSpeechClient.VOICE_MAN_READ_CALM : 남성 차분한 낭독체 TextToSpeechClient.VOICE_WOMAN_DIALOG_BRIGHT : 여성 밝은 대화체 TextToSpeechClient.VOICE_MAN_DIALOG_BRIGHT : 남성 밝은 대화체 |
음성합성은 멀티 스레드(Multi thread) 기반으로 동작하며 음성합성이 진행되는 과정에 따라 이벤트들이 호출되고 그에 따른 동작들을 구현해주면 됩니다. 음성인식과 달리 음성합성은 중간 결과가 없기 때문에, onFinished
와 onError
이벤트 밖에 없어서 비교적 구현이 간단합니다.
음성합성의 callback
을 받기위해서 TextToSpeechListener
를 구현해 줍니다.
모든 callback
함수는 UI thread가 아닌 background thread에서 호출될 수 있기 때문에, UI와 관련된 작업은 Activity.runOnUiThread(Runnable)
이나 Handler.post(Runnable)
을 통해 비동기로 호출해야 합니다.
onError
는 뉴톤톡 중에 에러가 발생한 경우 호출됩니다. onFinished
는 음성합성이 완료된 뒤에 호출됩니다.
//com.kakao.sdk.newtoneapi.TextToSpeechListener
@Override
public void onError(int code, String message) { //에러처리
handleError(code);
}
@Override
public void onFinished() { //음성합성이 종료될 때 호출된다.
int intSentSize = ttsClient.getSentDataSize(); //세션 중에 전송한 데이터 사이즈
int intRecvSize = ttsClient.getReceivedDataSize(); //세션 중에 전송받은 데이터 사이즈
final String strInacctiveText = "handleFinished() SentSize : " + intSentSize + " RecvSize : " + intRecvSize;
Log.i(TAG, strInacctiveText);
}
음성합성을 위한 텍스트를 넣고 play()
시키면 동작됩니다. play()
함수에 텍스트를 파라미터로 전달하거나 미리 텍스트를 세팅한 후 플레이 할 수도 있습니다.
//boolean com.kakao.sdk.newtoneapi.TextToSpeechClient.play(String)
//boolean com.kakao.sdk.newtoneapi.TextToSpeechClient.play()
//boolean com.kakao.sdk.newtoneapi.TextToSpeechClient.setSpeechText(String)
예)
String strText = "안녕하세요"
ttsClient.play(strText);
// 또는
ttsClient.setSpeechText(strText); //뉴톤톡 하고자 하는 문자열을 미리 세팅.
ttsClient.play(); //세팅된 문자열을 합성하여 재생.
합성된 음성이 재생되는 것을 중지시키려면 stop()
을 사용합니다.
//void com.kakao.sdk.newtoneapi.TextToSpeechClient.stop()
예)
ttsClient.stop();
합성된 음성이 재생중인지 확인하려면 isPlaying()을 사용합니다. 반환값이 True이면 재생중입니다.
//boolean com.kakao.sdk.newtoneapi.TextToSpeechClient.isPlaying()
예)
ttsClient.isPlaying();
onError
callback은 이름에서 알 수 있듯이 에러가 발생했을 때 호출됩니다. TextToSpeechClient
에서 다양한 에러 코드에 대응하는 'ERROR_' 로 시작하는 code
값들을 확인할 수 있습니다.
@Override
public void onError(int errorCode, String errorMsg) {
//TODO implement interface TextToSpeechListener method
}
음성 합성 API는 아래와 같은 에러코드를 전달합니다. TextToSpeechClient
에서 'ERROR_' 로 시작하는 static int
값들을 참고할 수 있습니다.
Error Code | description |
---|---|
ERROR_NONE | 정상 (오류가 아님.) |
ERROR_NETWORK | 네트워크 오류가 발생한 경우. |
ERROR_NETWORK_TIMEOUT | 네트워크 타임아웃이 발생한 경우. (클라이언트에서 SOCKET READ TIMEOUT 5초 초과) |
ERROR_CLIENT_INETRNAL | 클라이언트 내부 오류가 발생한 경우. |
ERROR_SERVER_INTERNAL | 서버에서 오류가 발생한 경우. |
ERROR_SERVER_TIMEOUT | 서버 최대 접속시간 초과.(세션 30초 초과 또는 서버에서 SOCKET READ TIMEOUT 5초 초과) |
ERROR_SERVER_AUTHENTICATION | APPID 또는 APPKEY가 틀려서 인증이 실패한 경우. |
ERROR_SERVER_SPEECH_TEXT_BAD | 뉴톤톡 텍스트 오류 (처리과정을 거친 후 문자열의 길이가 0 또는 문자열의 길이가 0이상이지만 발음할 수 없는 문자로 구성된 경우. (^^, ----, (), [], !!!!! ) 등.) |
ERROR_SERVER_SPEECH_TEXT_EXCESS | 뉴톤톡 최대 허용 길이 초과.(합성 길이가 30초 이상이거나 100byte이상 길이의 단어가 포함되어 있는 경우.) |
ERROR_SERVER_SPEECH_TEXT_FORBIDDEN | 뉴톤톡 금칙어 오류. |
ERROR_SERVER_ALLOWED_REQUESTS_EXCESS | 뉴톤톡 서비스 최대 허용 횟수 초과. |
ERROR_UNSUPPORTED_SERVICE | 음성합성 서비스 모드 오류. |
ERROR_UNKNOWN | 알 수 없는 오류. |
onFinished
메서드는 TextToSpeechClient
의 합성된 음성의 재생이 종료된 이후에 호출됩니다. 여러가지 합성음 작업을 성공적으로 마치고 나면 가장 마지막에 호출되는 메서드입니다.
@Override
public void onFinished() {
//TODO implement interface TextToSpeechListener method
}