2019-07-16 10:01:34 ffpiaoyilian233 阅读数 635
  • Android 实战开发 三方SDK 讯飞语音SDK

    Android 第三方SDK开发视频教程,给课程结合讯飞语音这个第三方SDK进行实战教学,实现在线语音合成,将文字信息转化为声音信息,给应用配上“嘴巴;语音听写,将连续语音识别为文字,给应用配上“耳朵”。

    4837 人正在学习 去看看 Frank Lee

使用Java编写一个与图灵机器人进行对话的工具。

但图灵机器人只支持文本对话,并不支持语音交互,所以本程序运用了第三方库百度语音识别/合成,来实现语音交互。

我们还可以将下载好的音乐放入指定文件夹,进行简单的配置后还能点歌。

1.登录图灵机器人官网:http://www.turingapi.com/,完成注册、身份认证、创建机器人。一般一到两天后就能身份审核成功,创建好机器人之后就会生成自己的apikey:

2.登录百度智能云官网:http://ai.baidu.com/,右上角“控制台”进入登录界面。登录后点击“语音技术”、“创建应用”,应用创建好后就是呢过程自己的AppID,API Key,Secret Key:

3.完成以上准备工作就可以开始编码了。我们可以参考相关文档,以及下载SDK。不同语言有不同的SDK,根据自己所需来下载。我这里使用的Java语言编写,所以下载的是“识别、合成 RESTful API JAVA SDK”。

4.以下就是相关代码:

Record类完成录音、播放音频文件:

package com.feng.robot;

import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;

import java.io.*;
import java.util.Scanner;
import javax.sound.sampled.*;

/**
 * 录音record(),录音完毕后将音频文件保存到指定文件夹中
 * 播放音频文件play(音频文件路径)
 */
public class Record {
    private static AudioFormat audioFormat;
    static TargetDataLine targetDataLine;

    public File record() {
        System.out.println("想聊天,请按y。结束讲话,请按n。");
        Scanner input = new Scanner(System.in);
        String Sinput = input.next();
        if(Sinput.equals("y")){
            System.out.println("讲话中……");
            captureAudio();//调用录音方法
        }
        Scanner input_2 = new Scanner(System.in);
        String Sinput_2 = input_2.next();
        if(Sinput_2.equals("n")){
            targetDataLine.stop();
            targetDataLine.close();
            System.out.println("结束讲话。");
        }
        //结束录音后便在指定路径生成一个record.wav文件
        File audioFile = new File("F:\\record.wav");
        return audioFile;
    }

