zoukankan      html  css  js  c++  java
  • 发送语音+讯飞翻译 项目案例

    数据结构

    1. public LongSparseArray<RecordBean> recordList=new LongSparseArray<>();
    封装所有相关数据的Bean
    1. public class RecordBean {
    2. public static final String VOICE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "voice";
    3. public static final String XF_VOICE_FILE_PATH = VOICE_PATH + File.separator + "xf_temp_file.wav";
    4. public String pcmPath;
    5. public String aacPath;
    6. public boolean startRecordSuccess = false;//开始录音成功,即调用JJMediaSDK.startRecord的返回值
    7. public boolean endRecordSuccess = false;//结束录音成功,即调用JJMediaSDK.stopRecord的返回值
    8. public long startTime;//开始录音时间
    9. public long endTime;//结束录音时间
    10. public boolean sendVoiceSuccess = false;//上传并发送成功
    11. public boolean translateSuccess = false;//翻译成功
    12. public String qnKey;//上传到七牛的语音地址
    13. public long clientid;//当上传七牛成功后发送一条socket语音消息,此消息需要客户端生成一个clientid。同时这也是集合recordList中的key
    14. public int msgid;//当上传七牛成功后发送一条socket语音消息,服务器响应时会返回一个msgid,以后就需根据msgid发送及获取语音对应的文本
    15. public String content;//讯飞翻译出的内容
    16. public RecordBean(long time) {
    17. clientid = time;
    18. String data = new SimpleDateFormat("yyyy_MM_dd HH_mm_ss SSS", Locale.getDefault()).format(new Date(time));
    19. this.aacPath = VOICE_PATH + File.separator + "aac_" + data + ".aac";
    20. this.pcmPath = VOICE_PATH + File.separator + "pcm_" + data + ".pcm";
    21. L.i("语音文件保存路径:" + pcmPath + " " + aacPath);
    22. }
    23. public static class VoiceBean {//发送的语音消息的内容。仅仅包含语音URL路径以及语音时长
    24. String path;
    25. int duration;
    26. public VoiceBean(String path, int duration) {
    27. this.path = path;
    28. this.duration = duration;
    29. }
    30. }
    31. }

    长按录制语音相关逻辑

    1. //长按说话
    2. mChatInputWidget.setPressListener(new PressListener() {
    3. private long key;//集合recordList中的key,同时也是RecordBean中的clientid,同时也是语音消息的clientid
    4. @Override
    5. public void pressing() {
    6. if (micOnoff == 1) {//是否正在上麦(占用录音设备):0,未指定;1,开;2,关
    7. ToastHelper.showToastInThread("亲,发送语音功能需要下麦哦...");
    8. } else { //注意,以下代码要在具有录音权限时访问
    9. AudioManager audioManager = (AudioManager) ChatActivity.this.getSystemService(Context.AUDIO_SERVICE);
    10. audioManager.setMicrophoneMute(false);//关闭麦克风静音
    11. //键为当前时间,以保证唯一性
    12. key = System.currentTimeMillis();
    13. RecordBean recordBean = new RecordBean(key);
    14. recordList.put(key, recordBean);
    15. //调用JNI代码启动录音,录音成功后会生成两个文件,这两个文件的存放位置封装在了recordBean中
    16. JJMediaSDK.captureStop();//停止录音
    17. recordBean.startRecordSuccess = JJMediaSDK.startRecord(recordBean.pcmPath, recordBean.aacPath);
    18. recordBean.startTime = System.currentTimeMillis();//记录开始和结束录音时间,以获取录音时长
    19. if (!recordBean.startRecordSuccess) Toast.makeText(ChatActivity.this, "录音失败", Toast.LENGTH_SHORT).show();
    20. else pressSpeeking("正在说话...");//一个自定义的UI,当按住的时候一直显示,当松开的时候消失
    21. }
    22. }
    23. @Override
    24. public void pressStop() {
    25. RecordBean recordBean = recordList.get(key);//获取当前key对应的RecordBean
    26. if (recordBean == null || !recordBean.startRecordSuccess) {//肯定是录音失败了
    27. Toast.makeText(ChatActivity.this, "录音失败", Toast.LENGTH_SHORT).show();
    28. return;
    29. }
    30. AudioManager audioManager = (AudioManager) ChatActivity.this.getSystemService(Context.AUDIO_SERVICE);
    31. audioManager.setMicrophoneMute(true);//开启麦克风静音
    32. //调用JNI代码结束录音。JNI同事说这里不会失败的。谁信啊,万一存储空间不足或手机突然爆掉了呢?
    33. recordBean.endRecordSuccess = JJMediaSDK.stopRecord();
    34. recordBean.endTime = System.currentTimeMillis();
    35. pressSpeekingdimiss();
    36. if (!recordBean.endRecordSuccess) {
    37. Toast.makeText(ChatActivity.this, "录音失败", Toast.LENGTH_SHORT).show();
    38. return;
    39. }
    40. //****************************************【第一个异步:异步上传语音】*****************************************
    41. //异步上传语音到七牛,当上传成功后发送一条socket消息通知语音的URL路径,此时其他用户就可以播放此语音了
    42. //同时,服务器收到此消息后会做出响应,主要是返回一个msgid,以后就可以根据msgid通知及获取语音对应的文本了
    43. VoiceUtils.uploadVoiceAndSendMsg(ChatActivity.this, recordBean);
    44. //****************************************【第二个异步:异步讯飞翻译】*****************************************
    45. if (mIat == null) mIat = VoiceUtils.getSpeechRecognizerInstance(ChatActivity.this);//讯飞SDK初始化
    46. if (mIat == null) return;//讯飞SDK初始化失败
    47. //讯飞SDK翻译过程及状态监听
    48. RecognizerListener recognizerListener = VoiceUtils.getRecognizerListener(content -> {//翻译成功回调
    49. recordBean.content = content;
    50. recordBean.translateSuccess = true;
    51. Toast.makeText(ChatActivity.this, recordBean.content, Toast.LENGTH_SHORT).show();
    52. //**************************【将上传到七牛的语音和讯飞翻译的内容关联起来】******************************
    53. //如果第一个异步已经完成,则直接发一条socket消息,将两者内容联系在一起;否则等第一个异步完成以后再做处理
    54. if (recordBean.sendVoiceSuccess) SendMsgUtils.sendVoiceContentMsg(ChatActivity.this, recordBean);
    55. });
    56. // 函数调用返回值
    57. int ret = mIat.startListening(recognizerListener);
    58. if (ret != ErrorCode.SUCCESS) {
    59. Toast.makeText(ChatActivity.this, "翻译失败", Toast.LENGTH_SHORT).show();
    60. L.i("讯飞SDK翻译失败,错误码:" + ret);
    61. } else {
    62. byte[] audioData = VoiceUtils.readSDFile(recordBean.pcmPath);//读取SDK返回的pcm文件流
    63. if (null != audioData) {
    64. L.i("讯飞SDK开始音频流识别");
    65. mIat.writeAudio(audioData, 0, audioData.length);
    66. mIat.stopListening();
    67. } else {
    68. mIat.cancel();
    69. Toast.makeText(ChatActivity.this, "讯飞SDK读取音频流失败", Toast.LENGTH_SHORT).show();
    70. }
    71. }
    72. }
    73. });

    发送三条消息

    1. public class SendMsgUtils {
    2. /**
    3. * 发送语音、Gif图等通用聊天消息
    4. *
    5. * @param activity 必须是ChatActivity或ChatActivityPrivate
    6. * @param msgType 例如Common.e_MsgType.MSGTYPE_GIF_VALUE
    7. * @param content 消息内容,一般都是json格式
    8. */
    9. public static void sendNormalMsg(Activity activity, int msgType, String content, long clientid) {
    10. if (activity instanceof ChatActivity) {
    11. if (msgType == Common.e_MsgType.MSGTYPE_VOICE_VALUE || msgType == Common.e_MsgType.MSGTYPE_GIF_VALUE) {
    12. int roleType = ((ChatActivity) activity).getRoleType();
    13. if (roleType <= 0) {//游客
    14. Toast.makeText(activity, "您没有权限发送此类型消息", Toast.LENGTH_SHORT).show();
    15. return;
    16. }
    17. }
    18. }
    19. int groupId = 0;
    20. boolean isGroup = false;
    21. int dstId = 0;
    22. if (activity instanceof ChatActivity) {
    23. groupId = ((ChatActivity) activity).getGroupId();
    24. isGroup = ((ChatActivity) activity).isGroup();
    25. dstId = ((ChatActivity) activity).getDstId();
    26. } else if (activity instanceof ChatActivityPrivate) {
    27. groupId = ((ChatActivityPrivate) activity).getGroupId();
    28. isGroup = ((ChatActivityPrivate) activity).isGroup();
    29. dstId = ((ChatActivityPrivate) activity).getDstId();
    30. }
    31. ChatReqHelper.sendNormalMsg(content, groupId, isGroup, dstId, clientid);
    32. ChatModel model = new ChatModel(content, ChatModel.RIGHT, msgType);
    33. model.clientid = clientid;
    34. model.setMsgTime((int) (System.currentTimeMillis() / 1000));
    35. model.setGroupId(groupId);
    36. model.setSrcUser(ChatReqHelper.getUserInfo());
    37. if (activity instanceof ChatActivity) {
    38. ((ChatActivity) activity).getmGroupChats().add(0, model);
    39. ((ChatActivity) activity).getmRvSquareChat().getAdapter().notifyItemInserted(0);
    40. ((ChatActivity) activity).getmRvSquareChat().scrollToPosition(0);
    41. } else if (activity instanceof ChatActivityPrivate) {
    42. Common.UserInfo_t dstUserInfo = Common.UserInfo_t.getDefaultInstance().newBuilderForType().setUserId(dstId).build();
    43. model.setDstUser(dstUserInfo);
    44. ((ChatActivityPrivate) activity).getmGroupChats().add(0, model);
    45. ((ChatActivityPrivate) activity).getmRvSquareChat().getAdapter().notifyItemInserted(0);
    46. ((ChatActivityPrivate) activity).getmRvSquareChat().scrollToPosition(0);
    47. }
    48. }
    49. /**
    50. * 发送语音消息(里面只有语音的URL路径及时长),里面用的完全就是sendNormalMsg的逻辑
    51. *
    52. * @param activity 必须是ChatActivity或ChatActivityPrivate
    53. * @param recordBean 封装所有信息的bean
    54. */
    55. public static void sendNormalVoiceMsg(Activity activity, RecordBean recordBean) {
    56. //当上传七牛成功后发送一条socket消息,当收到响应时(会返回一个msgid)说明此socket消息发送成功了
    57. int duration = (int) ((recordBean.endTime - recordBean.startTime) / 1000);
    58. RecordBean.VoiceBean voiceBean = new RecordBean.VoiceBean(recordBean.qnKey, duration);
    59. String content = new Gson().toJson(voiceBean);//{"path:":"", duration:100}
    60. sendNormalMsg(activity, Common.e_MsgType.MSGTYPE_VOICE_VALUE, content, recordBean.clientid);
    61. L.i("发送语音消息。content=" + content + "。clientid=" + recordBean.clientid);
    62. }
    63. /**
    64. * 发送语音所对应的文本消息,目的是将上传到七牛的【语音】和讯飞翻译的【内容】关联起来
    65. */
    66. public static void sendVoiceContentMsg(Activity activity, RecordBean recordBean) {
    67. if (recordBean == null) return;
    68. if (recordBean.sendVoiceSuccess && recordBean.translateSuccess && recordBean.msgid != 0) {
    69. int groupId = 0, dstId = 0;
    70. if (activity instanceof ChatActivity) {
    71. groupId = ((ChatActivity) activity).getGroupId();
    72. dstId = ((ChatActivity) activity).getDstId();
    73. } else if (activity instanceof ChatActivityPrivate) {
    74. groupId = ((ChatActivityPrivate) activity).getGroupId();
    75. dstId = ((ChatActivityPrivate) activity).getDstId();
    76. }
    77. ChatSvr.CMDVoiceContentSubmit message = ChatSvr.CMDVoiceContentSubmit.newBuilder()
    78. .setGroupid(groupId)//群id
    79. .setSrcuid(AccountManager.getInstance().getServiceUserId())//消息发起者id
    80. .setDstuid(dstId)//消息接收者id(群聊传0)
    81. .setMsgid(recordBean.msgid)//msgid,此msgid是由服务器返回的
    82. .setContent(recordBean.content)//语音消息翻译成文本的内容
    83. .build();
    84. LoginConnection.voiceContentSubmit(message.toByteArray(), null);
    85. L.i("发送语音文本消息。content=" + recordBean.content + "。msgid=" + recordBean.msgid);
    86. if (recordBean.pcmPath != null && new File(recordBean.pcmPath).delete()) L.i("成功删除pcm临时文件");
    87. if (recordBean.aacPath != null && new File(recordBean.aacPath).delete()) L.i("成功删除aac临时文件");
    88. //移除集合中的此RecordBean
    89. LongSparseArray<RecordBean> recordList = null;
    90. if (activity instanceof ChatActivity) recordList = ((ChatActivity) activity).recordList;
    91. else if (activity instanceof ChatActivityPrivate) recordList = ((ChatActivityPrivate) activity).recordList;
    92. if (recordList != null) {
    93. recordList.remove(recordBean.clientid);
    94. L.i("成功移除recordBean:" + recordBean.clientid);
    95. }
    96. } else L.i("RecordBean状态错误" + recordBean.toString());
    97. }
    98. /**
    99. * 查询语音文本消息。这时已经与RecordBeanme没有任何关系了,这里的msgid是后台返回的
    100. */
    101. public static void qryVoiceContentMsg(Activity activity, int msgid) {
    102. int groupId = 0, dstId = 0;
    103. if (activity instanceof ChatActivity) {
    104. groupId = ((ChatActivity) activity).getGroupId();
    105. dstId = ((ChatActivity) activity).getDstId();
    106. } else if (activity instanceof ChatActivityPrivate) {
    107. groupId = ((ChatActivityPrivate) activity).getGroupId();
    108. dstId = ((ChatActivityPrivate) activity).getDstId();
    109. }
    110. ChatSvr.CMDQryChatMsgReq req = ChatSvr.CMDQryChatMsgReq.newBuilder()
    111. .setGroupid(groupId)//群id
    112. .setSrcuid(AccountManager.getInstance().getServiceUserId())//消息发起者id
    113. .setDstuid(dstId)//消息接收者id(群聊传0)
    114. .setMsgid(msgid)//msgid
    115. .build();
    116. LoginConnection.qryChatMsgReq(req.toByteArray(), null);
    117. L.i("查询语音文本消息。msgid=" + msgid + "。groupId=" + groupId);
    118. }
    119. }

    服务器的两个响应

    1. public void onEventMainThread(BaseEvent event) {
    2. if (event.getEvent() == EventHelper.EVENT_GROUPMSGRECV) {
    3. if (event.getData() instanceof ChatSvr.CMDGroupMsgRecv) {
    4. //异步上传语音到七牛成功后,客户端发送一条socket消息通知语音的URL路径
    5. //这是当服务器收到此消息后做出的响应,我们主要是拿到回一个msgid,以后就可以根据msgid通知语音对应的文本了
    6. ChatSvr.CMDGroupMsgRecv msgRecv = (ChatSvr.CMDGroupMsgRecv) event.getData();
    7. for (int i = 0; i < recordList.size(); i++) {
    8. Long key = recordList.keyAt(i);
    9. if (msgRecv.getClientMSgId() == key) {//RecordBean的clientid和recordList的key时同一个数
    10. RecordBean recordBean = recordList.get(key);
    11. recordBean.sendVoiceSuccess = true;
    12. recordBean.msgid = msgRecv.getMsgId();
    13. L.i("发送语音响应:msgid=" + recordBean.msgid + " clientid=" + recordBean.clientid);
    14. //**************************【将上传到七牛的语音和讯飞翻译的内容关联起来】******************************
    15. //如果第二个异步已经完成,则直接发一条socket消息,将两者内容联系在一起;否则等第二个异步完成以后再做处理
    16. if (recordBean.translateSuccess) SendMsgUtils.sendVoiceContentMsg(this, recordBean);
    17. break;
    18. }
    19. }
    20. }
    21. return;
    22. }
    23. if (event.getEvent() == EventHelper.EVENT_QRY_CHAT_MSG) {
    24. //**********************************************【响应查询语音消息】************************************************
    25. if (event.getData() instanceof ChatSvr.CMDQryChatMsgResp) {
    26. ChatSvr.CMDQryChatMsgResp resp = (ChatSvr.CMDQryChatMsgResp) event.getData();
    27. if (resp.getMsg() != null) {
    28. int msgID = resp.getMsg().getMsgId();
    29. String voiceContent;
    30. if (resp.getMsg().getVoiceContent() != null) voiceContent = resp.getMsg().getVoiceContent().getData();
    31. else voiceContent = "翻译失败";
    32. Toast.makeText(this, "msgID:" + msgID + " 内容:" + voiceContent, Toast.LENGTH_SHORT).show();
    33. L.i("查询语音文本响应。" + "msgID:" + msgID + " 内容:" + voiceContent);
    34. }
    35. }
    36. return;
    37. }
    38. }

    讯飞监听、上传语音等

    1. public class VoiceUtils {
    2. public interface OnRecognizerResultListener {
    3. void onResult(String content);
    4. }
    5. public static RecognizerListener getRecognizerListener(OnRecognizerResultListener listener) {
    6. return new RecognizerListener() {
    7. StringBuilder sb = new StringBuilder();
    8. @Override
    9. public void onBeginOfSpeech() {// 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
    10. L.i("onBeginOfSpeech");
    11. }
    12. @Override
    13. public void onError(SpeechError error) {
    14. L.i("onError:" + error.getErrorCode() + " " + error.getErrorDescription());
    15. //http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=13056&fromuid=44990
    16. // 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
    17. // 如果使用本地功能(语记)需要提示用户开启语记的录音权限。
    18. //没有数据,vad_bos设置问题
    19. }
    20. @Override
    21. public void onEndOfSpeech() {// 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
    22. L.i("onEndOfSpeech");
    23. }
    24. @Override
    25. public void onResult(RecognizerResult results, boolean isLast) {
    26. L.i("onResult:" + results.getResultString() + "。格式化内容:" + getFormatResult(results) + "。isLast:" + isLast);
    27. sb.append(getFormatResult(results));
    28. if (isLast) {
    29. L.i("完整结果为:" + sb.toString());
    30. listener.onResult(sb.toString());
    31. }
    32. }
    33. @Override
    34. public void onVolumeChanged(int volume, byte[] data) {
    35. L.i("onVolumeChanged。当前正在说话,音量大小:" + volume + "。返回音频数据长度:" + data.length);
    36. }
    37. @Override
    38. public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
    39. // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
    40. // 若使用本地能力,会话id为null
    41. if (SpeechEvent.EVENT_SESSION_ID == eventType) {
    42. String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
    43. L.i("onEvent:" + eventType + " session_id =" + sid);
    44. }
    45. }
    46. };
    47. }
    48. public static SpeechRecognizer getSpeechRecognizerInstance(Context context) {
    49. //*****************************************************初始化监听器************************************************
    50. InitListener mInitListener = code -> {
    51. if (code != ErrorCode.SUCCESS) L.i("初始化失败,错误码:" + code);
    52. };
    53. SpeechRecognizer mIat = SpeechRecognizer.createRecognizer(context, mInitListener);
    54. if (null == mIat) {
    55. // 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
    56. L.i("创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化");
    57. Toast.makeText(context, "语音引擎初始化失败", Toast.LENGTH_SHORT).show();
    58. return null;
    59. }
    60. //******************************************************参数设置**************************************************
    61. // 清空参数
    62. mIat.setParameter(SpeechConstant.PARAMS, null);
    63. mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);// 设置听写引擎
    64. mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");// 设置返回结果格式
    65. mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");// 设置语言
    66. mIat.setParameter(SpeechConstant.ACCENT, "mandarin");// 设置语言区域,mandarin为普通话;
    67. // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
    68. mIat.setParameter(SpeechConstant.VAD_BOS, "4000");//4000
    69. // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
    70. mIat.setParameter(SpeechConstant.VAD_EOS, "4000");//1000
    71. // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
    72. mIat.setParameter(SpeechConstant.ASR_PTT, "1");
    73. // 设置音频【保存】路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
    74. mIat.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");// 注:AUDIO_FORMAT参数语记需要更新版本才能生效
    75. mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, RecordBean.XF_VOICE_FILE_PATH);
    76. // 设置音频来源为外部文件
    77. mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");
    78. // 也可以像以下这样直接设置音频文件路径识别(要求设置文件在sdcard上的全路径):
    79. //mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "-2");
    80. //mIat.setParameter(SpeechConstant.ASR_SOURCE_PATH, "sdcard/XXX/XXX.pcm");
    81. return mIat;
    82. }
    83. /**
    84. * 获取解析出的字符串内容
    85. */
    86. private static String getFormatResult(RecognizerResult results) {
    87. String text = parseIatResult(results.getResultString());
    88. String sn = null;
    89. // 读取json结果中的sn字段
    90. try {
    91. JSONObject resultJson = new JSONObject(results.getResultString());
    92. sn = resultJson.optString("sn");
    93. } catch (JSONException e) {
    94. e.printStackTrace();
    95. }
    96. // 用HashMap存储听写结果
    97. HashMap<String, String> mIatResults = new LinkedHashMap<>();
    98. mIatResults.put(sn, text);
    99. StringBuilder resultBuffer = new StringBuilder();
    100. for (String key : mIatResults.keySet()) {
    101. resultBuffer.append(mIatResults.get(key));
    102. }
    103. return resultBuffer.toString();
    104. }
    105. private static String parseIatResult(String json) {
    106. StringBuilder ret = new StringBuilder();
    107. try {
    108. JSONArray words = new JSONObject(new JSONTokener(json)).getJSONArray("ws");
    109. for (int i = 0; i < words.length(); i++) {
    110. // 转写结果词,默认使用第一个结果
    111. JSONArray items = words.getJSONObject(i).getJSONArray("cw");
    112. JSONObject obj = items.getJSONObject(0);
    113. ret.append(obj.getString("w"));
    114. }
    115. } catch (Exception e) {
    116. e.printStackTrace();
    117. }
    118. return ret.toString();
    119. }
    120. /**
    121. * 上传语音消息,然后发送语音消息
    122. */
    123. public static void uploadVoiceAndSendMsg(BaseActivity activity, RecordBean recordBean) {
    124. if (recordBean == null || recordBean.aacPath == null) return;
    125. final File file = new File(recordBean.aacPath);
    126. if (!file.exists()) {
    127. ToastHelper.showErrorToast("录音文件不存在");
    128. return;
    129. }
    130. if (AccountManager.getInstance().getServiceInfo() == null) {
    131. ToastHelper.showToastInThread("您尚未登录");
    132. return;
    133. }
    134. activity.showLoadingDialog();
    135. //**************************************************上传语音消息****************************************
    136. String keyQN = LoginConnection.getUploadKey(recordBean.aacPath);
    137. HBApplication.getInstance().getUploadManager()
    138. .put(recordBean.aacPath,
    139. keyQN,
    140. LoginConnection.getUploadToken(),
    141. (key, info, res) -> {
    142. L.i("上传语音骑牛key:" + key);
    143. //*************************************发送语音消息*****************************************
    144. //当上传七牛成功后发送一条socket消息,当收到响应时(会返回一个msgid)说明此socket消息发送成功了
    145. recordBean.qnKey = key;
    146. SendMsgUtils.sendNormalVoiceMsg(activity, recordBean);
    147. },
    148. new UploadOptions(null, null, false, (key, percent) -> {
    149. //if (activity.dialog != null) activity.dialog.update((int) percent * 100);
    150. }, null));
    151. }
    152. /**
    153. * 【读】SD卡也即/mnt/sdcard/目录下的文件
    154. */
    155. public static byte[] readSDFile(String fileName) {
    156. if (TextUtils.isEmpty(fileName)) return null;
    157. File file = new File(fileName);
    158. if (!file.exists()) return null;
    159. try {
    160. InputStream ins = new FileInputStream(file);
    161. byte[] data = new byte[ins.available()];
    162. ins.read(data);
    163. ins.close();
    164. return data;
    165. } catch (Exception e) {
    166. e.printStackTrace();
    167. }
    168. return null;
    169. }
    170. }

    日志

    发送语音
    1. I/RecordBean: 包青天bqt(RecordBean.java:39)#<init>【语音文件保存路径:/storage/emulated/0/voice/pcm_2017_07_04 17_05_23 100.pcm
    2. /storage/emulated/0/voice/aac_2017_07_04 17_05_23 100.aac
    3. I/ChatActivity$5: 包青天bqt(ChatActivity.java:908)#pressStop【讯飞SDK开始音频流识别】
    4. I/VoiceUtils$1: 包青天bqt(VoiceUtils.java:97)#onVolumeChangedonVolumeChanged。当前正在说话,音量大小:0。返回音频数据长度:33280
    5. I/VoiceUtils$1: 包青天bqt(VoiceUtils.java:81)#onEndOfSpeechonEndOfSpeech
    6. I/VoiceUtils$1: 包青天bqt(VoiceUtils.java:106)#onEventonEvent:20001 session_id =iatad118bff@gz02600cb6a6553cf300
    7. I/VoiceUtils$1: 包青天bqt(VoiceUtils.java:86)#onResultonResult:{"sn":1,"ls":false,"bg":0,"ed":0,"ws":[{"bg":0,"cw":[{"sc":0.00,"w":"你好"}]}]}。格式化内容:你好。isLastfalse
    8. I/VoiceUtils$1: 包青天bqt(VoiceUtils.java:106)#onEventonEvent:20001 session_id =iatad118bff@gz02600cb6a6553cf300
    9. I/VoiceUtils: 包青天bqt(VoiceUtils.java:222)#lambda$uploadVoiceAndSendMsg$1上传语音骑牛key_F-UBAN-YeQIB.aac
    10. I/SendMsgUtils: 包青天bqt(SendMsgUtils.java:87)#sendNormalVoiceMsg发送语音消息content={"duration":1,"path":"_F-UBAN-YeQIB.aac"}。clientid=1499159123100
    11. I/VoiceUtils$1: 包青天bqt(VoiceUtils.java:86)#onResultonResult:{"sn":2,"ls":true,"bg":0,"ed":0,"ws":[{"bg":0,"cw":[{"sc":0.00,"w":"。"}]}]}。格式化内容:。。isLasttrue
    12. I/VoiceUtils$1: 包青天bqt(VoiceUtils.java:89)#onResult完整结果为:你好。
    13. I/ChatActivity: 包青天bqt(ChatActivity.java:1703)#onEventMainThread发送语音响应msgid=13878 clientid=1499159123100
    14. I/SendMsgUtils: 包青天bqt(SendMsgUtils.java:113)#sendVoiceContentMsg发送语音文本消息content=你好。。msgid=13878
    15. I/SendMsgUtils: 包青天bqt(SendMsgUtils.java:115)#sendVoiceContentMsg【成功删除pcm临时文件】
    16. I/SendMsgUtils: 包青天bqt(SendMsgUtils.java:116)#sendVoiceContentMsg【成功删除aac临时文件】
    17. I/SendMsgUtils: 包青天bqt(SendMsgUtils.java:124)#sendVoiceContentMsg【成功移除recordBean1499159123100

    查询语音对应文字
    1. I/SendMsgUtils: 包青天bqt(SendMsgUtils.java:148)#qryVoiceContentMsg查询语音文本消息msgid=13879groupId=36
    2. I/ChatActivity: 包青天bqt(ChatActivity.java:1723)#onEventMainThread查询语音文本响应msgID13879 内容:需要。】
    2017-7-4
  • 相关阅读:
    NFS4.1规范研究:session
    散列冲突与作为特征值的散列
    使用Select的3个注意事项
    3个学习Socket编程的简单例子:TCP Server/Client, Select
    Gdb调试多进程程序
    Usage of pmake
    诡异的bug: tcsh陷入死循环
    【转】PowerDesigner 物理数据模型(PDM) 说明
    大批量文件处理的7条建议
    OLE DB、ODBC 和 Oracle 连接池 (ADO.NET)
  • 原文地址:https://www.cnblogs.com/baiqiantao/p/7117835.html
Copyright © 2011-2022 走看看