需要源码和相关资源请点赞关注收藏后评论区留下QQ~~~
一、在线语音识别
云知声的语音识别同样采用WebSocket接口,待识别的音频流支持MP3和PCM两种格式,对于在线语音识别来说,云知声使用JSON串封装报文,待识别的音频以二进制形式发给服务器,可分为以下几个步骤
云知声平台的创建及使用可以参考以下这篇博客
1:定义WebSocket客户端的语音识别功能
在请求报文中填写朗读领域 音频格式 采样率等识别参数 再把JSON串传给WebSocket服务器
把字节数字格式的原始音频通过sendBinary方法分批发给服务器
等到所有音频数据发送完毕 再向服务器发一个结束识别的报文 也就是type字段为end的JSON串
在识别过程中 服务器还会数次返回JSON格式的应答报文 只有报文中的end字段为true时才表示识别结束
2:定义PCM音频的实时录制线程
在线识别的音频源既可能是实时录制的音频文件,也可能是PCM音频,在实时录音的情况下,还需自定义专门的录音线程,每录制一段PCM数据就发给WebSocket服务器
3:创建并启动语音识别任务
回到测试页面的获得代码,先创建 WebSocket客户端的语音识别任务,再通过WebSocket客户端启动语音识别任务 串联之后的在线识别语音
点击开始实时识别按钮后开始说话,然后可以观察到语音识别结果
也可以点击右上角的识别样本音频,这时候会自动播放一段古诗 然后再点击识别
代码如下
Java类
-
package com.example.voice;
-
-
import android.media.AudioFormat;
-
import android.os.Bundle;
-
import android.os.Environment;
-
import androidx.appcompat.app.AppCompatActivity;
-
-
import android.text.TextUtils;
-
import android.util.Log;
-
import android.widget.Button;
-
import android.widget.TextView;
-
import android.widget.Toast;
-
-
import com.example.voice.constant.SoundConstant;
-
import com.example.voice.task.AsrClientEndpoint;
-
import com.example.voice.task.VoicePlayTask;
-
import com.example.voice.task.VoiceRecognizeTask;
-
import com.example.voice.util.AssetsUtil;
-
import com.example.voice.util.SoundUtil;
-
-
public
class
VoiceRecognizeActivity
extends
AppCompatActivity {
-
private
final
static
String
TAG
=
"VoiceRecognizeActivity";
-
private
String
SAMPLE_FILE
=
"sample/spring.pcm";
// 样本音频名称
-
private TextView tv_recognize_text;
// 声明一个文本视图对象
-
private Button btn_recognize;
// 声明一个按钮对象
-
private String mSamplePath;
// 样本音频的文件路径
-
private
boolean
isRecognizing
=
false;
// 是否正在识别
-
private VoiceRecognizeTask mRecognizeTask;
// 声明一个原始音频识别线程对象
-
-
public
void
onCreate
(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_voice_recognize);
-
findViewById(R.id.iv_back).setOnClickListener(v -> finish());
-
TextView
tv_title
= findViewById(R.id.tv_title);
-
tv_title.setText(
"在线语音识别");
-
TextView
tv_option
= findViewById(R.id.tv_option);
-
tv_option.setText(
"识别样本音频");
-
tv_recognize_text = findViewById(R.id.tv_recognize_text);
-
btn_recognize = findViewById(R.id.btn_recognize);
-
btn_recognize.setOnClickListener(v -> {
-
if (!isRecognizing) {
// 未在识别
-
btn_recognize.setText(
"停止实时识别");
-
new
Thread(() -> onlineRecognize(
"")).start();
// 启动在线识别语音的线程
-
}
else {
// 正在识别
-
btn_recognize.setText(
"开始实时识别");
-
new
Thread(() -> mRecognizeTask.cancel()).start();
// 启动取消识别语音的线程
-
}
-
isRecognizing = !isRecognizing;
-
});
-
tv_option.setOnClickListener(v -> {
-
new
Thread(() -> onlineRecognize(mSamplePath)).start();
// 启动在线识别语音的线程
-
});
-
mSamplePath = String.format(
"%s/%s",
-
getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(), SAMPLE_FILE);
-
// 把资产目录下的样本音频文件复制到存储卡
-
new
Thread(() -> AssetsUtil.Assets2Sd(
this, SAMPLE_FILE, mSamplePath)).start();
-
}
-
-
// 在线识别音频文件(文件路径为空的话,表示识别实时语音)
-
private
void
onlineRecognize
(String filePath) {
-
runOnUiThread(() -> {
-
tv_recognize_text.setText(
"");
-
Toast.makeText(
this,
"开始识别语音", Toast.LENGTH_SHORT).show();
-
});
-
// 创建语音识别任务,并指定语音监听器
-
AsrClientEndpoint
asrTask
=
new
AsrClientEndpoint(
this, filePath, arg -> {
-
Log.d(TAG,
"arg[0]="+arg[
0]+
",arg[2]="+arg[
2]);
-
tv_recognize_text.setText(arg[
2].toString());
-
if (Boolean.TRUE.equals(arg[
0])) {
-
Toast.makeText(
this,
"语音识别结束", Toast.LENGTH_SHORT).show();
-
}
-
});
-
SoundUtil.startSoundTask(SoundConstant.URL_ASR, asrTask);
// 启动语音识别任务
-
if (TextUtils.isEmpty(filePath)) {
// 文件路径为空,表示识别实时语音
-
// 创建一个原始音频识别线程
-
mRecognizeTask =
new
VoiceRecognizeTask(
this, asrTask);
-
mRecognizeTask.start();
// 启动原始音频识别线程
-
}
else {
// 文件路径非空,表示识别音频文件
-
int[] params =
new
int[] {
16000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT};
-
// 创建一个原始音频播放线程
-
VoicePlayTask
playTask
=
new
VoicePlayTask(
this, filePath, params);
-
playTask.start();
// 启动原始音频播放线程
-
}
-
}
-
-
@Override
-
protected
void
onPause
() {
-
super.onPause();
-
if (mRecognizeTask !=
null) {
-
new
Thread(() -> mRecognizeTask.cancel()).start();
// 启动取消识别语音的线程
-
}
-
}
-
-
}
任务类
-
package com.example.voice.task;
-
-
import android.app.Activity;
-
import android.media.AudioFormat;
-
import android.media.AudioRecord;
-
import android.media.MediaRecorder;
-
-
public
class
VoiceRecognizeTask
extends
Thread {
-
private
final
static
String
TAG
=
"VoiceRecognizeTask";
-
private Activity mAct;
// 声明一个活动实例
-
private
int
mFrequence
=
16000;
// 音频的采样频率,单位赫兹
-
private
int
mChannel
= AudioFormat.CHANNEL_IN_MONO;
// 音频的声道类型
-
private
int
mFormat
= AudioFormat.ENCODING_PCM_16BIT;
// 音频的编码格式
-
private
boolean
isCancel
=
false;
// 是否取消录音
-
private AsrClientEndpoint mAsrTask;
// 语音识别任务
-
-
public
VoiceRecognizeTask
(Activity act, AsrClientEndpoint asrTask) {
-
mAct = act;
-
mAsrTask = asrTask;
-
}
-
-
@Override
-
public
void
run
() {
-
// 根据定义好的几个配置,来获取合适的缓冲大小
-
int
bufferSize
= AudioRecord.getMinBufferSize(mFrequence, mChannel, mFormat);
-
bufferSize = Math.max(bufferSize,
9600);
-
byte[] buffer =
new
byte[bufferSize];
// 创建缓冲区
-
// 根据音频配置和缓冲区构建原始音频录制实例
-
AudioRecord
record
=
new
AudioRecord(MediaRecorder.AudioSource.MIC,
-
mFrequence, mChannel, mFormat, bufferSize);
-
// 设置需要通知的时间周期为1秒
-
record.setPositionNotificationPeriod(
1000);
-
record.startRecording();
// 开始录制原始音频
-
int i=
0;
-
// 没有取消录制,则持续读取缓冲区
-
while (!isCancel) {
-
int
bufferReadResult
= record.read(buffer,
0, buffer.length);
-
mAsrTask.sendRealtimeAudio(i++, buffer, bufferReadResult);
-
}
-
record.stop();
// 停止原始音频录制
-
}
-
-
// 取消实时录音
-
public
void
cancel
() {
-
isCancel =
true;
-
mAsrTask.stopAsr();
// 停止语音识别
-
}
-
-
}
客户端类
-
package com.example.voice.task;
-
-
import android.app.Activity;
-
import android.text.TextUtils;
-
import android.util.Log;
-
-
import org.json.JSONObject;
-
-
import javax.websocket.*;
-
-
import java.io.FileInputStream;
-
import java.io.InputStream;
-
import java.nio.ByteBuffer;
-
-
@ClientEndpoint
-
public
class
AsrClientEndpoint {
-
private
final
static
String
TAG
=
"AsrClientEndpoint";
-
private Activity mAct;
// 声明一个活动实例
-
private String mFileName;
// 语音文件名称
-
private VoiceListener mListener;
// 语音监听器
-
private Session mSession;
// 连接会话
-
-
public
AsrClientEndpoint
(Activity act, String fileName, VoiceListener listener) {
-
mAct = act;
-
mFileName = fileName;
-
mListener = listener;
-
}
-
-
@OnOpen
-
public
void
onOpen
(final Session session) {
-
mSession = session;
-
Log.d(TAG,
"->创建连接成功");
-
try {
-
// 组装请求开始的json报文
-
JSONObject
frame
=
new
JSONObject();
-
frame.put(
"type",
"start");
-
JSONObject
data
=
new
JSONObject();
-
frame.put(
"data", data);
-
data.put(
"domain",
"general");
// 领域。general(通用),law(司法),technology(科技),medical(医疗)
-
data.put(
"lang",
"cn");
// 语言。cn(中文普通话)、en(英语)
-
data.put(
"format",
"pcm");
// 音频格式。支持mp3和pcm
-
data.put(
"sample",
"16k");
// 采样率。16k,8k
-
data.put(
"variable",
"true");
// 是否可变结果
-
data.put(
"punctuation",
"true");
// 是否开启标点
-
data.put(
"post_proc",
"true");
// 是否开启数字转换
-
data.put(
"acoustic_setting",
"near");
// 音响设置。near近讲,far远讲
-
data.put(
"server_vad",
"false");
// 智能断句
-
data.put(
"max_start_silence",
"1000");
// 智能断句前静音
-
data.put(
"max_end_silence",
"500");
// 智能断句尾静音
-
// 发送开始请求
-
session.getBasicRemote().sendText(frame.toString());
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
// 文件名非空,表示从音频文件中识别文本
-
if (!TextUtils.isEmpty(mFileName)) {
-
new
Thread(() -> sendAudioData(session)).start();
-
}
-
}
-
-
// 发送音频文件的语音数据
-
private
void
sendAudioData
(final Session session) {
-
try (
InputStream
is
=
new
FileInputStream(mFileName)) {
-
byte[] audioData =
new
byte[
9600];
-
int
length
=
0;
-
while ((length = is.read(audioData)) != -
1) {
-
Log.d(TAG,
"发送语音数据 length="+length);
-
ByteBuffer
buffer
= ByteBuffer.wrap(audioData,
0, length);
-
session.getAsyncRemote().sendBinary(buffer);
-
Thread.sleep(
200);
// 模拟采集音频休眠
-
}
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
stopAsr();
// 停止语音识别
-
}
-
-
// 发送实时语音数据
-
public
synchronized
void
sendRealtimeAudio
(int seq, byte[] data, int length) {
-
if (mSession!=
null && mSession.isOpen()) {
-
Log.d(TAG,
"发送语音数据 seq="+seq+
",length="+length);
-
ByteBuffer
buffer
= ByteBuffer.wrap(data,
0, length);
-
mSession.getAsyncRemote().sendBinary(buffer);
-
}
-
}
-
-
// 停止语音识别
-
public
void
stopAsr
() {
-
try {
-
// 组装请求结束的json报文
-
JSONObject
frame
=
new
JSONObject();
-
frame.put(
"type",
"end");
-
if (mSession!=
null && mSession.isOpen()) {
-
// 发送结束请求
-
mSession.getBasicRemote().sendText(frame.toString());
-
}
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
-
@OnMessage
-
public
void
processMessage
(Session session, String message) {
-
Log.d(TAG,
"服务端返回:" + message);
-
try {
-
JSONObject
jsonObject
=
new
JSONObject(message);
-
boolean
end
= jsonObject.getBoolean(
"end");
// 是否结束识别
-
int
code
= jsonObject.getInt(
"code");
// 处理结果
-
String
msg
= jsonObject.getString(
"msg");
// 结果说明
-
if (code !=
0) {
-
Log.d(TAG,
"错误码:" + code +
",错误描述:" + msg);
-
return;
-
}
-
String
text
= jsonObject.getString(
"text");
-
mAct.runOnUiThread(() -> mListener.voiceDealEnd(end, msg, text));
-
if (end) {
-
Log.d(TAG, mFileName +
"识别结束");
-
session.close();
// 关闭连接会话
-
}
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
-
@OnError
-
public
void
processError
(Throwable t) {
-
t.printStackTrace();
-
}
-
}
创作不易 觉得有帮助请点赞关注收藏~~~
转载:https://blog.csdn.net/jiebaoshayebuhui/article/details/128065315
查看评论