    //录音方法
    public void captureAudio(){
        try {
            audioFormat = new AudioFormat(16000,16,1,true,false);
            DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
            targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);

            new CaptureThread().start();//开启线程
        } catch (Exception e){
            e.printStackTrace();
            System.exit(0);
        }
    }

    class CaptureThread extends Thread {
        public void run() {
            AudioFileFormat.Type fileType = null;
            //指定的文件类型
            File audioFile = null;
            //设置文件类型和文件扩展名
            //根据选择的单选按钮。
            fileType = AudioFileFormat.Type.WAVE;
            audioFile = new File("F://record.wav");
            try {
                targetDataLine.open(audioFormat);
                targetDataLine.start();
                //当开始音频捕获或回放时,生成 START 事件。
                AudioSystem.write(new AudioInputStream(targetDataLine),fileType, audioFile);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

     //播放音频文件
     public void play(String filePathName){
        File file = new File(filePathName);
         try {
             FileInputStream fis = new FileInputStream(file);
             BufferedInputStream bis = new BufferedInputStream(fis);
             Player player = new Player(bis);
             player.play();
         } catch (FileNotFoundException e) {
             e.printStackTrace();
         } catch (JavaLayerException e) {
             e.printStackTrace();
         }
     }
}

SpeechRec类完成百度语音识别/合成:

package com.feng.robot;

import com.baidu.aip.speech.AipSpeech;
import com.baidu.aip.speech.TtsResponse;
import org.json.JSONObject;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
/**
 * 百度语音识别ASR() & 合成TTS()
 */
public class SpeechRec {
    private static final String serverURL = "http://vop.baidu.com/server_api";
    private static String token = "";

    private static final String apiKey = "自己的API Key";
    private static final String secretKey = "自己的Secret Key";
    private static final String cuid = "自己的App ID";

    public static void main(String[] args) throws Exception {
        Record record = new Record();
        SpeechRec s = new SpeechRec();

        record.record();
        s.getToken();
        String str = s.ASR(new File("F:\\record.wav"));
        System.out.println(str);

    }

    //语音识别:音频-->文本,并返回解析后的文本
    public String ASR(File recordFile) throws Exception {
        HttpURLConnection conn = (HttpURLConnection) new URL(serverURL
                + "?cuid=" + cuid + "&token=" + token).openConnection();

        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "audio/wav; rate=16000");
        conn.setDoInput(true);
        conn.setDoOutput(true);

        // 发送请求
        DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
        wr.write(loadFile(recordFile));
        wr.flush();
        wr.close();

        String recordText = parseJson(printResponse(conn));//解析后的识别文本
        return recordText;
    }

    public void getToken() throws Exception {
        String getTokenURL = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials" +
                "&client_id=" + apiKey + "&client_secret=" + secretKey;
        HttpURLConnection conn = (HttpURLConnection) new URL(getTokenURL).openConnection();
        token = new JSONObject(printResponse(conn)).getString("access_token");
    }

    public String printResponse(HttpURLConnection conn) throws Exception {
        if (conn.getResponseCode() != 200) {
            System.out.println("conn.getResponseCode() = " + conn.getResponseCode());
            return "";
        }
        InputStream is = conn.getInputStream();
        BufferedReader rd = new BufferedReader(new InputStreamReader(is));
        String line;
        StringBuffer response = new StringBuffer();
        while ((line = rd.readLine()) != null) {
            response.append(line);
            response.append('\r');
        }
        rd.close();
        return response.toString();
    }

    private byte[] loadFile(File file) throws IOException {
        InputStream is = new FileInputStream(file);

        long length = file.length();
        byte[] bytes = new byte[(int) length];

        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length
                && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
            offset += numRead;
        }

        if (offset < bytes.length) {
            is.close();
            throw new IOException("Could not completely read file " + file.getName());
        }
        is.close();
        return bytes;
    }


    //解析后,得到百度语音识别后的文本
    public String parseJson(String response){
        if(response == null){
            return "";
        }
        net.sf.json.JSONObject ASRResult = net.sf.json.JSONObject.fromObject(response);

        String resultText = "";
        if(ASRResult.get("result") == null){
            resultText = "[\"\"]";
        }else{
            resultText = ASRResult.get("result").toString();
        }

        //resultText = ASRResult.get("result").toString();
        resultText = resultText.substring(2,resultText.length()-2);

        return resultText;
    }

    //语音合成,文本-->音频,返回得到的音频文件
    public File TTS(String text){
        AipSpeech aipSpeech = new AipSpeech(cuid,apiKey,secretKey);
        HashMap options = new HashMap();
        options.put("spd","5");
        options.put("pit","5");
        options.put("per","4");

        TtsResponse ttsResponse = aipSpeech.synthesis(text,"zh",1,options);
        byte[] aa = ttsResponse.getData();
        getFile(aa,"F:\\play.wav");

        File file = new File("F:\\play.wav");

        return file;
    }

    //合成的二进制数据放入文件中
    private void getFile(byte[] binData, String filePathName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = new File(filePathName);
        try {
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(binData);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{//关闭流
            if(bos != null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

TulingRobot类完成与图灵机器人进行对话的操作:

package com.feng.robot;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import net.sf.json.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * 图灵机器人
 */
public class TulingRobot {
    private static final String url = "http://www.tuling123.com/openapi/";
    private static final String api_key = "自己的apiKey";


    //获取响应,得到响应的json字符串
    public String getResult( String message ) {
        //图灵api接口
        String apiUrl = url+"api?key="+api_key+"&info=";
        try {
            //设置编码格式
            message = URLEncoder.encode(message, "utf-8");
            //拼接url
            apiUrl = apiUrl + message;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        //封装请求头
        HttpPost request = new HttpPost(apiUrl);
        String result = "";
        try {
            //发送http请求
            HttpResponse response = HttpClients.createDefault().execute(request);
            //获取响应码
            int code = response.getStatusLine().getStatusCode();

            if (code == 200) {
                //获取返回的结果
                result = EntityUtils.toString(response.getEntity());
            } else {
                System.out.println("code=" + code);
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result; //返回结果{"code":xxx,"text":xxx}
    }

    //解析Json字符串
    public String parseJson(String jsonStirng){
        if(jsonStirng == null){
            return "";
        }
        //json字符串 --> json对象
        JSONObject results = JSONObject.fromObject(jsonStirng);

        String result = results.getString("text");
        return result;
    }
}

RobotYuanYuan类中包含了要运行的主方法,也可以在主方法添加音乐,进行点歌:

package com.feng.robot;

import java.io.File;

/**
 * 机器人圆圆
 */

public class YuanYuan {
    private static File recordFile = new File("F:\\record.wav");
    private static String playFileName = "F:\\play.wav";

    public static void main(String[] args){
        /**
         * 录音-->百度语音识别,获取到文本-->文本传入到图灵机器人与之对话-->拿到图灵机器人的回话
         * -->百度语音合成,将回话转为音频文件-->播放音频文件
         * 以上完成一次完整的对话
         * 若我说:退出-->百度语音识别为“退出”-->百度语音合成文本“好的,那下次再见了”-->播放音频文件-->退出程序
         * 若我说的是歌名-->播放音乐(前提是音乐已经下载好了)
         */

        Record record = new Record();
        SpeechRec speechRec = new SpeechRec();
        TulingRobot tulingRobot = new TulingRobot();

        while(true){
            record.record();//录音
            try {
                speechRec.getToken();
                String recordText = speechRec.ASR(recordFile);//百度语音识别
                if(recordText.equals("退出。")){
                    speechRec.TTS("好的,那下次再见了");
                    System.out.println("(我):退出");
                    System.out.println("(圆圆):"+"好的,那下次再见了");
                    record.play(playFileName);//播放合成的音频文件
                    System.exit(0);//退出程序
                }
                if(recordText.equals("")){
                    speechRec.TTS("你啥也不说,我如何作答呀");
                    System.out.println("(我):"+recordText);
                    System.out.println("(圆圆):"+"你啥也不说,我如何作答呀");
                    record.play(playFileName);//播放合成的音频文件
                    continue;
                }
                /**
                 *  播放音乐(可配置)
                 *  配置过程:在指定文件夹下添加下载好的音乐-->如果识别的是音乐名,播放音频文件即可
                 */
                if(recordText.equals("意外。")){
                    System.out.println("音乐播放中...");
                    record.play("F:\\music\\意外.mp3");
                    continue;
                }
                if(recordText.equals("告白之夜。")){
                    System.out.println("音乐播放中...");
                    record.play("F:\\music\\告白之夜.mp3");
                    continue;
                }
                if(recordText.equals("工资向北走。")){//百度语音识别总是将“公子”识别成“工资”,可能是我发音不对吧哈哈                   record.play("F:\\music\\公子向北走.mp3");
                    System.out.println("音乐播放中...");
                    record.play("F:\\music\\公子向北走.mp3");
                    continue;
                }//按以上格式添加配置即可

                String result = tulingRobot.parseJson(tulingRobot.getResult(recordText));//得到图灵机器人的回话
                speechRec.TTS(result);//百度语音合成
                System.out.println("(我):"+recordText);
                System.out.println("(圆圆):"+result);
                record.play(playFileName);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

我们简单的运行一下:

对机器人说歌名,就可以播放音乐了:

如果想退出聊天了,说“退出”:

程序还存在缺点:播放音乐时,必须整首歌播放完之后才能继续聊天,不能中途打断。

后期可以进行扩展:不想听歌了输入相关指令停止音乐播放。

也可以进行以下扩展:让机器人打开网站进行关键词搜索等命令。

2018-04-10 11:36:44 Manketon 阅读数 2615
  • Android 实战开发 三方SDK 讯飞语音SDK

    Android 第三方SDK开发视频教程,给课程结合讯飞语音这个第三方SDK进行实战教学,实现在线语音合成,将文字信息转化为声音信息,给应用配上“嘴巴;语音听写,将连续语音识别为文字,给应用配上“耳朵”。

    4837 人正在学习 去看看 Frank Lee

转自:https://blog.csdn.net/github_19776427/article/details/52530066

语音识别项目:

http://www.oschina.net/project/tag/203/tts-speech

 

sf.net

 

http://www.codesoso.net/Search?q=%D3%EF%D2%F4%CA%B6%B1%F0&l=c

http://search.codesoso.com/Search?q=%E8%AF%AD%E9%9F%B3%E8%AF%86%E5%88%AB

http://simon-listens.blogspot.com/2012/12/simon-040.html
http://cmusphinx.sourceforge.net/wiki/
http://member.voicecloud.cn/index.php/default/register
最后这个。。。应该不是 
 
 
這裏有許多 语音识别系统 其中部分是開源的
There are currently several speech recognition software packages for Linux, some of them being open-source and others proprietary.
http://en.wikipedia.org/wiki/Speech_rec ... n_in_Linux

http://www.pudn.com/downloads630/sourcecode/speech/detail2559966.html

 

Speech SDK 5.1 识别不太准确

 

Jasper:开源的语音控制系统

文/文:周骏挺    

两位来自普林斯顿大学的本科生Shubhro Saha(左)和Charles Marsh,利用业余时间开发了一个名叫Jasper的语音控制项目

“明天早上8 点叫醒我”,“帮我打电话给老妈”,“提醒我星期五下午公司要开会”……4 年前Siri发布时,业界普遍还对这个技术的成熟度以及实用性保持质疑的态度。但今天除了Siri之外,在手机上打开百度地图、大众点评或者微信,语音搜 索以及输入几乎已成主流标配。加之2012 年Google发布Google Now,以及今年不久前微软发布的用于Windows Phone 8.1 的语音助手Cortana,现在看来Siri更像掀起了又一场智能语音的技术革新。
从2013 年夏天开始,两位来自普林斯顿大学的本科生Charles Marsh和Shubhro Saha,利用业余时间开发了一个名叫Jasper的语音控制项目。
比 起为移动设备而生的Siri和Cortana,Jasper则是为居家或者工作室而生的定点智能语音系统。它运行在“树莓派”B型计算机 (Raspberry Pi Module B)上,这是一款由英国开发,只有信用卡大小的低价单板机计算机,一方面连接着麦克风与扬声器用于与用户互动,另一方面连接着网络。摒弃了关机或者开机的 传统概念,Jasper被设计成一个永远在线的系统,你能够随时通过语音呼唤“Jasper”唤醒它,然后听到“哔”地一声确认之后说出指令。在默认状态 下,Jasper支持查询时间、天气、新闻,还有新邮件、Facebook推送等社交信息,不知道是不是由于Siri和Cortana之前上演的“二人 转”大热的原因,Jasper也支持为用户讲笑话这样的恶俗功能。
J.A.R.V.I.S,是这个项目最初的名字。听起来有点熟悉?没错,这就是 钢铁侠电影中Tony Stark家里那个智能中央控制电脑,只要Tony一声令下,J.A.R.V.I.S几乎可以完成家中的所有事情,打开窗帘、灯光等电源,报告天气、交 通、新闻信息,甚至协助Tony进行战衣的研发和管理。Marsh和Saha将这个电影中的电脑管家带入了现实,后来主创人员觉得项目名字叫 J.A.R.V.I.S太没创意了,就将项目改名Jasper。
要比复杂性和智能程度,Jasper比不上聪慧搞笑的Siri或者 Cortana。严格意义上说,它最多只能算是一个语音控制系统,而并不是智能的。但开源性让Jasper充满了无限的可能性。Marsh和Saha完全 利用网络上公开的开源代码开发出Jasper,例如它的语音识别系统则是由卡耐基梅隆大学所开发的开源软件PocketSphinx所支持;同 时,Jasper还利用Phonetisaurus来优化语音的识别,这是一款能够适应用户的讲话速度与习惯的开源听写词库软件。
这一切都是开源 的,Jasper的存在让你意识到开源的美妙之处。一个定价35 美元的“树莓派”B型计算机、一张4 GB的SD卡、一条以太网线、一个USB充电器、一条micro USB线、一个USB麦克风以及一套有源扬声器,如果你想自己建一台Jasper,这就是你所需要的全部东西,全部加起来可能都不会超过500 元人民币。安装过程同样是直接简单,把所有该插入的东西都插入就可以了,Jasper的初始安装需用以太网线将“树莓派”与PC连接起来,安装完成了就可 以把Jasper的无线网络打开,让其成为一个完全独立运行的语音控制系统。在Jasper的官网上有一系列教程指引你如何安装软件,同时主创者还开发了 一系列“简单到死”(dead-simple)的API,让开发者或者用户根据自己的需要开发语音指令。

Jasper则是为居家或者工作室而生的定点智能语音系统。一方面连接着麦克风与扬声器用于和用户互动,另一方面连接着网络

你也许很难想象世界各地的人们会拿Jasper干什么。在《连线》的采访中,Jasper的开发者Charles Marsh提到了一些。有人用Jasper来控制自家整个房子的电源,有人则希望能利用这个语音系统来控制整个工厂所有的自动化运输设备,甚至还有人用 Jasper来教小朋友编程。这种语音控制应用的程度对Siri这种封闭的智能语音系统是难以企及的。Jasper令人想起2012 年底一度大热的那只“小鸡”SimSimi,本质上来说Simsimi只是一个自动回复的虚拟卡通形象,它甚至还没有语音功能。但用户能够“教”会 Simsimi如何回复相应的关键词,结果在全球无数网民的调教下,SimSimi被誉为“犯贱版Siri”。从这个角度看,发挥网民无穷的智慧,让其成 为UGC(用户产生内容)与众包作用的结果, Jasper的前途似乎光明无限。
但Marsh和Saha目前似乎并没有如此的野心,直至目前,他 们还没有将Jasper商业化运作的想法,而纯粹只想让更多开发者和黑客加入到Jasper这一项目中,集合无数人的创意与想法,探索这一设备未来更多的 可能性。而对这些极客来说,比起Jasper在不同领域的运用,让更多人意识到现存的开源代码背后所蕴含的巨大潜能更有意义。

 

开源语音识别项目JuliusJS

现在,你可以用你的声音控制你的智能手机。像苹果的Siri和谷歌,不触摸屏幕你就可以搜索网络,寻找简单问题的答案,并更新你的在线日历。但是在台式电脑上语音控制仍是未来的事情。再在许多新的台式机附 带语音识别软件,可以让你控制一些事情。编程学校的波默朗茨的目标是更多的东西。他试图建立一个开源项目叫做JuliusJS,,帮助软件开发人员构建 web语音应用程序的工具,他要为台式机构建一个类似Siri的应用程序。截至目前,JuliusJS只能识别包含在样本字典中的几句话,想要识别更多程 序员将不得不扩大软件的词汇本身。但它是一个开源项目。因此,它可以生长。
  今天,开发商有兴趣加入语音控制到一个Web应用程序。现代浏览器都有一些语音控制工具,但他们总是依赖于某种形式的远程服务,如谷歌的基本语音处理 在远程服务器上。这涉及到整个网络流媒体的声音。JuliusJS会解决此问题。这是一个运行在浏览器中的代码库,而且由于它使用通用的Web标准,它几 乎在任何一台电脑上可以运行。开发人员可以从网站的网站导航来构建工具,添加语音控制进入游戏,或者做别的没有想到事。

 

 

7个开源的TTS(文本转语音)系统推荐

摘要:TTS可以帮助有视觉障碍的人阅读计算机上的信息,或者只是简单的用来增加文本文档的可读性。TTS经常与声音识别程序一起使用。

TTS(Text To Speech,文本转语音)是语音合成应用的一种,它将储存于电脑中的文件,如帮助文件或者网页,转换成自然语音输出。TTS可以帮助有视觉障碍的人阅读 计算机上的信息,或者只是简单的用来增加文本文档的可读性。TTS经常与声音识别程序一起使用。

1.MARY - Text-to-Speech System

MARY是一个采用Java开发的、多语种的文本转语音平台,它支持:德语、英语、美式英语、泰卢固语、土耳其语和俄语。

2.SpeakRight Framework - Helps to build Speech Recognition Applications

SpeakRight 是一个 Java 框架,用于编写语音识别应用,基于 VoiceXML 技术。使用 StringTemplate 模板引擎自动生成 VoiceXML 文档。

3.Festival - Speech Synthesis System

Festival提供了一个通用的框架,用于构建语音合成系统,该系统包含了各种模块示例。它提供了完整的文本转语音的API,原生支持Mac OS,支持的语言包括英语和西班牙语。

4.FreeTTS - Speech Synthesizer in Java

FreeTTS 是完全采用 Java 开发的语音合成系统,它是卡内基梅隆大学基于 Flite 这个小型的语音合成引擎开发的。

5.Festvox - Builds New Synthetic Voices

Festvox项目构建了一个更加系统化、全新的语音合成功能。Festvox是大部分语音合成库的基础。

6.eSpeak - Text to Speech 

eSpeak是一个小型的、开放源码的语音合成系统,支持多种语言。eSpeak使用共振峰合成方法,这可以使提供的语言文件非常小。该系统支持 Windows平台上的SAPI5,所以能用于屏幕阅读程序和其他支持Windows SAPI5接口的程序。eSpeak可以将文本转换成音素代码,因此它也可以用于另一个语音合成引擎的前端。

7.Flite - Fast Run time Synthesis Engine

Flite是一个小型、快速的TTS系统,是著名的语音合成系统festival的C版本,可用于嵌入式系统。

文章出自:OPEN资讯

英文出自:findbestopensource

 

 

Android 轻松实现语音识别

苹果的iphone 有语音识别用的是Google 的技术,做为Google 力推的Android 自然会将其核心技术往Android 系统里面植入,并结合google 的云端技术将其发扬光大。 
所以Google Voice Recognition在Android 的实现就变得极其轻松。 
语音识别,借助于云端技术可以识别用户的语音输入,包括语音控制等技术,下面我们将利用Google 提供的Api 实现这一功能。 
功能点为:通过用户语音将用户输入的语音识别出来,并打印在列表上。 
用户通过点击speak按钮显示界面: 
用户说完话后,将提交到云端搜索: 
在云端搜索完成后,返回打印数据:

Android 轻松实现语音识别的完整代码    

* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package com.example.android.apis.app;
 
import com.example.android.apis.R;
 
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
 
import java.util.ArrayList;
import java.util.List;
 
/**
* Sample code that invokes the speech recognition intent API.
*/
public class VoiceRecognition extends Activity implements OnClickListener {
 
private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;
 
private ListView mList;
 
/**
* Called with the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
 
// Inflate our UI from its XML layout description.
setContentView(R.layout.voice_recognition);
 
// Get display items for later interaction
Button speakButton = (Button) findViewById(R.id.btn_speak);
 
mList = (ListView) findViewById(R.id.list);
 
// Check to see if a recognition activity is present
PackageManager pm = getPackageManager();
List activities = pm.queryIntentActivities(
new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
if (activities.size() != 0) {
speakButton.setOnClickListener(this);
} else {
speakButton.setEnabled(false);
speakButton.setText("Recognizer not present");
}
}
 
/**
* Handle the click on the start recognition button.
*/
public void onClick(View v) {
if (v.getId() == R.id.btn_speak) {
startVoiceRecognitionActivity();
}
}
 
/**
* Fire an intent to start the speech recognition activity.
*/
private void startVoiceRecognitionActivity() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Speech recognition demo");
startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
}
 
/**
* Handle the results from the recognition activity.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK) {
// Fill the list view with the strings the recognizer thought it could have heard
ArrayList matches = data.getStringArrayListExtra(
RecognizerIntent.EXTRA_RESULTS);
mList.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1,
matches));
}
 
super.onActivityResult(requestCode, resultCode, data);
}
}

 

Google推出开源语音视频聊天软件WebRTC

天极网软件频道2011-06-22 09:30

  Google近期推出了开源的语音视频聊天软件WebRTC。有消息称Google将把这款功能类似Skype的软件集成到Chrome浏览器中。

  WebRTC源于Google 2010年收购的互联网电话和视频会议公司Global IP Solutions(以下简称“GIPS”)。当Chrome浏览器集成WebRTC之后,Gmail的受益最明显。目前,Gmail拥有语音视频聊天功能,但用户需要安装Google私有的插件。随着Google VoIP业务的成熟,以及Gmail对Google Voice/Talk等的集成,Gmail聊天已经越来越重要。

  不过,Google对WebRTC有更高的期望。Google希望WebRTC能成为互联网视频会议和点对点通信的标准,并在此基础之上制定网 络通信协议。Google在官方博客中表示,WebRTC将是开源、无版权费的,Google还将就WebRTC与Mozilla和Opera等其他浏览器厂商合作。

  Google是网页应用和云计算的积极支持者。网页应用能够很方便地跨操作系统,不仅可以用于Windows和Mac OS X,也可以被智能手机使用。预计WebRTC将很快进入Chrome浏览器。

  Google GIPS一名程序员亨里克·安德里森(Henrik Andreasson)表示:“我们的目标是通过简单的Javascript应用程序接口,使Chrome拥有实时通信能力(RTC)。我们正在努力使Chrome全面支持RTC,从WebKit到语音视频通信功能。”

  WebRTC使用了GIPS的两款语音编解码器,包括用于宽带连接的iSAC和用于窄带连接的iLBC。视频部分,WebRTC使用了Google的VP8编解码器,这也是一项开源、无版权费的技术。

 

 几个常见的语音交互平台的简介和比较
分类: 多媒体技术 2014-01-19 16:04 2762人阅读 评论(0) 收藏 举报

目录(?)[+]
1.概述

最近做了两个与语音识别相关的项目,两个项目的主要任务虽然都是语音识别,或者更确切的说是关键字识别,但开发的平台不同, 一个是windows下的,另一个是android平台的,于是也就选用了不同的语音识别平台,前者选的是微软的Speech API开发的,后者则选用 的是CMU的pocketsphinx,本文主要将一些常见的语音交互平台进行简单的介绍和对比。

这里所说的语音交互包含语音识别(Speech Recognition,SR,也称为自动语音识别,Automatic Speech Recognition,ASR)和语音 合成(Speech Synthesis,SS,也称为Text-To-Speech,简记为TTS)两种技术,另外还会提到声纹识别(Voice Print Recognition, 简记为VPR)技术。

语音识别技术是将计算机接收、识别和理解语音信号转变为相应的文本文件或者命令的技术。它是一门涉及到语音语言学、信号处理、 模式识别、概率论和信息论、发声机理和听觉机理、人工智能的交叉学科。在语音识别系统的帮助下,即使用户不懂电脑或者无法使用 电脑,都可以通过语音识别系统对电脑进行操作。

语音合成,又称文语转换(Text to Speech)技术,能将任意文字信息实时转化为标准流畅的语音朗读出来,相当于给机器装上了人工 嘴巴。它涉及声学、语言学、数字信号处理、计算机科学等多个学科技术,是中文信息处理领域的一项前沿技术,解决的主要问题就是如何 将文字信息转化为可听的声音信息,也即让机器像人一样开口说话。

下面按平台是否开源来介绍几种常见的语音交互平台,关于语音识别和语音合成技术的相关原理请参见我接下来的其他文章。
2.商业化的语音交互平台
1)微软Speech API

微软的Speech API(简称为SAPI)是微软推出的包含语音识别(SR)和语音合成(SS)引擎的应用编程接口(API),在Windows下应用 广泛。目前,微软已发布了多个SAPI版本(最新的是SAPI 5.4版),这些版本要么作为于Speech SDK开发包发布,要么直接被包含在windows 操作系统中发布。SAPI支持多种语言的识别和朗读,包括英文、中文、日文等。SAPI的版本分为两个家族,1-4为一个家族,这四个版本彼此 相似,只是稍微添加了一些新的功能;第二个家族是SAPI5,这个系列的版本是全新的,与前四个版本截然不同。

最早的SAPI 1.0于1995年发布,支持Windows 95和Windows NT 3.51。这个版本的SAPI包含比较初级的直接语音识别和直接语音合成的API, 应用程序可以直接控制识别或合成引擎,并简化更高层次的语音命令和语音通话的API。SAPI3.0于97年发布,它添加了听写语音识别(非连续 语音识别)和一些应用程序实例。98年微软发布了SAPI4.0,这个版本不仅包含了核心的COM API,用C++类封装,使得用C++来编程更容易, 而且还有ActiveX控件,这个控件可以再VB中拖放。这个版本的SS引擎随Windows2000一起发布,而SR引擎和SS引擎又一起以SDK的形式发布。

SAPI5.0 于2000年发布,新的版本将严格将应用与引擎分离的理念体现得更为充分,所有的调用都是通过动态调用sapi.dll来实现的, 这样做的目的是使得API更为引擎独立化,防止应用依赖于某个具有特定特征的引擎,这种改变也意图通过将一些配置和初始化的代码放 到运行时来使得应用程序的开发更为容易。
2).IBM viaVoice

IBM是较早开始语音识别方面的研究的机构之一,早在20世纪50年代末期,IBM就开始了语音识别的研究,计算机被设计用来检测特定的语言 模式并得出声音和它对应的文字之间的统计相关性。在1964年的世界博览会上,IBM向世人展示了数字语音识别的“shoe box recognizer”。 1984年,IBM发布的语音识别系统在5000个词汇量级上达到了95%的识别率。

1992年,IBM引入了它的第一个听写系统,称为“IBM Speech Server Series (ISSS)”。1996年发布了新版的听写系统,成为“VoiceType3.0”, 这是viaVoice的原型,这个版本的语音识别系统不需要训练,可以实现孤立单词的听写和连续命令的识别。VoiceType3.0支持Windows95系统, 并被集成到了OS/2 WARP系统之中。与此同时,IBM还发布了世界上首个连续听写系统“MedSpeak Radiology”。最后,IBM及时的在假日购物季节 发布了大众化的实用的“VoiceType Simply Speaking”系统,它是世界上首个消费版的听写产品(the world’s first consumer dictation product).

1999年,IBM发布了VoiceType的一个免费版。2003年,IBM授权ScanSoft公司拥有基于ViaVoice的桌面产品的全球独家经销权,而ScanSoft公司 拥有颇具竞争力的产品“Dragon NaturallySpeaking”。两年后,ScanSoft与Nuance合并,并宣布公司正式更名为Nuance Communications,Inc。 现在很难找到IBM viaVoice SDK的下载地址了,它已淡出人们的视线,取而代之的是Nuance。
3)Nuance

Nuance通讯是一家跨国计算机软件技术公司,总部设在美国马萨诸塞州伯灵顿,主要提供语音和图像方面的解决方案和应用。目前的业务集中 在服务器和嵌入式语音识别,电话转向系统,自动电话目录服务,医疗转录软件与系统,光学字符识别软件,和台式机的成像软件等。

Nuance语音技术除了语音识别技术外,还包扩语音合成、声纹识别等技术。世界语音技术市场,有超过80%的语音识别是采用Nuance识别引擎技术, 其名下有超过1000个专利技术,公司研发的语音产品可以支持超过50种语言,在全球拥有超过20亿用户。据传,苹果的iPhone 4S的Siri语音识别中 应用了Nuance的语音识别服务。另外,据Nuance公司宣布的重磅消息,其汽车级龙驱动器Dragon Drive将在新奥迪A3上提供一个免提通讯接口, 可以实现信息的听说获取和传递。

Nuance Voice Platform(NVP)是Nuance公司推出的语音互联网平台。Nuance公司的NVP平台由三个功能块组成:Nuance Conversation Server 对话服务器,Nuance Application Environment (NAE)应用环境及Nuance Management Station管理站。Nuance Conversation Server对话服务 器包括了与Nuance语音识别模块集成在一起的VoiceXML解释器,文语转换器(TTS)以及声纹鉴别软件。NAE应用环境包括绘图式的开发工具, 使得语音应用的设计变得和应用框架的设计一样便利。Nuance Management Station管理站提供了非常强大的系统管理和分析能力,它们是为了 满足语音服务的独特需要而设计的。
4)科大讯飞——讯飞语音

提到科大讯飞,大家都不陌生,其全称是“安徽科大讯飞信息科技股份有限公司”,它的前身是安徽中科大讯飞信息科技有限公司,成立于99 年12月,07年变更为安徽科大讯飞信息科技股份有限公司,现在是一家专业从事智能语音及语音技术研究、软件及芯片产品开发、语音信息服务 的企业,在中国语音技术领域可谓独占鳌头,在世界范围内也具有相当的影响力。

科大讯飞作为中国最大的智能语音技术提供商,在智能语音技术领域有着长期的研究积累,并在中文语音合成、语音识别、口语评测等多项 技术上拥有国际领先的成果。03年,科大讯飞获迄今中国语音产业唯一的“国家科技进步奖(二等)”,05年获中国信息产业自主创新最高荣誉 “信息产业重大技术发明奖”。06年至11年,连续六届英文语音合成国际大赛(Blizzard Challenge)荣获第一名。08年获国际说话人识别评测 大赛(美国国家标准技术研究院—NIST 2008)桂冠,09年获得国际语种识别评测大赛(NIST 2009)高难度混淆方言测试指标冠军、通用测试 指标亚军。

科大讯飞提供语音识别、语音合成、声纹识别等全方位的语音交互平台。拥有自主知识产权的智能语音技术,科大讯飞已推出从大型电信级 应用到小型嵌入式应用,从电信、金融等行业到企业和家庭用户,从PC到手机到MP3/MP4/PMP和玩具,能够满足不同应用环境的多种产品,科大 讯飞占有中文语音技术市场60%以上市场份额,语音合成产品市场份额达到70%以上。
5)其他

其他的影响力较大商用语音交互平台有谷歌的语音搜索(Google Voice Search),百度和搜狗的语音输入法等等,这些平台相对于以上的4个 语音交互平台,应用范围相对较为局限,影响力也没有那么强,这里就不详细介绍了。
3.开源的语音交互平台
1)CMU-Sphinx

CMU-Sphinx也简称为Sphinx(狮身人面像),是卡内基 - 梅隆大学( Carnegie Mellon University,CMU)开发的一款开源的语音识别系统, 它包括一系列的语音识别器和声学模型训练工具。

Sphinx有多个版本,其中Sphinx1~3是C语言版本的,而Sphinx4是Java版的,另外还有针对嵌入式设备的精简优化版PocketSphinx。Sphinx-I 由李开复(Kai-Fu Lee)于1987年左右开发,使用了固定的HMM模型(含3个大小为256的codebook),它被号称为第一个高性能的连续语音识别 系统(在Resource Management数据库上准确率达到了90%+)。Sphinx-II由Xuedong Huang于1992年左右开发,使用了半连续的HMM模型, 其HMM模型是一个包含了5个状态的拓扑结构,并使用了N-gram的语言模型,使用了Fast lextree作为实时的解码器,在WSJ数据集上的识别率 也达到了90%+。

Sphinx-III主要由Eric Thayer 和Mosur Ravishankar于1996年左右开发,使用了完全连续的(也支持半连续的)HMM模型,具有灵活 的feature vector和灵活的HMM拓扑结构,包含可选的两种解码器:较慢的Flat search和较快的Lextree search。该版本在BN(98的测评数据 集)上的WER(word error ratio)为19%。Sphinx-III的最初版还有很多limitations,诸如只支持三音素文本、只支持Ngram模型(不 支持CFG/FSA/SCFG)、对所有的sound unit其HMM拓扑结构都是相同的、声学模型也是uniform的。Sphinx-III的最新版是09年初发布的0.8版, 在这些方面有很多的改进。

最新的Sphinx语音识别系统包含如下软件包:
? Pocketsphinx — recognizer library written in C.
? Sphinxbase — support library required by Pocketsphinx
? Sphinx4 — adjustable, modifiable recognizer written in Java
? CMUclmtk — language model tools
? Sphinxtrain — acoustic model training tools
这些软件包的可执行文件和源代码在sourceforge上都可以免费下载得到。
2)HTK

HTK是Hidden Markov Model Toolkit(隐马尔科夫模型工具包)的简称,HTK主要用于语音识别研究,现在已经被用于很多其他方面的研究, 包括语音合成、字符识别和DNA测序等。

HTK最初是由剑桥大学工程学院(Cambridge University Engineering Department ,CUED)的机器智能实验室(前语音视觉及机器人组) 于1989年开发的,它被用来构建CUED的大词汇量的语音识别系统。93年Entropic Research Laboratory Inc.获得了出售HTK的权利,并在95年 全部转让给了刚成立的Entropic Cambridge Research Laboratory Ltd,Entropic一直销售着HTK,直到99年微软收购了Entropic,微软重新 将HTK的版权授予CUED,并给CUED提供支持,这样CUED重新发布了HTK,并在网络上提供开发支持。

HTK的最新版本是09年发布的3.4.1版,关于HTK的实现原理和各个工具的使用方法可以参看HTK的文档HTKBook。
3)Julius

Julius是一个高性能、双通道的大词汇量连续语音识别(large vocabulary continues speech recognition,LVCSR)的开源项目, 适合于广大的研究人员和开发人员。它使用3-gram及上下文相关的HMM,在当前的PC机上能够实现实时的语音识别,单词量达到60k个。

Julius整合了主要的搜索算法,高度的模块化使得它的结构模型更加独立,它同时支持多种HMM模型(如shared-state triphones 和 tied-mixture models等),支持多种麦克风通道,支持多种模型和结构的组合。它采用标准的格式,这使得和其他工具箱交叉使用变得 更容易。它主要支持的平台包括Linux和其他类Unix系统,也适用于Windows。它是开源的,并使用BSD许可协议。

自97年后,Julius作为日本LVCSR研究的一个自由软件工具包的一部分而延续下来,后在2000年转由日本连续语音识别联盟(CSRC)经营。 从3.4版起,引入了被称为“Julian”的基于语法的识别解析器,Julian是一个改自Julius的以手工设计的DFA作为语言模型的版本,它可以 用来构建小词汇量的命令识别系统或语音对话系统。
4)RWTH ASR

该工具箱包含最新的自动语音识别技术的算法实现,它由 RWTH Aachen 大学的Human Language Technology and Pattern Recognition Group 开发。

RWTH ASR工具箱包括声学模型的构建、解析器等重要部分,还包括说话人自适应组件、说话人自适应训练组件、非监督训练组件、个性化 训练和单词词根处理组件等,它支持Linux和Mac OS等操作系统,其项目网站上有比较全面的文档和实例,还提供了现成的用于研究目的的 模型等。

该工具箱遵从一种从QPL发展而来的开源协议,只允许用于非商业用途。
5)其他

上面提到的开源工具箱主要都是用于语音识别的,其他的开源语音识别项目还有Kaldi 、simon 、iATROS-speech 、SHoUT 、 Zanzibar OpenIVR 等。

常见的语音合成的开源工具箱有MARY、SpeakRight、Festival 、FreeTTS 、Festvox 、eSpeak 、Flite 等。

常见的声纹识别的开源工具箱有Alize、openVP等。
4.小结

本文介绍了几种常见的语音交互平台,主要是语音识别、语音合成的软件或工具包,还顺便提到了声纹识别的内容, 下面做一个简单的总结:
以上总结的表格希望对读者有用!

参考文献

[1]语音识别-维基百科:http://zh.wikipedia.org/wiki/语音识别 
[2]语音合成-百度百科:http://baike.baidu.com/view/549184.htm 
[3] Microsoft Speech API:http://en.wikipedia.org/wiki/Speech_Application_Programming_Interface#SAPI_1 
[4] MSDN-SAPI:http://msdn.microsoft.com/zh-cn/library/ms723627.aspx 
[5] 微软语音技术 Windows 语音编程初步:http://blog.csdn.net/yincheng01/article/details/3511525 
[6]IBM Human Language Technologies History:http://www.research.ibm.com/hlt/html/history.html 
[7] Nuance: http://en.wikipedia.org/wiki/Nuance_Communications 
[8] 科大讯飞:http://baike.baidu.com/view/362434.htm 
[9] CMU-Sphinx: http://en.wikipedia.org/wiki/CMU_Sphinx 
[10] CMU Sphinx homepage:http://cmusphinx.sourceforge.net/wiki/ 
[11] HTK Toolkit:http://htk.eng.cam.ac.uk/ 
[12] Julius:http://en.wikipedia.org/wiki/Julius_(software) 
[13] RWTH ASR:http://en.wikipedia.org/wiki/RWTH_ASR 
[14] List of speech recognition software: http://en.wikipedia.org/wiki/List_of_speech_recognition_software 
[15] Speech recognition: http://en.wikipedia.org/wiki/Speech_recognition 
[16] Speech synthesis: http://en.wikipedia.org/wiki/Speech_synthesis 
[17] Speaker recognition: http://en.wikipedia.org/wiki/Speaker_recognition

 

 Sphinx-4一个完全采用Java开的语音识别器.
  http://cmusphinx.sourceforge.net/sphinx4/#what_is_sphinx4

 

Google推出开源语音视频聊天软件WebRTC

天极网软件频道2011-06-22 09:30

  Google近期推出了开源的语音视频聊天软件WebRTC。有消息称Google将把这款功能类似Skype的软件集成到Chrome浏览器中。

  WebRTC源于Google 2010年收购的互联网电话和视频会议公司Global IP Solutions(以下简称“GIPS”)。当Chrome浏览器集成WebRTC之后,Gmail的受益最明显。目前,Gmail拥有语音视频聊天功能,但用户需要安装Google私有的插件。随着Google VoIP业务的成熟,以及Gmail对Google Voice/Talk等的集成,Gmail聊天已经越来越重要。

  不过,Google对WebRTC有更高的期望。Google希望WebRTC能成为互联网视频会议和点对点通信的标准,并在此基础之上制定网 络通信协议。Google在官方博客中表示,WebRTC将是开源、无版权费的,Google还将就WebRTC与Mozilla和Opera等其他浏览器厂商合作。

  Google是网页应用和云计算的积极支持者。网页应用能够很方便地跨操作系统,不仅可以用于Windows和Mac OS X,也可以被智能手机使用。预计WebRTC将很快进入Chrome浏览器。

  Google GIPS一名程序员亨里克·安德里森(Henrik Andreasson)表示:“我们的目标是通过简单的Javascript应用程序接口,使Chrome拥有实时通信能力(RTC)。我们正在努力使Chrome全面支持RTC,从WebKit到语音视频通信功能。”

  WebRTC使用了GIPS的两款语音编解码器,包括用于宽带连接的iSAC和用于窄带连接的iLBC。视频部分,WebRTC使用了Google的VP8编解码器,这也是一项开源、无版权费的技术。

 

一个简单语音识别系统:

http://www.cnblogs.com/zhuweisky/p/4059048.html

 

调用科大讯飞:

http://www.apkbus.com/android-170225-1-1.html

 

开源语音格式speex教程(for iOS):

http://www.cocoachina.com/industry/20121105/5029.html



2019-09-28 17:58:24 qq_42233538 阅读数 234
  • Android 实战开发 三方SDK 讯飞语音SDK

    Android 第三方SDK开发视频教程,给课程结合讯飞语音这个第三方SDK进行实战教学,实现在线语音合成,将文字信息转化为声音信息,给应用配上“嘴巴;语音听写,将连续语音识别为文字,给应用配上“耳朵”。

    4837 人正在学习 去看看 Frank Lee

目标:

1.学习使用百度AI开放平台进行语音识别与语音合成

       百度AI有两种开发方式:REST, SDK;    本文使用的是REST api+python进行开发

        文档地址:https://ai.baidu.com/docs#/ASR-Guide/top

2.将学到的内容:JSON数据,HTTP API调用,base64文件编码与解码

3.生成exe格式可执行文件

  pyinstaller -F xxx.py 参考文档 https://blog.csdn.net/qq_35203425/article/details/78568141

4.python-Tkinter图形界面开发

问题点:

1.界面上的模块不会随窗口放大产生变化

2.未添加异常捕获

界面:

代码:

from tkinter import *
from tkinter import ttk
from tkinter.filedialog import askopenfilename,askdirectory
import json
import requests
import base64
from urllib.parse import urlencode,quote_plus
import os

class Audio():
    def __init__(self):
        #参数初始化化
        # self.width,self.height,self.xoffset,self.yoffset=800,400,350,200  #定义窗口大小
        self.myWindow = Tk()
        self.path =  StringVar()          #搜索路径变量
        self.path1=StringVar()            #保存路径变量
        self.audio_formats = StringVar() #定义音频识别格式

        self.API_Key = 'AN6TAou6hNd5UEMxBGxUFXGC'             #百度AI秘钥
        self.Secret_Key = 'rTb6zkjVWEnuXoEVyv6cSaiblzNfxP6l'
        self.url_1 = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=' \
                     'client_credentials&client_id=AN6TAou6hNd5UEMxBGxUFXGC&client_secret=rTb6zkjVWEnuXoEVyv6cSaiblzNfxP6l& '
        self.url_2='http://vop.baidu.com/server_api'
        self.url_3 = 'http://tsn.baidu.com/text2audio'
    def selectPath(self):
        # 路径搜索
        self.name = askopenfilename()
        self.path.set(self.name)
    def savepath(self):
        self.name1=askdirectory()
        self.path1.set(self.name1)

    def audio_recognition(self):
        #语言识别模块
        audio_path=self.path.get()
        audio_formats=self.audio_formats.get()
        if len(audio_path) == 0 or len(audio_formats) == 0:
            self.text.insert(INSERT, '未选定识别文件')
        else:
            response = requests.get(url=self.url_1)
            self.token = response.json()['access_token']
            # 打开文件
            with open(audio_path,'rb') as f:
                audio=f.read()
            # 识别文件
            length = len(audio)
            speech = base64.b64encode(audio)
            speech = str(speech, 'utf-8')
            params = {
                "format": audio_formats,
                "rate": 16000,

                "channel": '1',
                "token": self.token,
                "cuid": 'D8-F2-CA-06-B4-59',
                'len': length,
                "speech": speech}
            post_data = json.dumps(params, sort_keys=False)
            text = requests.post(self.url_2, post_data.encode('utf-8'))
            # 输出文件内容
            if text.json()['err_msg']=='success.':
                self.text.insert(INSERT,text.json()[ 'result'])
            else:
                self.text.insert(INSERT,text.json()['err_msg']+text.json()['err_no'])

    def audi_composite(self):
        #语言合成模块
        response = requests.get(url=self.url_1)
        token = response.json()['access_token']
        string=self.text1.get(1.0,2.0)
        tex = quote_plus(string)

        params = {'tok': token, 'tex': tex, 'per': 1, 'spd': 5, 'pit': 5, 'vol': 5, 'aue': 3,
                  'cuid': 'D8-F2-CA-06-B4-59',
                  'lan': 'zh', 'ctp': 1}
        data = urlencode(params)
        audio = requests.post(self.url_3, data.encode('utf-8'))
        if len(self.path1.get())!=0:
            path=os.path.join(self.path1.get(),'audio.mp3')

            with open(path, 'wb') as f:
                f.write(audio.content)

    def interface(self):
        # 制作界面

        self.myWindow.title('语音演示程序')  # 修改窗口标题
        self.myWindow.geometry("800x400+350+200")  # 修改窗口大小 width*height+xoffset+yoffset
        # 创建两个标签容器
        frm_l = LabelFrame(self.myWindow, text='语言识别', width=380, height=380)
        frm_l.grid(row=0, column=0, ipadx=20, ipady=10, padx=10, pady=10)
        frm_r = LabelFrame(self.myWindow, text='语言合成', width=380, height=380)
        frm_r.grid(row=0, column=1, padx=10, pady=10)

        entry1 = Entry(frm_l, textvariable=self.path, width=35).grid(row=0, column=0, rowspan=2, columnspan=4, sticky='EW', pady=5, padx=5)
        button1 = Button(frm_l, text='选择文件', command=self.selectPath, width=10, height=1).grid(row=0, column=4, sticky='EW',pady=5, padx=5)

        label_1 = Label(frm_l, text="音频格式").grid(row=2, column=0, sticky='EW', pady=5, padx=5)
        com = ttk.Combobox(frm_l, textvariable=self.audio_formats, value=['PCM', 'WAV', 'AMR'], width=10, height=1)
        com.current(0)
        com.grid(row=2, column=1, sticky='EW', pady=5, padx=5)
        button2 = Button(frm_l, text='开始识别', command=self.audio_recognition, width=10, height=1).grid(row=2, column=4,sticky='EW', pady=5,padx=5)

        label_2 = Label(frm_l, text='识别结果').grid(row=4, column=0, sticky='EW', pady=5, padx=5)

        self.text = Text(frm_l, width=40, height=15)
        self.text.grid(row=5, column=0, rowspan=2, columnspan=5, sticky='EW', pady=5, padx=5)

        # 语音合成模块

        self.text1 = Text(frm_r, width=50, height=19)
        self.text1.grid(row=0, column=0, rowspan=2, columnspan=4, sticky='EW', pady=5, padx=5)


        entry1 = Entry(frm_r, textvariable=self.path1).grid(row=2, column=0, rowspan=1, columnspan=3,
                                                                     sticky='EW', pady=5, padx=5)
        button4=Button(frm_r, text='保存路径',command=self.savepath, width=10, height=1).grid(row=2, column=3, sticky='EW',pady=5, padx=5)

        button3 = Button(frm_r, text='开始合成',command=self.audi_composite, width=10, height=1)
        button3.grid(row=3, column=3, sticky='EW', pady=5, padx=5)

        # 启动主窗口的消息循环
        self.myWindow.mainloop()

if __name__ == '__main__':
    audio=Audio()
    audio.interface()

 

 

 

2019-03-29 17:21:17 weixin_40391500 阅读数 698
  • Android 实战开发 三方SDK 讯飞语音SDK

    Android 第三方SDK开发视频教程,给课程结合讯飞语音这个第三方SDK进行实战教学,实现在线语音合成,将文字信息转化为声音信息,给应用配上“嘴巴;语音听写,将连续语音识别为文字,给应用配上“耳朵”。

    4837 人正在学习 去看看 Frank Lee

上一遍写了语音唤醒和语音合成,这篇写下语音合成

/**
 * 语音识别
 * Created by fujiayi on 2017/6/13.
 * EventManager内的方法如send 都可以在主线程中进行,SDK中做过处理
 */

public class RecognizerUtils {
    private final String TAG = this.getClass().getSimpleName();
    private static RecognizerUtils utils = null;

    /**
     * SDK 内部核心 EventManager 类
     */
    private EventManager asr;
    // SDK 内部核心 事件回调类, 用于开发者写自己的识别回调逻辑
    private EventListener eventListener;
    // 是否加载离线资源
    private boolean isOfflineEngineLoaded = false;
    // 未release前,只能new一个
    private volatile boolean isInited = false;
    /**
     * 0: 方案1, backTrackInMs > 0,唤醒词说完后,直接接句子,中间没有停顿。
     *              开启回溯,连同唤醒词一起整句识别。推荐4个字 1500ms
     *          backTrackInMs 最大 15000,即15s
     *
     * >0 : 方案2:backTrackInMs = 0,唤醒词说完后,中间有停顿。
     *       不开启回溯。唤醒词识别回调后,正常开启识别。
     * <p>
     *
     */
    private static int backTrackInMs = 0;
    private static Handler handler = null;
    public static final int RECOGNIZER_ERROR = 1012;

    public static RecognizerUtils getIntance(){
        if (utils == null){
            synchronized (RecognizerUtils.class){
                if (utils == null){
                    utils = new RecognizerUtils();
                }
            }
        }
        return utils;
    }

    public void init(Handler mHandler){
        handler = mHandler;
        if (isInited) {
            LogUtils.log(TAG,"还未调用release(),请勿新建一个新类");
            return;
        }
        isInited = true;
        // SDK集成步骤 初始化asr的EventManager示例,多次得到的类,只能选一个使用
        asr = EventManagerFactory.create(MyApplication.context, "asr");
        // SDK集成步骤 设置回调event, 识别引擎会回调这个类告知重要状态和识别结果
        asr.registerListener(new EventListener() {
            @Override
            public void onEvent(String name, String params, byte[] data, int offset, int length) {
                eventListener = this;

                if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_LOADED)) {
                    LogUtils.log("RecognizerUtils", "离线命令词资源加载成功");
                } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_UNLOADED)) {
                    LogUtils.log("RecognizerUtils", "离线命令词资源释放成功");
                } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_READY)) {
                    // 引擎准备就绪,可以开始说话
                    LogUtils.log("RecognizerUtils", "引擎准备就绪,可以开始说话");
                } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_BEGIN)) {
                    // 检测到用户的已经开始说话
                    LogUtils.log("RecognizerUtils", "检测到用户的已经开始说话");
                } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_END)) {
                    // 检测到用户的已经停止说话
                    LogUtils.log("RecognizerUtils", "检测到用户的已经停止说话");
                } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {
                    RecogResult recogResult = RecogResult.parseJson(params);
                    // 临时识别结果, 长语音模式需要从此消息中取出结果
                    LogUtils.log("RecognizerUtils", "临时识别结果, 长语音模式需要从此消息中取出结果");
                    String[] results = recogResult.getResultsRecognition();
                    if (recogResult.isFinalResult()) {
                        LogUtils.log("RecognizerUtils", "isFinalResult 可能返回多个结果,请取第一个结果" + Arrays.toString(results));
                        Resolution.getIntance().resolution(handler, Arrays.toString(results));
                    } else if (recogResult.isPartialResult()) {
                        LogUtils.log("RecognizerUtils", "onAsrBegin 后 随着用户的说话,返回的临时结果" + Arrays.toString(results));
                    } else if (recogResult.isNluResult()) {
                        LogUtils.log("RecognizerUtils", "isNluResult 可能返回多个结果,请取第一个结果" + new String(data, offset, length));
                    }

                } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_FINISH)) {
                    // 识别结束, 最终识别结果或可能的错误
                    LogUtils.log("RecognizerUtils", name + "- CALLBACK_EVENT_ASR_FINISH识别结束, 最终识别结果或可能的错误");
                    RecogResult recogResult = RecogResult.parseJson(params);
                    if (recogResult.hasError()) {
//                        int errorCode = recogResult.getError();
//                        int subErrorCode = recogResult.getSubError();
                        if (handler != null){
                            handler.sendEmptyMessage(RECOGNIZER_ERROR);
                        }
                        LogUtils.log("RecognizerUtils", "识别结束, 最终识别结果错误" + recogResult.getDesc());
                    } else {
                        LogUtils.log("RecognizerUtils", "识别结束, 最终识别结果" + params);
                    }
                } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_LONG_SPEECH)) { // 长语音
                    LogUtils.log("RecognizerUtils", "长语音");
                } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_EXIT)) {
                    LogUtils.log("RecognizerUtils", "退出");
                } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_VOLUME)) {
                    // Logger.info(TAG, "asr volume event:" + params);
                    LogUtils.log("RecognizerUtils", params);
                } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_AUDIO)) {
//                    LogUtils.log("RecognizerUtils", "长语音");
                }
            }
        });
        loadOfflineEngine(fetchOfflineParams());
    }

    /**
     * 离线命令词,在线不需要调用
     *
     * @param params 离线命令词加载参数,见文档“ASR_KWS_LOAD_ENGINE 输入事件参数”
     */
    private void loadOfflineEngine(Map<String, Object> params) {
        String json = new JSONObject(params).toString();
        // SDK集成步骤(可选)加载离线命令词(离线时使用)
        asr.send(SpeechConstant.ASR_KWS_LOAD_ENGINE, json, null, 0, 0);
        isOfflineEngineLoaded = true;
        // 没有ASR_KWS_LOAD_ENGINE这个回调表试失败,如缺少第一次联网时下载的正式授权文件。
    }

    private Map<String, Object> fetchOfflineParams() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put(SpeechConstant.DECODER, 2);
        map.put(SpeechConstant.ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH, "assets:///baidu_speech_grammar.bsg");
