赞
踩
开发工具是Android Studio,实现了一个中英互译的安卓app,调用科大讯飞的语音识别、语音合成api以及百度翻译api,需要科大讯飞的appid,以及百度翻译的appid和密钥。
App运行截图:
科大讯飞开放平台官网:
先去讯飞开发平台注册成为开发者,申请APPID,创建新应用,需要确定应用名称、应用分类、应用功能描述,其中应用分类我选的是应用-教育学习-学习。当新应用创建好后,每天免费服务量是500。
*SDK调用方式只需APPID。APIKey或APISecret适用于WebAPI调用方式。
需要在项目main文件夹下新建Jnilibs并拷贝libmsc.so,msc.jar需要拷贝至项目libs下,并且右键jar添加Add As Library,sdk下文件夹main/assets/,自带UI页面(iflytek文件夹)和相关其他服务资源文件(语法文件、音频示例、词表),使用自带UI接口时,可以将assets/iflytek文件拷贝到项目中。
注:arm版本已经逐步淘汰了,arm架构的推荐使用armeabi-v7a。
当你点按钮开始说话时,会出现动画及图标,这些来源就是iflytek文件夹下的。
在工程 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"/>
- <!--获取当前wifi状态 -->
- <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.READ_CONTACTS"/>
- <!--外存储写权限,构建语法需要用到此权限 -->
- <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"/>
- <!--手机定位信息,用来为语义等功能提供定位,提供更精准的服务-->
- <!--定位信息是敏感信息,可通过Setting.setLocationEnable(false)关闭定位请求 -->
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
- <!--如需使用人脸识别,还要添加:摄像头权限,拍照需要用到 -->
- <uses-permission android:name="android.permission.CAMERA" />
只介绍科大讯飞这部分核心代码
引入依赖
- import com.iflytek.cloud.ErrorCode;
- import com.iflytek.cloud.InitListener;
- import com.iflytek.cloud.RecognizerListener;
- import com.iflytek.cloud.RecognizerResult;
- import com.iflytek.cloud.SpeechConstant;
- import com.iflytek.cloud.SpeechError;
- import com.iflytek.cloud.SpeechRecognizer;
- import com.iflytek.cloud.SpeechSynthesizer;
- import com.iflytek.cloud.SpeechUtility;
- import com.iflytek.cloud.SynthesizerListener;
- import com.iflytek.cloud.ui.RecognizerDialog;
- import com.iflytek.cloud.ui.RecognizerDialogListener;
定义变量:
- // 用HashMap存储听写结果
- private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();
- private Button bt_zhspeech;
- private SpeechSynthesizer mTts;// 语音合成
- private SpeechRecognizer mIat;// 语音听写
- private Button bt_enwrite;
- private RecognizerDialog iatDialog;//听写动画
- static String flag;
- private String[] voiceName = {"xiaoyan", "xiaoyu", "catherine", "henry",
- "vimary", "vixy", "xiaoqi", "vixf", "xiaomei", "xiaolin",
- "xiaorong", "xiaoqian", "xiaokun", "xiaoqiang", "vixying",
- "xiaoxin", "nannan", "vils"};
onCreate函数:
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- ......
- // 初始化即创建语音配置对象,只有初始化后才可以使用MSC的各项服务
- SpeechUtility.createUtility(this, SpeechConstant.APPID + "=APPID");
- // 语音合成 1.创建SpeechSynthesizer对象, 第二个参数:本地合成时传InitListener
- mTts = SpeechSynthesizer.createSynthesizer(MainActivity.this,
- mTtsInitListener);
- // 语音听写1.创建SpeechRecognizer对象,第二个参数:本地听写时传InitListener
- mIat = SpeechRecognizer.createRecognizer(this, mTtsInitListener);
- // 1.创建SpeechRecognizer对象,第二个参数:本地听写时传InitListener
- iatDialog = new RecognizerDialog(this,
- mTtsInitListener);
- }
语音识别及语音合成:
- public void starSpeech() { //语音合成
- // 2.合成参数设置,详见《科大讯飞MSC API手册(Android)》SpeechSynthesizer 类
- mTts.setParameter(SpeechConstant.VOICE_NAME, voiceName[5]);// 设置发音人
- mTts.setParameter(SpeechConstant.SPEED, "50");// 设置语速
- mTts.setParameter(SpeechConstant.VOLUME, "80");// 设置音量,范围0~100
- mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);//设置云端
- // 设置合成音频保存位置(可自定义保存位置),保存在“./sdcard/iflytek.pcm”
- // 保存在SD卡需要在AndroidManifest.xml添加写SD卡权限
- // 如果不需要保存合成音频,注释该行代码
- mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, "./sdcard/iflytek.pcm");
- // 3.开始合成
- mTts.startSpeaking(result, mSynListener);
- // 合成监听器
- }
-
- /**
- * 初始化参数开始听写
- *
- * @Description:
- */
- private void starWrite() {
- // 2.设置听写参数,详见《科大讯飞MSC API手册(Android)》SpeechConstant类
- // 语音识别应用领域(:iat,search,video,poi,music)
- mIat.setParameter(SpeechConstant.DOMAIN, "iat");
- // 接收语言中文
- mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
- // 接受的语言是普通话
- mIat.setParameter(SpeechConstant.ACCENT, "mandarin ");
- // 设置听写引擎(云端)
- mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
- iatDialog.setListener(mRecognizerDialogListener);
- iatDialog.show();
- Toast.makeText(getApplication(), "请开始说话…", Toast.LENGTH_SHORT).show();
- // 3.开始听写
- //mIat.startListening(mRecoListener);
- // 听写监听器
- }
-
- /**
- * 语音听写监听
- */
- private RecognizerListener mRecoListener = new RecognizerListener() {
- // 听写结果回调接口(返回Json格式结果,用户可参见附录12.1);
- // 一般情况下会通过onResults接口多次返回结果,完整的识别内容是多次结果的累加;
- // 关于解析Json的代码可参见MscDemo中JsonParser类;
- // isLast等于true时会话结束。
- public void onResult(RecognizerResult results, boolean isLast) {
- Log.d(TAG, results.getResultString());
- printResult(results);
- }
-
- // 会话发生错误回调接口
- public void onError(SpeechError error) {
- // 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
- if (error.getErrorCode() == 10118) {
- Toast.makeText(getApplicationContext(), "你好像没有说话哦",
- Toast.LENGTH_SHORT).show();
- }
- Toast.makeText(getApplicationContext(), error.getPlainDescription(true),
- Toast.LENGTH_SHORT).show();
-
- }// 获取错误码描述}
-
- // 开始录音
- public void onBeginOfSpeech() {
- Log.d(TAG, "开始说话");
- Toast.makeText(getApplicationContext(), "开始说话",
- Toast.LENGTH_SHORT).show();
- }
-
- // 结束录音
- public void onEndOfSpeech() {
- Log.d(TAG, "说话结束");
- Toast.makeText(getApplicationContext(), "说话结束",
- Toast.LENGTH_SHORT).show();
- }
-
- // 扩展用接口
- public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
- }
-
- //音量
- @Override
- public void onVolumeChanged(int volume, byte[] data) {
- // TODO Auto-generated method stub
- Log.d(TAG, "当前说话音量大小" + volume);
-
- }
-
- };
-
- /**
- * 听写UI监听器
- */
- private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {
- public void onResult(RecognizerResult results, boolean isLast) {
- printResult(results);
- }
-
- /**
- * 识别回调错误.
- */
- public void onError(SpeechError error) {
- Toast.makeText(getApplication(), error.getPlainDescription(true), Toast.LENGTH_SHORT).show();
- }
-
- };
- /**
- * 语音合成监听
- */
- private SynthesizerListener mSynListener = new SynthesizerListener() {
- // 会话结束回调接口,没有错误时,error为null
- public void onCompleted(SpeechError error) {
- if (error != null) {
- Log.d("mySynthesiezer complete code:", error.getErrorCode()
- + "");
- } else {
- Log.d("mySynthesiezer complete code:", "0");
- }
- }
-
- // 缓冲进度回调
- // percent为缓冲进度0~100,beginPos为缓冲音频在文本中开始位置,endPos表示缓冲音频在文本中结束位置,info为附加信息。
- public void onBufferProgress(int percent, int beginPos, int endPos,
- String info) {
- }
-
- // 开始播放
- public void onSpeakBegin() {
- }
-
- // 暂停播放
- public void onSpeakPaused() {
- }
-
- // 播放进度回调
- // percent为播放进度0~100,beginPos为播放音频在文本中开始位置,endPos表示播放音频在文本中结束位置.
- public void onSpeakProgress(int percent, int beginPos, int endPos) {
- }
-
- // 恢复播放回调接口
- public void onSpeakResumed() {
- }
-
- // 会话事件回调接口
- public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) {
- }
- };
-
- /**
- * 初始化语音合成监听。
- */
- private InitListener mTtsInitListener = new InitListener() {
- @SuppressLint("ShowToast")
- @Override
- public void onInit(int code) {
- Log.d(TAG, "InitListener init() code = " + code);
- if (code != ErrorCode.SUCCESS) {
- // showTip("初始化失败,错误码:" + code);
- Toast.makeText(getApplicationContext(), "初始化失败,错误码:" + code,
- Toast.LENGTH_SHORT).show();
- } else {
- // 初始化成功,之后可以调用startSpeaking方法
- // 注:有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成,
- // 正确的做法是将onCreate中的startSpeaking调用移至这里
- }
- }
- };
语音识别官方参考文档:
语音听写 Android SDK 文档 | 讯飞开放平台文档中心https://www.xfyun.cn/doc/asr/voicedictation/Android-SDK.html#_1%E3%80%81%E7%AE%80%E4%BB%8B 语音合成官方参考文档:
去百度翻译开放平台注册成为开发者,获得APPID,进行开发者认证(如仅需标准版可跳过),开通通用翻译API服务,创建新应用,需要确定选择开通的服务版本(可以选择个人开发者、企业开发者)、申请认证、填写申请表格,申请表格主要包括*您的应用名称是什么?(名称不超过40个字符)、有无应用相关的介绍链接(不超过40个字符)、请简单介绍下您的应用(不超过200字)、服务器地址(使用服务器调用API的用户,请填写服务器IP地址,APP等客户端不需要填写;多个服务器中间请用“|”隔开,如“113.173.40.255|124.12.122.1”;填写IP后,只有填写的IP才可被调用,请谨慎填写,不超过100个字符)
官方参考文档:
百度翻译开放平台百度翻译开放平台提供通用翻译API、定制化翻译API、图片翻译SDK及语音翻译SDK服务,全面满足开发者的翻译需求。https://fanyi-api.baidu.com/doc/11
通用翻译API通过HTTP接口对外提供多语种互译服务。您只需要通过调用通用翻译API,传入待翻译的内容,并指定要翻译的源语言(支持源语言语种自动检测)和目标语言种类,就可以得到相应的翻译结果。
通用翻译API HTTP地址:
http://api.fanyi.baidu.com/api/trans/vip/translate
通用翻译API HTTPS地址:
https://fanyi-api.baidu.com/api/trans/vip/translate
输入参数
字段名 | 类型 | 必填参数 | 描述 | 备注 |
---|---|---|---|---|
q | TEXT | Y | 请求翻译query | UTF-8编码 |
from | TEXT | Y | 翻译源语言 | 语言列表(可设置为auto) |
to | TEXT | Y | 译文语言 | 语言列表(不可设置为auto) |
appid | TEXT | Y | APP ID | 可在管理控制台查看 |
salt | TEXT | Y | 随机数 | |
sign | TEXT | Y | 签名 | appid+q+salt+密钥 的MD5值 |
以下字段仅开通了词典、TTS者需填写 | ||||
tts | STRING | N | 是否显示语音合成资源 | tts=0显示,tts=1不显示 |
dict | STRING | N | 是否显示词典资源 | dict=0显示,dict=1不显示 |
以下字段仅开通“我的术语库”用户需填写 | ||||
action | STRING | N | 是否需使用自定义术语干预通用翻译API | 1=是,0=否 |
请求方式:可使用GET或POST方式,如使用POST方式,Content-Type请指定为:application/x-www-form-urlencoded
字符编码:统一采用UTF-8编码格式:
query长度:为保证翻译质量,请将单次请求长度控制在 6000 bytes以内。(汉字约为2000个)
签名生成方法:
签名是为了保证调用安全,使用MD5算法生成的一段字符串,生成的签名长度为32位,签名中的英文字符均为小写格式。
生成方法:
Step1、将请求参数中的 APPID(appid), 翻译query(q, 注意为UTF-8编码), 随机数(salt), 以及平台分配的密钥(可在管理控制台查看),按照 appid+q+salt+密钥 的顺序拼接得到字符串1。
Step2、对字符串1做md5,得到32位小写的sign。
输出参数
返回结果是json格式,包含以下字段:
字段名 | 类型 | 描述 | 备注 |
---|---|---|---|
from | TEXT | 翻译源语言 | 返回用户指定的语言,或自动检测的语言(源语言设为auto时) |
to | TEXT | 译文语言 | 返回用户指定的目标语言 |
trans_result | MIXED LIST | 翻译结果 | 返回翻译结果,包含src 和 dst 字段。 |
src | TEXT | 原文 | |
dst | TEXT | 译文 | |
error_code | Int32 | 错误码 | 仅当出现错误时显示 |
以下字段仅开通词典、TTS资源者可见 | |||
src_tts | 原文tts | mp3格式,暂时无法指定发音 | |
dst_tts | 译文tts | mp3格式,暂时无法指定发音 | |
dict | 中英词典资源 | 返回中文或英文词典资源,包含音标、简明释义等内容 |
接入举例
例如:将英文单词apple翻译成中文:
请求参数:
q=apple
from=en
to=zh
appid=2015063000000001(请替换为您的appid)
salt=1435660288(随机码)
平台分配的密钥: 12345678
生成签名sign:
Step1. 拼接字符串1:
拼接appid=2015063000000001+q=apple+salt=1435660288+密钥=12345678
得到字符串1:"2015063000000001apple143566028812345678"
Step2. 计算签名sign(对字符串1做md5加密)
sign=md5(2015063000000001apple143566028812345678),
得到 sign=f89f9594663708c1605f3d736d01d2d4
拼接完整请求:
注:也可使用POST方式,如POST方式传送,Content-Type请指定为:application/x-www-form-urlencoded
语言列表
源语言语种不确定时可设置为 auto,目标语言语种不可设置为auto。但对于非常用语种,语种自动检测可能存在误差。
语言简写 | 名称 |
---|---|
auto | 自动检测 |
zh | 中文 |
en | 英语 |
yue | 粤语 |
wyw | 文言文 |
jp | 日语 |
kor | 韩语 |
fra | 法语 |
spa | 西班牙语 |
th | 泰语 |
ara | 阿拉伯语 |
ru | 俄语 |
pt | 葡萄牙语 |
de | 德语 |
it | 意大利语 |
el | 希腊语 |
nl | 荷兰语 |
pl | 波兰语 |
bul | 保加利亚语 |
est | 爱沙尼亚语 |
dan | 丹麦语 |
fin | 芬兰语 |
cs | 捷克语 |
rom | 罗马尼亚语 |
slo | 斯洛文尼亚语 |
swe | 瑞典语 |
hu | 匈牙利语 |
cht | 繁体中文 |
vie | 越南语 |
错误码列表
当翻译结果无法正常返回时,请参考下表处理:
错误码 | 含义 | 解决方法 |
---|---|---|
52000 | 成功 | |
52001 | 请求超时 | 重试 |
52002 | 系统错误 | 重试 |
52003 | 未授权用户 | 检查您的 appid 是否正确,或者服务是否开通 |
54000 | 必填参数为空 | 检查是否少传参数 |
54001 | 签名错误 | 请检查您的签名生成方法 |
54003 | 访问频率受限 | 请降低您的调用频率 |
54004 | 账户余额不足 | 请前往管理控制台为账户充值 |
54005 | 长query请求频繁 | 请降低长query的发送频率,3s后再试 |
58000 | 客户端IP非法 | 检查个人资料里填写的 IP地址 是否正确 可前往管理控制平台修改 IP限制,IP可留空 |
58001 | 译文语言方向不支持 | 检查译文语言是否在语言列表里 |
58002 | 服务当前已关闭 | 请前往管理控制台开启服务 |
90107 | 认证未通过或未生效 | 请前往我的认证查看认证进度 |
引入依赖:
- import retrofit2.Call;
- import retrofit2.Callback;
- import retrofit2.Response;
- import retrofit2.Retrofit;
- import retrofit2.converter.gson.GsonConverterFactory;
翻译方法:
- public void translate() {
- //准备请求百度翻译接口需要的参数
- String word = fanyiWords;//需查询的单词 q
- String from = "auto";//源语种 en 英语 zh 中文
- //String中英文占用一个字节,中文占用两个字节,
- //利用String的这个存储特性可以用来判断String中有没有中文。
- // to = "zh"; //没有汉字 英译中
- to = "en";//含有汉字 中译英
- String appid = "appid";//appid 管理控制台有
- String salt = (int) (Math.random() * 100 + 1) + "";//随机数这里范围是[0,100]整数无强制要求
- String key = "secret key";//密钥 管理控制台有
- String secretKey = appid + word + salt + key;// secretKey = appid+q+salt+密钥
- String sign = MD5Utils.getMD5Code(secretKey);// 签名 = secretKey 的MD5加密32位字母小写
- Log.d(TAG, "secretKey:" + secretKey);
- Log.d(TAG, "sign: " + sign);
-
- Retrofit retrofitBaidu = new Retrofit.Builder()
- .baseUrl("https://fanyi-api.baidu.com/api/trans/vip/")
- .addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器
- .build();
- BaiduTranslateService baiduTranslateService =retrofitBaidu.create(BaiduTranslateService.class);
- Call<RespondBean> call = baiduTranslateService.translate(word, from, to, appid, salt, sign);
- call.enqueue(new Callback<RespondBean>() {
- @Override
- public void onResponse(Call<RespondBean> call, Response<RespondBean> response) {
- //请求成功
- Log.d(TAG, "onResponse: 请求成功");
- RespondBean respondBean = response.body();//返回的JSON字符串对应的对象
- result = respondBean.getTrans_result().get(0).getDst();//获取翻译的字符串String
- Log.d(TAG, "中译英结果" + result);
- }
- @Override
- public void onFailure(Call<RespondBean> call, Throwable t) {
- //请求失败 打印异常
- Log.d(TAG, "onResponse: 请求失败 " + t);
- }
- });
- }
BaiduTranslateService
- import retrofit2.Call;
- import retrofit2.http.Field;
- import retrofit2.http.FormUrlEncoded;
- import retrofit2.http.POST;
- //源URL https://fanyi-api.baidu.com/api/trans/vip/translate
- //参数如下
- // String q 英文单词/中文
- // String from 原始语种 zh中文/eh英文
- // String to 目标语种 zh中文/eh英文
- // String from zh中文/eh英文
- // String appid 你的appid
- // String salt 随机数(整形转字符串)
- // String sign 签名 32位字母小写MD5编码的 appid+q+salt+密钥
- public interface BaiduTranslateService {
- //翻译接口
- //表示提交表单数据,@Field注解键名
- //适用于数据量少的情况
- @POST("translate")
- @FormUrlEncoded
- Call<RespondBean> translate(@Field("q") String q, @Field("from") String from, @Field("to") String to, @Field("appid") String appid, @Field("salt") String salt,
- @Field("sign") String sign);
- }
MD5Utils
- import java.security.MessageDigest;
-
- /**
- * 加密解密工具类(对字符串加密) MD5加密
- */
- public class MD5Utils {
-
- /**
- * MD5加密算法使用 对字符串加密
- *
- * @param info 参数为需要加密的String
- * @return 返回加密后的String
- */
- public static String getMD5Code(String info) {
- try {
- MessageDigest md5 = MessageDigest.getInstance("MD5");
- md5.update(info.getBytes("utf-8"));//设置编码格式
- byte[] encryption = md5.digest();
- StringBuffer stringBuffer = new StringBuffer();
- for (int i = 0; i < encryption.length; i++) {
- if (Integer.toHexString(0xff & encryption[i]).length() == 1) {
- stringBuffer.append("0").append(Integer.toHexString(0xff & encryption[i]));
- } else {
- stringBuffer.append(Integer.toHexString(0xff & encryption[i]));
- }
- }
- return stringBuffer.toString();
- } catch (Exception e) {
- return "MD5加密异常";
- }
- }
-
- }
RespondBean:
- import java.util.List;
-
- public class RespondBean {
-
- /**
- * from : zh
- * to : en
- * trans_result : [{"src":"你好","dst":"Hello"}]
- */
-
- private String from;
- private String to;
- private List<TransResultBean> trans_result;
-
- public String getFrom() {
- return from;
- }
-
- public void setFrom(String from) {
- this.from = from;
- }
-
- public String getTo() {
- return to;
- }
-
- public void setTo(String to) {
- this.to = to;
- }
-
- public List<TransResultBean> getTrans_result() {
- return trans_result;
- }
-
- public void setTrans_result(List<TransResultBean> trans_result) {
- this.trans_result = trans_result;
- }
-
- public static class TransResultBean {
- /**
- * src : 你好
- * dst : Hello
- */
-
- private String src;
- private String dst;
-
- public String getSrc() {
- return src;
- }
-
- public void setSrc(String src) {
- this.src = src;
- }
-
- public String getDst() {
- return dst;
- }
-
- public void setDst(String dst) {
- this.dst = dst;
- }
- }
- }
百度通用翻译API官方技术文档:百度翻译开放平台百度翻译开放平台提供通用翻译API、定制化翻译API、拍照翻译SDK及语音翻译SDK服务,全面满足开发者的翻译需求。https://fanyi-api.baidu.com/api/trans/product/apidoc#joinFile
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。