独居的生活很是无聊,如果有什么成精的东西和我聊聊天就好了…
“独居的生活很是无聊,如果有什么成精的东西和我聊聊天就好了”,基于这个独特的想法,我,决定让某一样东西成精,赋予它阅读指定文字的能力。
目前市面上有两款产品可以较好的实现语音相关的功能,分别是百度语音识别与科大讯飞语音识别,在这两个中我选科大讯飞。如果Python、Node.js、C#、C++、PHP作为你的开发语言,百度语音识别可以找到相关文档。如果开发的语音识别是搭载着HarmonyOS系统上,可以选科大讯飞。二者各有所长、各有所短。
在操作前需要先前往官网下载语音相关的demo,demo里面有我们集成语音技术必要的资源。
下载后,将assets、libs文件夹拷贝至自己的项目,在
AndroidManifest.xml
静态声明部分权限。
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
接着动态申请危险权限:
private void initPermission() {
String permissions[] = {Manifest.permission.RECORD_AUDIO,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
ArrayList<String> toApplyList = new ArrayList<String>();
for (String perm : permissions) {
if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this,
perm)) {
toApplyList.add(perm);
}
}
String tmpList[] = new String[toApplyList.size()];
if (!toApplyList.isEmpty()) {
ActivityCompat.requestPermissions(this, toApplyList.toArray(tmpList), 123);
}
}
使用科大讯飞语音识别需要初始化,初始化即创建语音配置对象,只有初始化后才可以使用MSC的各项服务。建议将初始化放在程序入口处(如Application、Activity的onCreate方法)。
SpeechUtility.createUtility(this, "appid=" + getString(R.string.app_id));
实现语音识别监听
private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {
public void onResult(RecognizerResult results, boolean isLast) {
if (!isLast) {
}
}
public void onError(SpeechError error) {
Toast.makeText(MainActivity.this, error.getPlainDescription(true),
Toast.LENGTH_SHORT).show();
}
};
接着就是 call 孙子啦
public void call() {
mIat = SpeechRecognizer.createRecognizer(this, mInitListener);
if (null == mIat) {
Toast.makeText(this, "创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化",
Toast.LENGTH_SHORT).show();
return;
}
mIatResults.clear();
mIat.setParameter(SpeechConstant.PARAMS, null);
mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");
if (language.equals("zh_cn")) {
String lag = mSharedPreferences.getString("iat_language_preference",
"mandarin");
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
mIat.setParameter(SpeechConstant.ACCENT, lag);
} else {
mIat.setParameter(SpeechConstant.LANGUAGE, language);
}
mIat.setParameter("view_tips_plain", "false");
mIat.setParameter(SpeechConstant.VAD_BOS, mSharedPreferences.getString(
"iat_vadbos_preference", "4000"));
mIat.setParameter(SpeechConstant.VAD_EOS, mSharedPreferences.getString(
"iat_vadeos_preference", "1000"));
mIat.setParameter(SpeechConstant.ASR_PTT, mSharedPreferences.getString(
"iat_punc_preference", "1"));
mIat.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH,
Environment.getExternalStorageDirectory() + "/msc/iat.wav");
mIatDialog.setListener(mRecognizerDialogListener);
mIatDialog.show();
}
看到 show()
方法没?随着 show()
方法的执行,语音识别功能也就完成了喔
爷爷问,这时孙子无法回答爷爷的话,对于爷爷的问候,只能默默地看着爷爷,像个木头人一样不知所措。
[En]
Grandpa asked, at this time the grandson can not reply to Grandpa’s words, for Grandpa’s greeting, can only silently look at Grandpa, like a wooden man like at a loss.
当孙子说话时,你需要使用语音合成。语音合成与语音听写相反,是将一段文字转换成语音,可以根据需要合成不同音色、速度和语调的声音,使机器说话像人一样。不仅如此,还可以根据个人需要,更换孙辈,高大上的孙辈可以经常认国语,多语种哦。
[En]
When Sun Tzu speaks, you need to use speech synthesis. Speech synthesis, contrary to speech dictation, converts a section of text into speech, which can synthesize sounds with different timbre, speed and intonation according to needs, making the machine speak like a human. Not only that, but also according to personal needs, change grandchildren, high-end grandchildren can often recognize national languages, multi-language oh.
孙子怎么知道该回复什么信息呢?
[En]
How does Sun Tzu know what message to reply to?
回复消息是我们预先设置的,语音不同,回复内容也不一样。语音识别和命令词识别是有区别的。命令词识别是通过文本输出识别语音并提取预设关键字。另一方面,语音识别将一系列语音翻译成文本并直接输出。
[En]
The reply message is we preset in advance, the speech is different, the reply content is not the same. There is a difference between speech recognition and command word recognition. Command word recognition is to recognize speech and extract preset keywords through text output. On the other hand, speech recognition translates a series of speech into text and outputs them directly.
我把爷爷发言与孙子的答复提前插入 Sqlite
,待语音识别到的文本与存储在 Sqlite
里爷爷的发言一致时,取对应的答案,通过语音输出,孙子也就不再是一个哑巴了。
那么,让我们来实现孙子的声音回复。
[En]
So, let’s realize Sun Tzu’s voice reply.
private void grandsonAnswer(String answer) {
cloudVoicersEntries = getResources().getStringArray(R.array.voicer_cloud_entries);
cloudVoicersValue = getResources().getStringArray(R.array.voicer_cloud_values);
mTts = SpeechSynthesizer.createSynthesizer(this, mInitListener);
mTts.setParameter(SpeechConstant.PARAMS, null);
mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
mTts.setParameter(SpeechConstant.VOICE_NAME, voicerCloud);
mTts.setParameter(SpeechConstant.SPEED, "50");
mTts.setParameter(SpeechConstant.PITCH, "50");
mTts.setParameter(SpeechConstant.VOLUME, "50");
mTts.setParameter(SpeechConstant.STREAM_TYPE, "3");
mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");
mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH,
Environment.getExternalStorageDirectory() + "/msc/tts.wav");
int code = mTts.startSpeaking(answer, mTtsListener);
if (code != ErrorCode.SUCCESS) {
Toast.makeText(this, "语音合成失败,错误码: " + code + ",请点击网址https://www.xfyun" +
".cn/document/error-code查询解决方案", Toast.LENGTH_SHORT).show();
}
}
代码copy一下运行起来便是这样的结果了 ↓
如果您希望听到您的孙子调用Gardpa,只需在调用该方法时传递一个Gardpa参数即可。
[En]
If you want to hear your grandson call Grandpa, just pass a Grandpa parameter when you call the method.
public void callGrandpa(View view) {
grandsonAnswer("爷爷~");
}
我厌倦了听我孙子的声音,我可以把它换成我孙女的声音。
[En]
I’m tired of hearing my grandson’s voice, and I can switch it to my granddaughter’s voice.
public void update(View view) {
new AlertDialog.Builder(this).setTitle("更换孙子或孙女")
.setSingleChoiceItems(cloudVoicersEntries,
selectedNumCloud,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
voicerCloud = cloudVoicersValue[which];
selectedNumCloud = which;
dialog.dismiss();
}
}).show();
}
可切换的孙子、孙女
<string-array name="voicer_cloud_entries">
<item>小燕item>
<item>小宇item>
<item>凯瑟琳item>
<item>亨利item>
<item>玛丽item>
<item>小研item>
<item>小琪item>
<item>小峰item>
<item>小梅item>
<item>小莉item>
<item>小蓉item>
<item>小芸item>
<item>小坤item>
<item>小强 item>
<item>小莹item>
<item>小新item>
<item>楠楠item>
<item>老孙item>
string-array>
<string-array name="voicer_cloud_values">
<item>xiaoyanitem>
<item>xiaoyuitem>
<item>catherineitem>
<item>henryitem>
<item>vimaryitem>
<item>vixyitem>
<item>xiaoqiitem>
<item>vixfitem>
<item>xiaomeiitem>
<item>xiaolinitem>
<item>xiaorongitem>
<item>xiaoqianitem>
<item>xiaokunitem>
<item>xiaoqiangitem>
<item>vixyingitem>
<item>xiaoxinitem>
<item>nannanitem>
<item>vilsitem>
string-array>
到这里,能想到的功能也就都完成了,附上demo运行GIF
最后,不要忘记,当接口被破坏时,相应的变量应该释放内存。
[En]
Finally, don’t forget that when the interface is destroyed, the corresponding variables should release memory.
@Override
protected void onDestroy() {
super.onDestroy();
if( null != mIat ){
mIat.cancel();
mIat.destroy();
}
if( null != mTts ){
mTts.stopSpeaking();
mTts.destroy();
}
}
本文代码已上传至:开发一个会叫自己”爷爷”的”孙子”,是一种什么样的体验?
参考文献:
1、Android 科大讯飞语音识别(详细步骤+源码)
2、科大讯飞在线语音听写 Android SDK 文档
3、科大讯飞在线语音合成 Android SDK 文档
Original: https://blog.csdn.net/baidu_41616022/article/details/119580034
Author: 宾有为
Title: 开发一个会叫自己“爷爷”的“孙子”,是一种什么样的体验?
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/512717/
转载文章受原作者版权保护。转载请注明原作者出处!