//        map.putAll(fetchSlotDataParam());
        return map;
    }

    private Map<String, Object> fetchSlotDataParam() {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            JSONObject json = new JSONObject();
            json.put("name", new JSONArray().put("妈妈").put("老伍"))
                    .put("appname", new JSONArray().put("手百").put("度秘"));
            map.put(SpeechConstant.SLOT_DATA, json);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 开始
     */
    public void start() {
        // 此处 开始正常识别流程
        Map<String, Object> params = new LinkedHashMap<String, Object>();
        if (isOfflineEngineLoaded){
            params.put(SpeechConstant.DECODER, 2);
        }
        params.put(SpeechConstant.ACCEPT_AUDIO_VOLUME, false);
        params.put(SpeechConstant.VAD, SpeechConstant.VAD_DNN);
        // 如识别短句,不需要需要逗号,使用1536搜索模型。其它PID参数请看文档
        params.put(SpeechConstant.PID, 1536);
        if (backTrackInMs > 0) {
            // 方案1  唤醒词说完后,直接接句子,中间没有停顿。开启回溯,连同唤醒词一起整句识别。
            // System.currentTimeMillis() - backTrackInMs ,  表示识别从backTrackInMs毫秒前开始
            params.put(SpeechConstant.AUDIO_MILLS, System.currentTimeMillis() - backTrackInMs);
        }
        cancel();
        // SDK集成步骤 拼接识别参数
        String json = new JSONObject(params).toString();
        asr.send(SpeechConstant.ASR_START, json, null, 0, 0);
    }


    /**
     * 提前结束录音等待识别结果。
     */
    public void stop() {
        // SDK 集成步骤(可选)停止录音
        if (!isInited) {
//            throw new RuntimeException("release() was called");
        }
        if (asr == null) {
            return;
        }
        asr.send(SpeechConstant.ASR_STOP, "{}", null, 0, 0);
    }

    /**
     * 取消本次识别,取消后将立即停止不会返回识别结果。
     * cancel 与stop的区别是 cancel在stop的基础上,完全停止整个识别流程,
     */
    public void cancel() {
        if (!isInited) {
//            throw new RuntimeException("release() was called");
        }
        if (asr == null) {
            return;
        }
        // SDK集成步骤 (可选) 取消本次识别
        asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
    }

    public void release() {
        isInited = false;
        cancel();
        if (asr == null) {
            return;
        }
        if (isOfflineEngineLoaded) {
            // SDK集成步骤 如果之前有调用过 加载离线命令词,这里要对应释放
            asr.send(SpeechConstant.ASR_KWS_UNLOAD_ENGINE, null, null, 0, 0);
            isOfflineEngineLoaded = false;
        }
        // SDK 集成步骤(可选),卸载listener
        asr.unregisterListener(eventListener);
        asr = null;
        isInited = false;
        utils = null;
    }

}
/**
 * 解析语音识别
 */
