在 移动端 接入实时语音识别方面,讯飞和腾讯云都是优秀的选择,但各有其特点和优势。以下是对两者的详细比较:
一、讯飞语音识别
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 接入要求
内容 | 说明 |
---|---|
请求协议 | ws[s] (为提高安全性,强烈推荐wss) |
请求地址 | ws[s]: //rtasr.xfyun.cn/v1/ws?{请求参数} 注:服务器IP不固定,为保证您的接口稳定,请勿通过指定IP的方式调用接口,使用域名方式调用 |
接口鉴权 | 签名机制,详见数字签名 |
字符编码 | UTF-8 |
响应格式 | 统一采用JSON格式 |
开发语言 | 任意,只要可以向讯飞云服务发起WebSocket请求的均可 |
音频属性 | 采样率16k、位长16bit、单声道 |
音频格式 | pcm |
数据发送 | 建议音频流每40ms发送1280字节 |
语言种类 | 中文普通话、中英混合识别、英文,小语种以及中文方言可以到控制台-实时语音转写-方言/语种处添加试用或购买 |
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 文件中添加如下权限,在实际项目中还需要动态申请权限。
< uses-permission android:name="android.permission.INTERNET"/>
<!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 --> <uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--读取网络信息状态 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
注意:如需在打包或者生成APK的时候进行混淆,请在proguard.cfg中添加如下代码:
-keepclasseswithmembernames class * { # 保持 native 方法不被混淆
native <methods>;
}
-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。_星火aiuihttps://shuaici.blog.csdn.net/article/details/141430041