因为小项目是基于:java学生管理系统(百度人脸识别 + Swing + mysql + 邮件发送 )所以小伙伴们可移步阅读
因为会实时收录环境声音,所以建议在比较安静的环境进行测试
package Speech_sound;
import javax.sound.sampled.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
public class EngineeCore {
String filePath = "E:\\voice\\coop.wav"; //换上你自己的文件路径
AudioFormat audioFormat;
TargetDataLine targetDataLine;
boolean flag = true;
public static void main(String args[]) {
EngineeCore engineeCore = new EngineeCore();
engineeCore.startRecognize();
}
private void stopRecognize() {
flag = false;
targetDataLine.stop();
targetDataLine.close();
}
private AudioFormat getAudioFormat() {
float sampleRate = 16000;
// 8000,11025,16000,22050,44100
int sampleSizeInBits = 16;
// 8,16
int channels = 1;
// 1,2
boolean signed = true;
// true,false
boolean bigEndian = false;
// true,false
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}// end getAudioFormat
private void startRecognize() {
try {
// 获得指定的音频格式
audioFormat = getAudioFormat();
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
flag = true;
new CaptureThread().start();
} catch (Exception e) {
e.printStackTrace();
}
}
class CaptureThread extends Thread {
public void run() {
AudioFileFormat.Type fileType = null;
File audioFile = new File(filePath);
fileType = AudioFileFormat.Type.WAVE;
//声音录入的权值
int weight = 2;
//判断是否停止的计数
int downSum = 0;
ByteArrayInputStream bais = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
AudioInputStream ais = null;
try {
targetDataLine.open(audioFormat);
targetDataLine.start();
byte[] fragment = new byte[1024];
ais = new AudioInputStream(targetDataLine);
while (flag) {
targetDataLine.read(fragment, 0, fragment.length);
//当数组末位大于weight时开始存储字节(有声音传入),一旦开始不再需要判断末位
if (Math.abs(fragment[fragment.length - 1]) > weight || baos.size() > 0) {
baos.write(fragment);
System.out.println("守卫:" + fragment[0] + ",末尾:" + fragment[fragment.length - 1] + ",lenght" + fragment.length);
//判断语音是否停止
if (Math.abs(fragment[fragment.length - 1]) <= weight) {
downSum++;
} else {
System.out.println("重置奇数");
downSum = 0;
}
//计数超过20说明此段时间没有声音传入(值也可更改)
if (downSum > 20) {
System.out.println("停止录入");
break;
}
}
}
//取得录音输入流
audioFormat = getAudioFormat();
byte audioData[] = baos.toByteArray();
bais = new ByteArrayInputStream(audioData);
ais = new AudioInputStream(bais, audioFormat, audioData.length / audioFormat.getFrameSize());
//定义最终保存的文件名
System.out.println("开始生成语音文件");
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, audioFile);
downSum = 0;
stopRecognize();
} catch (Exception e) {
e.printStackTrace();
}
finally {
//关闭流
try {
ais.close();
bais.close();
baos.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
至于在代码中是否需要开启新的线程由小伙伴们自己定夺
实现语音播报
package Speech_sound;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class jacobtest {
// public static void main(String[] args) {
// jacobtest jacobtest = new jacobtest();
// jacobtest.textToSpeech("欢迎使用Tiko语音助手,请问有什么可以帮您的");
// }
public static void textToSpeech(String text) {
ActiveXComponent ax = null;
try {
ax = new ActiveXComponent("Sapi.SpVoice");
// 运行时输出语音内容
Dispatch spVoice = ax.getObject();
// 音量 0-100
ax.setProperty("Volume", new Variant(100));
// 语音朗读速度 -10 到 +10
ax.setProperty("Rate", new Variant(1));
// 执行朗读
Dispatch.call(spVoice, "Speak", new Variant(text));
// 下面是构建文件流把生成语音文件
ax = new ActiveXComponent("Sapi.SpFileStream");
Dispatch spFileStream = ax.getObject();
ax = new ActiveXComponent("Sapi.SpAudioFormat");
Dispatch spAudioFormat = ax.getObject();
// 设置音频流格式
Dispatch.put(spAudioFormat, "Type", new Variant(22));
// 设置文件输出流格式
Dispatch.putRef(spFileStream, "Format", spAudioFormat);
// 调用输出 文件流打开方法,创建一个.wav文件
Dispatch.call(spFileStream, "Open", new Variant("./text.wav"), new Variant(3), new Variant(true));
// 设置声音对象的音频输出流为输出文件对象
Dispatch.putRef(spVoice, "AudioOutputStream", spFileStream);
// 设置音量 0到100
Dispatch.put(spVoice, "Volume", new Variant(100));
// 设置朗读速度
Dispatch.put(spVoice, "Rate", new Variant(-2));
// 开始朗读
Dispatch.call(spVoice, "Speak", new Variant(text));
// 关闭输出文件
Dispatch.call(spFileStream, "Close");
Dispatch.putRef(spVoice, "AudioOutputStream", null);
spAudioFormat.safeRelease();
spFileStream.safeRelease();
spVoice.safeRelease();
ax.safeRelease();
} catch (Exception e) {
e.printStackTrace();
}
}
}
这里要注意的是要在jdk bin文件中需要导入jacob-1.17-M2-x64.dll
–> 此链接
其次还需要添加一个依赖
<!-- 文字转语音 -->
<dependency>
<groupId>com.hynnet</groupId>
<artifactId>jacob</artifactId>
<version>1.18</version>
</dependency>
这里的操作和我之前的博客中写的人脸识别基本一致,小伙伴们可移步 -->
–>java学生管理系统(百度人脸识别 + Swing + mysql + 邮件发送 )
最后获取到 “AppID” “API Key” “Secret Key”
文档奉上先:JavaSDK技术文档
不想看?没问题!小编为你一一道来
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>${version}</version>
</dependency>
若是直接使用jar包
则去如下网址(官网jar包获取)中的此处
package Speech_sound;
import com.baidu.aip.speech.AipSpeech;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.json.JSONException;
import org.json.JSONObject;
import java.sql.SQLException;
public class Sample {
//“...”这里面分别填写“百度AI账号注册”那一步中的三个值(一一对应)
public static final String APP_ID = "...";
public static final String API_KEY = "...";
public static final String SECRET_KEY = "...";
// 初始化一个AipSpeech
private static AipSpeech client = new AipSpeech(APP_ID, API_KEY, SECRET_KEY);
public static void main(String[] args) throws JSONException, InterruptedException, SQLException {
// 可选:设置网络连接参数
client.setConnectionTimeoutInMillis(2000);
client.setSocketTimeoutInMillis(60000);
// 可选:设置代理服务器地址, http和socket二选一,或者均不设置
// client.setHttpProxy("proxy_host", proxy_port); // 设置http代理
// client.setSocketProxy("proxy_host", proxy_port); // 设置socket代理
// 可选:设置log4j日志输出格式,若不设置,则使用默认配置
// 也可以直接通过jvm启动参数设置此环境变量
System.setProperty("aip.log4j.conf", "path/to/your/log4j.properties");
//下面的音频文件路径写入你自己的即可
//支持的格式: pcm(不压缩)、wav(不压缩,pcm编码)、amr(压缩格式)
JSONObject res = client.asr("test.pcm", "pcm", 16000, null);
System.out.println(res.toString(2));
}
}
// 成功返回
{
"err_no": 0,
"err_msg": "success.",
"corpus_no": "15984125203285346378",
"sn": "481D633F-73BA-726F-49EF-8659ACCC2F3D",
"result": ["北京天气"]
}
添加依赖:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.3</version>
</dependency>
String content = res.toString(2);
//将json字符串转化成json对象
JsonParser jp = new JsonParser();
//获取message对应的值
JsonObject jo = jp.parse(content).getAsJsonObject();
//测试发现,实时录音结果可能为null,所以加上此判断
if(jo.get("result") == null)
new jacobtest().textToSpeech("对不起,没听清您说的话");
else
result = jo.get("result").getAsString();
System.out.println("result = "+result);
控制台返回参数:
因为考虑到后面对返回字符串的判断不需要标点,所以可以用以下方法解决:
//去除字符串中的标点
public static String format(String s){
String str=s.replaceAll("[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……& amp;*()——+|{}【】‘;:”“’。,、?|-]", "");
return str;
}
因为是本人的小项目中语音这一块文件,所以小伙伴们就做个大致参考,懂得原理实现即可,你肯定可以写出比更好的代码,Fighting!Together~
package Speech_sound;
import org.json.JSONException;
import pack2.AudioPlayer;
import pack2.Demo;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
public class Cycle_Speech {
private static Integer num = null;
private static Sample sample_2;
private static String str_1; //按专业查询时的专业名
private static Integer judge = 0; //判断是否为语音标识
public static Integer getJudge() {
return judge;
}
public static String getStr_1() {
return str_1;
}
public static void Cycle_Speech_body() throws JSONException, InterruptedException, SQLException {
//语音助手提示信息
jacobtest jaco = new jacobtest();
jaco.textToSpeech("欢迎使用Tiko语音助手,请问有什么可以帮您的");
Sample sample = new Sample();
sample.main(null);
num = new Sample().getIndex();
while(num == 1)
{
// if(sample.getResult() == null)
// {
// new jacobtest().textToSpeech("对不起,我没听清你说的话");
// continue;
// }
if(sample.getResult().contains("打开音乐")||sample.getResult().contains("音乐打开")||
sample.getResult().contains("音乐响起来")||sample.getResult().contains("燥起来")||
sample_2.getResult().contains("打开音乐")||sample_2.getResult().contains("音乐打开")||
sample_2.getResult().contains("音乐响起来")||sample_2.getResult().contains("燥起来"))
{
AudioPlayer audio = new AudioPlayer(new File("D:\\java2\\不将就.mp3"));
audio.start();
break;
}
else if(sample.getResult().contains("常规查询")||sample.getResult().contains("一般查询")||
sample.getResult().contains("信息查询")||sample.getResult().contains("查询信息")||
sample_2.getResult().contains("常规查询")||sample_2.getResult().contains("一般查询")||
sample_2.getResult().contains("信息查询")||sample_2.getResult().contains("查询信息"))
{
new Demo().Found_normal();
break;
}
else if(sample.getResult().contains("总分降序查询")||sample.getResult().contains("总分降序")||
sample.getResult().contains("总降序")||
sample_2.getResult().contains("总分降序查询")||sample_2.getResult().contains("总分降序")||
sample_2.getResult().contains("总降序"))
{
new Demo().total_down();
break;
}
else if(sample.getResult().contains("总分升序查询")||sample.getResult().contains("总分升序")||
sample.getResult().contains("总升序")||
sample_2.getResult().contains("总分升序查询")||sample_2.getResult().contains("总分升序")||
sample_2.getResult().contains("总升序"))
{
new Demo().total_up();
break;
}
else if(sample.getResult().contains("数学降序查询")||sample.getResult().contains("数学降序")||
sample.getResult().contains("数降序")||
sample_2.getResult().contains("数学降序查询")||sample_2.getResult().contains("数学降序")||
sample_2.getResult().contains("数降序"))
{
new Demo().math_down();
break;
}
else if(sample.getResult().contains("政治降序查询")||sample.getResult().contains("政治降序")||
sample.getResult().contains("政降序")||
sample_2.getResult().contains("政治降序查询")||sample_2.getResult().contains("政治降序")||
sample_2.getResult().contains("政降序"))
{
new Demo().poli_down();
break;
}
else if(sample.getResult().contains("英语降序查询")||sample.getResult().contains("英语降序")||
sample.getResult().contains("英降序")||
sample_2.getResult().contains("英语降序查询")||sample_2.getResult().contains("英语降序")||
sample_2.getResult().contains("英降序"))
{
new Demo().eng_down();
break;
}
else if(sample.getResult().contains("按专业查询")||sample_2.getResult().contains("按专业查询")||
sample.getResult().contains("专业查询")||sample_2.getResult().contains("专业查询"))
{
jacobtest jacobtest = new jacobtest();
jaco.textToSpeech("请问您要查询的专业名称是什么");
Sample sample_1 = new Sample();
sample_1.main(null);
//去除字符串中的标点
str_1 = format(sample_1.getResult());
//设置语音判断标识
judge = 1;
new Demo().found_major_content();
//还原判断值
judge = 0;
break;
}
else if(sample.getResult().contains("bbox")||sample.getResult().contains("bboss")||
sample_2.getResult().contains("bbox")||sample_2.getResult().contains("bboss"))
{
jacobtest jacobtest = new jacobtest();
jaco.textToSpeech("哎呀!我不会,不过没关系,嘿Siri,来一段beatbox");
break;
}
else if(sample.getResult().contains("背景一")||sample.getResult().contains("背景1")
||sample.getResult().contains("NBA背景")||sample.getResult().contains("nba背景")||
sample_2.getResult().contains("背景一")||sample_2.getResult().contains("背景1")
||sample_2.getResult().contains("NBA背景")||sample_2.getResult().contains("nba背景"))
{
new Demo().background_1();
break;
}
else if(sample.getResult().contains("背景二")||sample.getResult().contains("背景2")||
sample_2.getResult().contains("背景二")||sample_2.getResult().contains("背景2"))
{
new Demo().background_2();
break;
}
else if(sample.getResult().contains("背景三")||sample.getResult().contains("背景3")||
sample_2.getResult().contains("背景三")||sample_2.getResult().contains("背景3"))
{
new Demo().background_3();
break;
}
else if(sample.getResult().contains("背景四")||sample.getResult().contains("背景4")||
sample_2.getResult().contains("背景四")||sample_2.getResult().contains("背景4"))
{
new Demo().background_4();
break;
}
else if(sample.getResult().contains("滚")||sample.getResult().contains("拜拜")||
sample.getResult().contains("再见")||sample.getResult().contains("爬开")||
sample_2.getResult().contains("滚")||sample_2.getResult().contains("拜拜")||
sample_2.getResult().contains("再见")||sample_2.getResult().contains("爬开"))
{
new jacobtest().textToSpeech("好的");
break;
}
else if(sample.getResult().contains("放个屁")||sample_2.getResult().contains("放个屁"))
{
new jacobtest().textToSpeech("噗噗噗噗,噗噗噗");
break;
}
else if(sample.getResult().contains("打开QQ")||sample.getResult().contains("QQ")||
sample_2.getResult().contains("打开QQ")||sample_2.getResult().contains("QQ"))
{
try {
Process p = java.lang.Runtime.getRuntime().exec("C:\\Program Files\\tencent\\QQ\\Bin\\QQ.exe");
System.err.println("p===="+p.getInputStream());
} catch (IOException ex1)
{
ex1.printStackTrace();
}
break;
}
else if(sample.getResult().contains("打开优酷")||sample.getResult().contains("优酷")||
sample_2.getResult().contains("打开优酷")||sample_2.getResult().contains("优酷"))
{
try {
Process p = java.lang.Runtime.getRuntime().exec("D:\\Program Files (x86)\\YouKu\\YoukuClient\\proxy\\YoukuDesktop.exe");
System.err.println("p===="+p.getInputStream());
} catch (IOException ex1)
{
ex1.printStackTrace();
}
break;
}
else
{
new jacobtest().textToSpeech("我好像没有听懂您的意思,能再说一次吗?");
sample_2 = new Sample();
sample_2.main(null);
continue;
}
}
}
//去除字符串中的标点
public static String format(String s){
String str=s.replaceAll("[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……& amp;*()——+|{}【】‘;:”“’。,、?|-]", "");
return str;
}
}
视频链接:语音助手演示
这样一顿处理后,可以实现基本的语音助手功能,除开“唤醒操作”
如果对这方面有兴趣的小伙伴,可以参考–>实时语音识别技术文档
感谢博客:
java 获取json字符串中key对应的值
java实现麦克风自动录音
百度语音识别技术文档