public class Resolution {
    private final String TAG = this.getClass().getSimpleName();
    private static Resolution utils = null;

    public static Resolution getIntance() {
        if (utils == null) {
            synchronized (Resolution.class) {
                if (utils == null) {
                    utils = new Resolution();
                }
            }
        }
        return utils;
    }

    /**
     * 解析 通过handler返回状态
     * @param handler
     * @param work 识别结果
     */
    public void resolution(Handler handler, String work) {
        try {
            if (PhoneUtils.CALL_PHONE
                    && (work.equals("[确定]") || work.equals("[是的]"))
                    && !StringUtils.isEmpty(PhoneUtils.PHONE)){
                PhoneUtils.getInstance().callPhone(PhoneUtils.PHONE);
            }else if (work.indexOf("打开") != -1) {
                InstallAppUtils.getIntanste().openApp(work);
            } else if (work.indexOf("打电话") != -1) {
                PhoneUtils.getInstance().call(work);
            }else {
                TTSUtils.getInstance().speak(MyApplication.context.getString(R.string.wakeup_no_hear), true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

/**
 * 安装的APP实例
 * Created by pc20170521 on 2017-10-28.
 */
public class InstallAppInfo {
    private boolean check = false;
    private String pakecge;
    private Drawable icon;
    private String name;
    private ComponentName component;

    public InstallAppInfo(){

    }

    public InstallAppInfo(Drawable d, String s, ComponentName cn){
        icon = d;
        name = s;
        component = cn;
    }

    public Drawable getIcon() {
        return icon;
    }

    public void setIcon(Drawable icon) {
        this.icon = icon;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ComponentName getComponent() {
        return component;
    }

    public void setComponent(ComponentName component) {
        this.component = component;
    }

    public boolean isCheck() {
        return check;
    }

    public void setCheck(boolean check) {
        this.check = check;
    }

    public String getPakecge() {
        return component.getPackageName();
    }

    public void setPakecge(String pakecge) {
        this.pakecge = pakecge;
    }
}
/**
 * 获取安装的APP
 * Created by pc20170521 on 2017-10-28.
 */
public class InstallAppUtils {
    private final String TAG = this.getClass().getSimpleName();
    private ArrayList<InstallAppInfo> appList = null;
    private static InstallAppUtils utils = null;

    public static InstallAppUtils getIntanste(){
        if (utils == null){
            synchronized (InstallAppUtils.class){
                if(utils == null){
                    utils = new InstallAppUtils();
                }
            }
        }
        return utils;
    }


    /***
     * 获取安装的APP
     * @return
     */
    public ArrayList<InstallAppInfo> getInstallApp(){
        appList = new ArrayList<>();
        PackageManager pkgMgt = MyApplication.context.getPackageManager();

        Intent it = new Intent(Intent.ACTION_MAIN);
        it.addCategory(Intent.CATEGORY_LAUNCHER);

        List<ResolveInfo> ra = pkgMgt.queryIntentActivities(it,0);
        for(int i=0;i<ra.size();i++){
            ActivityInfo ai = ra.get(i).activityInfo;
            String label = ai.loadLabel(pkgMgt).toString();
            ComponentName c = new ComponentName(ai.applicationInfo.packageName,ai.name);
            InstallAppInfo item = new InstallAppInfo(ai.loadIcon(pkgMgt),label,c);
            appList.add(item);
        }
        return appList;
    }

    public ArrayList<InstallAppInfo> getAppList() {
        if (appList == null){
            appList = getInstallApp();
        }
        return appList;
    }

    /***
     * 语音打开某个APP
     */
    public void openApp(String name){
        name = name.substring(2);
        LogUtils.log(TAG, name);
        boolean isHasApp = false;
        for (int i = 0; i < getAppList().size(); i++) {
            if (name.contains(appList.get(i).getName())){
                TTSUtils.getInstance().speak(MyApplication.context.getString(R.string.wakeup_open_wx)
                        + appList.get(i).getName());
                try {
                    Intent intent;
                    PackageManager packageManager = MyApplication.context.getPackageManager();
                    intent = packageManager.getLaunchIntentForPackage(appList.get(i).getPakecge());
                    MyApplication.context.startActivity(intent);
                    isHasApp = true;
                    break;
                } catch (Exception e) {
                    TTSUtils.getInstance().speak(MyApplication.context.getString(R.string.wakeup_no_wx)
                            + appList.get(i).getName());
                    e.printStackTrace();
                }
            }
        }
        if (!isHasApp){
            TTSUtils.getInstance().speak(MyApplication.context.getString(R.string.wakeup_no_hear));
        }
    }

}
/**
 * 获取电话本/打电话工具类
 */
public class PhoneUtils {
    private final String TAG = this.getClass().getSimpleName();
    private static PhoneUtils utils = null;

    public static boolean CALL_PHONE = false;//语音拨电话请求
    public static String PHONE = "";//电话号码

    private List<PhoneInfo> list;

    public static PhoneUtils getInstance(){
        if (utils == null){
            synchronized (PhoneUtils.class){
                if (utils == null){
                    utils = new PhoneUtils();
                }
            }
        }
        return utils;
    }

    /**
     * 获取电话本
     * @return
     */
    public List<PhoneInfo> getPhoneList() {
        list = new ArrayList<>();
        Cursor cursor = MyApplication.context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                new String[] { "display_name", "sort_key", "contact_id",
                        "data1" }, null, null, null);
//        moveToNext方法返回的是一个boolean类型的数据
        while (cursor.moveToNext()) {
            //读取通讯录的姓名
            String name = cursor.getString(cursor
                    .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            //读取通讯录的号码
            String number = cursor.getString(cursor
                    .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            int Id = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
            String Sortkey = getSortkey(cursor.getString(1));
            PhoneInfo phoneInfo = new PhoneInfo(name, number,Sortkey,Id);
            list.add(phoneInfo);
//            LogUtils.log("电话联系人", name);
        }
        cursor.close();
        return list;
    }

    private static String getSortkey(String sortKeyString) {
        String key =sortKeyString.substring(0,1).toUpperCase();
        if (key.matches("[A-Z]")){
            return key;
        }else
            return "#";
    }

    /**
     * 语音识别并拨打电话
     */
    public void call(String name){
        try {
            name = name.substring(3);
            LogUtils.log(TAG, name);
            if (name.contains("10086")) {
                PHONE = "10086";
                name = "10086";
                callTips(name);
            } else {
                boolean isPhone = false;
                List<PhoneInfo> list = PhoneUtils.getInstance().getPhoneList();
                for (int i = 0; i < list.size(); i++) {
                    if (name.contains(list.get(i).getName())
                            || name.contains(list.get(i).getNumber())) {
                        PHONE = list.get(i).getNumber();
                        name = list.get(i).getName();
                        isPhone = true;
                        break;
                    }
                }
                if (isPhone) {
                    callTips(name);
                } else {
                    TTSUtils.getInstance().speak(MyApplication.context.getString(R.string.wakeup_no_phone));
                }
            }
        } catch (Exception e) {
            TTSUtils.getInstance().speak(MyApplication.context.getString(R.string.wakeup_no_phone));
            e.printStackTrace();
        }
    }

    /**
     * 拨打电话
     */
    private void callTips(String name) {
        CALL_PHONE = true;
        String tips = MyApplication.context.getString(R.string.wakeup_find_phone) + name
                + MyApplication.context.getString(R.string.wakeup_find_phone1);
        TTSUtils.getInstance().speak(tips, true);
        ProgressDialog dialog = new ProgressDialog(MyApplication.context);
        dialog.setTitle(tips);
        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {
                dialog.dismiss();
            }
        });
    }

    /**
     * 拨打电话
     * @param phone
     */
    public void callPhone(String phone) {
        Uri uri = Uri.parse("tel:" + phone);
        Intent intent = new Intent(Intent.ACTION_CALL, uri);
        if (ActivityCompat.checkSelfPermission(MyApplication.context, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
            ToastUtils.show(MyApplication.context, MyApplication.context.getString(R.string.phone_permision));
            PermissionsUtils.getInstance().showSystemPermissionsSettingDialog(MyApplication.activity);
            return;
        }
        MyApplication.activity.startActivityForResult(intent, 1);
        PHONE = "";
        CALL_PHONE = false;
    }

}
/**
 * Created by fujiayi on 2017/6/24.
 */
public class RecogResult {
    private static final int ERROR_NONE = 0;

    private String origalJson;
    private String[] resultsRecognition;
    private String origalResult;
    private String sn; // 日志id, 请求有问题请提问带上sn
    private String desc;
    private String resultType;
    private int error = -1;
    private int subError = -1;

    public static RecogResult parseJson(String jsonStr) {
        RecogResult result = new RecogResult();
        result.setOrigalJson(jsonStr);
        try {
            JSONObject json = new JSONObject(jsonStr);
            int error = json.optInt("error");
            int subError = json.optInt("sub_error");
            result.setError(error);
            result.setDesc(json.optString("desc"));
            result.setResultType(json.optString("result_type"));
            result.setSubError(subError);
            if (error == ERROR_NONE) {
                result.setOrigalResult(json.getString("origin_result"));
                JSONArray arr = json.optJSONArray("results_recognition");
                if (arr != null) {
                    int size = arr.length();
                    String[] recogs = new String[size];
                    for (int i = 0; i < size; i++) {
                        recogs[i] = arr.getString(i);
                    }
                    result.setResultsRecognition(recogs);
                }


            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return result;
    }

    public boolean hasError() {
        return error != ERROR_NONE;
    }

    public boolean isFinalResult() {
        return "final_result".equals(resultType);
    }


    public boolean isPartialResult() {
        return "partial_result".equals(resultType);
    }

    public boolean isNluResult() {
        return "nlu_result".equals(resultType);
    }

    public String getOrigalJson() {
        return origalJson;
    }

    public void setOrigalJson(String origalJson) {
        this.origalJson = origalJson;
    }

    public String[] getResultsRecognition() {
        return resultsRecognition;
    }

    public void setResultsRecognition(String[] resultsRecognition) {
        this.resultsRecognition = resultsRecognition;
    }

    public String getSn() {
        return sn;
    }

    public void setSn(String sn) {
        this.sn = sn;
    }

    public int getError() {
        return error;
    }

    public void setError(int error) {
        this.error = error;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getOrigalResult() {
        return origalResult;
    }

    public void setOrigalResult(String origalResult) {
        this.origalResult = origalResult;
    }

    public String getResultType() {
        return resultType;
    }

    public void setResultType(String resultType) {
        this.resultType = resultType;
    }

    public int getSubError() {
        return subError;
    }

    public void setSubError(int subError) {
        this.subError = subError;
    }
}

c#语音识别与合成

阅读数 1799

没有更多推荐了,返回首页