讯飞与腾讯云:Android 实时语音识别服务对比选择_腾讯云语音识别
在 移动端 接入实时语音识别方面,讯飞和腾讯云都是优秀的选择,但各有其特点和优势。以下是对两者的详细比较:
一、讯飞语音识别
1.1 讯飞实时语音识别介绍
1.1.1 功能特点
1.支持多种语言识别,满足不同语种用户的需求。(普通话/英语免费,其他语音可试用半年。试用到期后需单独购买,价格为:2万/个/年)
2.提供丰富的API接口,不太方便 Android 开发者接入。
1.1.2 优势
1.讯飞在语音识别领域有较高的知名度和市场占有率。
2.提供了详细的开发文档和示例代码,方便开发者快速上手。
3.支持定制化开发,可以根据用户需求进行个性化定制。
1.2 接入流程
1.2.1 注册账号并创建应用
注册讯飞开放平台账号,创建应用并获得AppID。
1.2.2 实时语音转写API文档
实时语音转写(Real-time ASR)基于深度全序列卷积神经网络框架,通过 WebSocket 协议,建立应用与语言转写核心引擎的长连接,开发者可实现将连续的音频流内容,实时识别返回对应的文字流内容。
支持的音频格式: 采样率为16K,采样深度为16bit的pcm_s16le音频
1.2.3 接入要求
注:服务器IP不固定,为保证您的接口稳定,请勿通过指定IP的方式调用接口,使用域名方式调用
Demo 中不包含Android SDK,感觉有一些麻烦,该方案暂时保留,去腾讯云语音识别看看。
讯飞官方文档:实时语音转写 API 文档 | 讯飞
二、腾讯云实时语音识别
2.1 腾讯云实时语音识别介绍
2.1.1 功能特点
腾讯云语音识别(ASR)基于深度学习技术,具备较高的语音识别准确性。
提供实时语音识别和离线语音识别两种类型,满足不同场景需求。
支持多种语种和方言识别,如中文、英文、粤语等。
2.1.2 优势
腾讯云作为国内领先的云服务提供商,拥有强大的技术实力和丰富的应用场景。
提供了丰富的语音识别和语音合成产品,可以满足开发者多样化的需求。
提供了可视化控制台和详尽的 SDK 和 API 文档,方便开发者进行配置和管理。
2.2 接入流程
2.2.1 注册腾讯云账号
注册腾讯云账号(需要个人实名认证/企业认证),并在控制台中创建语音识别应用。
2.2.2 获取相关的凭证信息
获取相关的凭证信息(如SecretId和SecretKey),用于后续的API调用。
2.2.3 下载SDK等相关资料
直接下载SDK,SDK中包含简易可运行的Demo。
2.2.4 导入SDK和添加其他依赖
添加录音文件识别 SDK aar,将 asr-realtime-release.aar 放在 libs 目录下,在 App 的 build.gradle 文件中添加。
implementation(name: \'asr-realtime-release\', ext: \'aar\') implementation \'com.squareup.okhttp3:okhttp:4.2.2\'
2.2.5 添加用户权限
在工程 AndroidManifest.xml 文件中添加如下权限,在实际项目中还需要动态申请权限。
注意:如需在打包或者生成APK的时候进行混淆,请在proguard.cfg中添加如下代码:
-keepclasseswithmembernames class * { # 保持 native 方法不被混淆
native ;
}
-keep public class com.tencent.aai.*
-keep public class com.qq.wx.voice.*
2.2.6 初始化腾讯云SDK
private void initAAIClient() { int appId = xxxxx; int projectId = 0; //此参数固定为0; String secretId = \"xxxx\"; String secretKey = \"xxx\"; try { /**直接鉴权**/ // 1. 签名鉴权类,sdk中给出了一个本地的鉴权类,您也可以自行实现CredentialProvider接口,在您的服务器上实现鉴权签名 if (aaiClient == null) { aaiClient = new AAIClient(SparkMessageTencentActivity.this, appId, projectId, secretId, new LocalCredentialProvider(secretKey)); } }
2.2.7 初始化语音识别请求
AudioRecognizeRequest.Builder builder = new AudioRecognizeRequest.Builder(); final AudioRecognizeRequest audioRecognizeRequest = builder //设置数据源,数据源要求实现PcmAudioDataSource接口,您可以自己实现此接口来定制您的自定义数据源,例如从第三方推流中获 .pcmAudioDataSource(new AudioRecordDataSource(false))// 使用SDK内置录音器作为数据源,false:不保存音频 .setEngineModelType(\"16k_zh\") // 设置引擎参数(\"16k_zh\" 通用引擎,支持中文普通话+英文) .setFilterDirty(0) // 0 :默认状态 不过滤脏话 1:过滤脏话 .setFilterModal(0) // 0 :默认状态 不过滤语气词 1:过滤部分语气词 2:严格过滤 .setFilterPunc(0) // 0 :默认状态 不过滤句末的句号 1:滤句末的句号 .setConvert_num_mode(1) //1:默认状态 根据场景智能转换为阿拉伯数字;0:全部转为中文数字。 .setNeedvad(1) //0:关闭 vad,1:默认状态 开启 vad。语音时长超过一分钟需要开启,如果对实时性要求较高,并且时间较短的输入,建议关闭 // .setHotWordId(\"\")//热词 id。用于调用对应的热词表,如果在调用语音识别服务时,不进行单独的热词 id 设置,自动生效默认热词;如果进行了单独的热词 id 设置,那么将生效单独设置的热词 id。 //.setCustomizationId(\"\")//自学习模型 id。如果设置了该参数,那么将生效对应的自学习模型 .build();
2.2.8 初始化语音识别结果监听器
final AudioRecognizeResultListener audioRecognizeResultlistener = new AudioRecognizeResultListener() { /** * 返回分片的识别结果 * @param request 相应的请求 * @param result 识别结果 * @param seq 该分片所在句子的序号 (0, 1, 2...) * 此为中间态结果,会被持续修正 */ @Override public void onSliceSuccess(AudioRecognizeRequest request, AudioRecognizeResult result, int seq) { Log.d(TAG, \"分片on slice success..\"); Log.d(TAG, \"分片slice seq =\" + seq + \"voiceid =\" + result.getVoiceId() + \"result = \" + result.getText() + \"startTime =\" + result.getStartTime() + \"endTime = \" + result.getEndTime()); Log.d(TAG, \"分片on slice success.. ResultJson =\" + result.getResultJson());//后端返回的未解析的json文本,您可以自行解析获取更多信息 //主线程更新UI 实时识别结果 handlerMain.post(() -> binding.tvVoiceFlowText.setText(result.getText())); } /** * 返回语音流的识别结果 * @param request 相应的请求 * @param result 识别结果 * @param seq 该句子的序号 (1, 2, 3...) * 此为稳定态结果,可做为识别结果用与业务 */ @Override public void onSegmentSuccess(AudioRecognizeRequest request, AudioRecognizeResult result, int seq) { Log.d(TAG, \"语音流on segment success\"); Log.d(TAG, \"语音流segment seq =\" + seq + \"voiceid =\" + result.getVoiceId() + \"result = \" + result.getText() + \"startTime =\" + result.getStartTime() + \"endTime = \" + result.getEndTime()); Log.d(TAG, \"语音流on segment success.. ResultJson =\" + result.getResultJson());//后端返回的未解析的json文本,您可以自行解析获取更多信息 } /** * 识别结束回调,返回所有的识别结果 * @param request 相应的请求 * @param result 识别结果,sdk内会把所有的onSegmentSuccess结果合并返回,如果业务不需要,可以只使用onSegmentSuccess返回的结果 * 注意:仅收到onStopRecord回调时,表明本次语音流录音任务已经停止,但识别任务还未停止,需要等待后端返回最终识别结果, * 如果此时立即启动下一次录音,结果上一次结果仍会返回,可以调用cancelAudioRecognize取消上一次识别任务 * 当收到 onSuccess 或者 onFailure时,表明本次语音流识别完毕,可以进行下一次识别; */ @Override public void onSuccess(AudioRecognizeRequest request, String result) {// handler.post(() -> {// start.setEnabled(true);// }); Log.d(TAG, \"识别结束, onSuccess..\"); Log.d(TAG, \"识别结束, result = \" + result); //最终识别结果,主线程更新UI handlerMain.post(() -> sendInputText(result)); } /** * 识别失败 * @param request 相应的请求 * @param clientException 客户端异常 * @param serverException 服务端异常 * @param response 服务端返回的json字符串(如果有) * 注意:仅收到onStopRecord回调时,表明本次语音流录音任务已经停止,但识别任务还未停止,需要等待后端返回最终识别结果, * 如果此时立即启动下一次录音,结果上一次结果仍会返回,可以调用cancelAudioRecognize取消上一次识别任务 * 当收到 onSuccess 或者 onFailure时,表明本次语音流识别完毕,可以进行下一次识别; */ @Override public void onFailure(AudioRecognizeRequest request, final ClientException clientException, final ServerException serverException, String response) { if (response != null) { Log.d(TAG, \"onFailure response.. :\" + response); } if (clientException != null) { Log.d(TAG, \"onFailure..:\" + clientException); } if (serverException != null) { Log.d(TAG, \"onFailure..:\" + serverException); } //识别失败处理,主线程更新UI handlerMain.post(() -> { setUIInputView(); }); } };
2.2.9 识别配置及识别状态监听器
// 4、自定义识别配置 final AudioRecognizeConfiguration audioRecognizeConfiguration = new AudioRecognizeConfiguration.Builder() //分片默认40ms,可设置40-5000,如果您不了解此参数不建议更改 //.sliceTime(40) // 是否使能静音检测, .setSilentDetectTimeOut(false) // 静音检测超时停止录音可设置>2000ms,setSilentDetectTimeOut为true有效,超过指定时间没有说话将关闭识别;需要大于等于sliceTime,实际时间为sliceTime的倍数,如果小于sliceTime,则按sliceTime的时间为准 .audioFlowSilenceTimeOut(5000) // 音量回调时间,需要大于等于sliceTime,实际时间为sliceTime的倍数,如果小于sliceTime,则按sliceTime的时间为准 .minVolumeCallbackTime(80) .build(); /** * 识别状态监听器 */ final AudioRecognizeStateListener audioRecognizeStateListener = new AudioRecognizeStateListener() { float minVoiceDb = Float.MAX_VALUE; float maxVoiceDb = Float.MIN_VALUE; /** * 开始录音 * @param request */ @Override public void onStartRecord(AudioRecognizeRequest request) { voiceStatType = 1; minVoiceDb = Float.MAX_VALUE; maxVoiceDb = Float.MIN_VALUE; Log.d(TAG, \"onStartRecord..\"); handlerMain.post(() -> { voiceBuffer.setLength(0); binding.tvVoiceFlowText.setText(\"\"); binding.llPupSoundRecording.setVisibility(View.VISIBLE); binding.ivSoundRecordingAnimation.setVisibility(View.VISIBLE); voiceStatType = 1; setUIVoiceView(); if (animationDrawable != null) { animationDrawable.start(); } }); } /** * 结束录音 * @param request */ @Override public void onStopRecord(AudioRecognizeRequest request) { Log.d(TAG, \"onStopRecord..\"); handlerMain.post(() -> { Log.e(TAG, \"ivStopSoundRecording:\" + voiceStr); try { binding.llPupSoundRecording.setVisibility(View.GONE); binding.ivSoundRecordingAnimation.setVisibility(View.GONE); if (animationDrawable != null) { animationDrawable.stop(); } voiceStatType = 9; setUIVoiceView(); } catch (Exception e) { e.printStackTrace(); } }); } /** * 返回音频流, * 用于返回宿主层做录音缓存业务。 * 由于方法跑在sdk线程上,这里多用于文件操作,宿主需要新开一条线程专门用于实现业务逻辑 * @param audioDatas */ @Override public void onNextAudioData(final short[] audioDatas, final int readBufferLength) { Log.d(TAG, \"onNextAudioData..\"); } /** * 静音检测回调 * 当设置AudioRecognizeConfiguration setSilentDetectTimeOut为true时,如触发静音超时,将触发此回调 * 当setSilentDetectTimeOutAutoStop 为true时,触发此回调的同时会停止本次识别,相当于手动调用了 aaiClient.stopAudioRecognize() */ @Override public void onSilentDetectTimeOut() { Log.d(TAG, \"onSilentDetectTimeOut: \"); //您的业务逻辑 } /** * 音量变化时回调。该方法已废弃 * * 建议使用 {@link #onVoiceDb(float db)} * * @deprecated 建议使用 {@link #onVoiceDb(float db)}. */ @Override public void onVoiceVolume(AudioRecognizeRequest request, final int volume) { Log.d(TAG, \"onVoiceVolume..\"); } /** * 音量变化时回调。 */ @Override public void onVoiceDb(float volumeDb) { Log.d(TAG, \"onVoiceDb: \" + volumeDb); handlerMain.post(new Runnable() { @Override public void run() { if (volumeDb > maxVoiceDb) { maxVoiceDb = volumeDb; } if (volumeDb < minVoiceDb) { minVoiceDb = volumeDb; } if (minVoiceDb != Float.MAX_VALUE && maxVoiceDb != Float.MIN_VALUE) {// voiceDb.setText(getString(R.string.voice_db) + volumeDb// + \"(\" + minVoiceDb + \" ~ \" + maxVoiceDb + \")\"); } } }); } };
2.2.10 启动语音识别
new Thread(() -> { Log.d(TAG, \"startAudioRecognize..\"); if (aaiClient != null) { aaiClient.startAudioRecognize(audioRecognizeRequest, audioRecognizeResultlistener, audioRecognizeStateListener, audioRecognizeConfiguration); } Log.d(TAG, \"startAudioRecognize..222\"); }).start();
2.2.11 停止语音识别
if (aaiClient != null) { aaiClient.stopAudioRecognize();}
2.2.12 取消实时语音识别
if (aaiClient != null) { //取消语音识别,丢弃当前任务,丢弃最终结果 boolean taskExist = aaiClient.cancelAudioRecognize();}
腾讯云语音识别:实时语音识别-腾讯云
三、选择建议(腾讯云)
讯飞免费额度:实时语音转写(一年50小时,支持中英文)。
接入方式:仅支持API接入。
腾讯云免费额度:实时语音识别(每月5小时)。
接入方式:支持 Android SDK 相当友好。
综上所述,讯飞在语音识别领域有较高的知名度和市场占有率,拥有是优秀的Android语音识别解决方案。所以我选择腾讯云。
相关推荐
讯飞与腾讯云:Android 语音识别服务对比选择-CSDN博客文章浏览阅读1.9k次,点赞87次,收藏84次。讯飞与腾讯云在Android语音识别领域均表现出色,各具特色。讯飞提供全面的语音识别功能,支持多种语言和离线识别,拥有高知名度和市场占有率,适合高度定制化需求。腾讯云则基于深度学习技术,提供高准确性的语音识别,支持多种语种和方言,且作为领先的云服务提供商,拥有丰富的语音识别和语音合成产品,适合快速接入并希望利用其他云服务的开发者。两者均提供详细的开发文档和API接口,但开发者在选择时应根据自身需求、成本因素和用户评价进行综合考虑,以确保选择最具性价比的方案。https://shuaici.blog.csdn.net/article/details/142849015Android SDK 遇到的坑之讯飞语音合成-CSDN博客文章浏览阅读1.9k次,点赞50次,收藏36次。loadLibrary msc error:java.lang.UnsatisfiedLinkError: dlopen failed: library \"libmsc.so\" not found组件未安装.(错误码:21002)_组件未安装.(错误码:21002)
https://shuaici.blog.csdn.net/article/details/141169429Android SDK 遇到的坑之 AIUI(星火大模型)-CSDN博客文章浏览阅读3.4k次,点赞92次,收藏66次。需要给桌面机器人(医康养)应用做语音指引/控制/健康咨询等功能。AIUI常见错误:唤醒无效;错误码:600103;错误码:600022。_星火aiui
https://shuaici.blog.csdn.net/article/details/141430041