用键盘输入讯息,对年轻人或许稀松平常,但对长者而言,使用语音的方式或许更轻松。所以除了画面字体放大外,我们也使用语音识别与输出技术,提供长者更友善的工具。
上次的文章 [Zenbo开发系列] 06-安装DDE语料到Zenbo 有讲到 DDE 的问题和使用 Android 语音识别与输出的原因。那麽,今天就要来介绍 Android 这边的实作罗!
STT (Speach to Text)
语音转文字的功能用在左下的麦克风按钮,点击之後会有个对话框请使用者说出问句。
我们让麦克风按钮被点击後,执行一个 Intent。
ImageButton btnSpeak = findViewById(R.id.speak);
btnSpeak.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent sttIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
sttIntent.putExtra(
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
);
sttIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
sttIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.start_to_speak));
try {
startActivityForResult(sttIntent, REQUEST_CODE_STT);
} catch (ActivityNotFoundException e) {
Log.d(TAG, "onClick: " + e.getLocalizedMessage());
Toast.makeText(ChatActivity.this, "Your device does not support STT.", Toast.LENGTH_LONG).show();
}
}
});
之後我们就能在 onActivityResult
取得语音辨识的结果,并把文字显示到 EditText 上。
这样设计的原因是想解决 DDE 常辨识不到文字的状况,使用者可以确认语音识别的内容是否正确,再点选送出纽。
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_STT) {
if (resultCode == Activity.RESULT_OK && data != null) {
ArrayList<String> result = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
if (result != null) {
String recognizedText = result.get(0);
mUserInput.setText(recognizedText);
}
}
}
}
TTS (Text to Speach)
我是在 ViewModel 的呼叫使用 TTSSpeaker。
这边参数需要传两个 Callback 给 TTSSpeaker。
TTSCallback
是我自己写的,主要用来确认 TTS 初始化是否成功,onReady
才能执行将句子念出来的动作。UtteranceProgressListener
是要确认 TTS 目前的状况,onStart
(开始)、onDone
(念完)、onError
(错误)。private void speak(String message) {
TTSCallback ttsCallback = new TTSCallback() {
@Override
public void onReady() {
mSpeaker.speak(message);
}
@Override
public void onFail() {
Log.d(TAG, "ttsCallback onFail");
}
};
UtteranceProgressListener speakingStatus = new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {
Log.d(TAG, "speakingStatus onStart");
}
@Override
public void onDone(String utteranceId) {
Log.d(TAG, "speakingStatus onDone");
mSpeaker.destroy();
}
@Override
public void onError(String utteranceId) {
Log.d(TAG, "speakingStatus onError");
mSpeaker.destroy();
}
};
mSpeaker = new TTSSpeaker(mApplication, ttsCallback, speakingStatus);
}
public class TTSSpeaker {
private TextToSpeech mTTS;
private TTSCallback mCallback;
private Application mApplication;
public TTSSpeaker(Application application, TTSCallback callback, UtteranceProgressListener utteranceProgressListener) {
mApplication = application;
mCallback = callback;
mTTS = new TextToSpeech(mApplication, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
int result = mTTS.setLanguage(Locale.TAIWAN); //设定语言为中文
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "This Language is not supported");
} else {
mTTS.setPitch(1); //语调(1为正常语调;0.5比正常语调低一倍;2比正常语调高一倍)
mTTS.setSpeechRate(1); //速度(1为正常速度;0.5比正常速度慢一倍;2比正常速度快一倍)
}
mTTS.setOnUtteranceProgressListener(utteranceProgressListener);
mCallback.onReady();
} else {
Log.e("TTS", "Initialization Failed!");
mCallback.onFail();
}
}
});
}
public void speak(String message) {
mTTS.speak(message, TextToSpeech.QUEUE_FLUSH, null, "tts1");
// destroy();
}
public void destroy() {
mTTS.shutdown();
}
}
<<: 【把玩Azure DevOps】Day27 Build Pipeline的YAML结构描述:多个Agent Job
>>: [Day 24] Edge Impulse + BLE Sense实现手势动作辨识(上)
前情提要 上一集让人等到很崩溃的,终於..郑列终於吹嘘完了 阿物件:我跟你说... 我:... (接...
Aloha~!又是我少女人妻Uerica!这阵子家人住院,从急诊到加护病房再到普通病房,看到形形色色...
周慕姿x邓惠文 聊《过度努力》、《我想看你变老的样子》 今天看到《过度努力》这本书,一路找到这个访谈...
今天处里剩下的部分:checker 函式和它注入页面的辅助函式。 checker checker 函...
第一次遇到发PR,原来就是档案修改後,发通知请原作来拉回去(Pull)的请求(Request) 1....