java+百度语音识别(语音助手)

文章目录

  • 项目实施图
  • java实时录音
  • java文字转语音
  • 百度AI账号注册
  • 百度AI接口调用
  • 项目中应用
  • 具体实现效果
  • 程序缺点

因为小项目是基于:java学生管理系统(百度人脸识别 + Swing + mysql + 邮件发送 )所以小伙伴们可移步阅读

项目实施图

java+百度语音识别(语音助手)_第1张图片

java实时录音

因为会实时收录环境声音,所以建议在比较安静的环境进行测试

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();
                }
            }

        }
    }
}

至于在代码中是否需要开启新的线程由小伙伴们自己定夺

java文字转语音

实现语音播报

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>

百度AI账号注册

这里的操作和我之前的博客中写的人脸识别基本一致,小伙伴们可移步 -->
–>java学生管理系统(百度人脸识别 + Swing + mysql + 邮件发送 )

最后获取到 “AppID” “API Key” “Secret Key”
java+百度语音识别(语音助手)_第2张图片

百度AI接口调用

文档奉上先:JavaSDK技术文档

不想看?没问题!小编为你一一道来

  1. 首先要添加一个依赖
<dependency>
    <groupId>com.baidu.aip</groupId>
    <artifactId>java-sdk</artifactId>
    <version>${version}</version>
</dependency>
	若是直接使用jar包		

则去如下网址(官网jar包获取)中的此处

java+百度语音识别(语音助手)_第3张图片

  1. 然后是下面这个类
    注意看注释
    注意看注释
    注意看注释
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));

    }

}
  1. 成功返回后在控制台是这样的结果
// 成功返回
{
	"err_no": 0,
	"err_msg": "success.",
	"corpus_no": "15984125203285346378",
	"sn": "481D633F-73BA-726F-49EF-8659ACCC2F3D",
	"result": ["北京天气"]
}
  1. 单个参数的获取

添加依赖:

		<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实现麦克风自动录音
百度语音识别技术文档

你可能感兴趣的:(java,语音识别,gson)