2017-07-05 16:10:35 Jerry_CSDN_YZR 阅读数 7773
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5905 人正在学习 去看看 杨波

基于科大讯飞的语音识别 windows平台开发

 

 

最近,在做一个关于语音识别的项目,并将语音识别应用于UE4

还好,上个学期的树莓派大作业,有了相关的接触,心里有点底,做总能做出来的

就是时间周期的问题,

终于,三天打鱼两天晒网,在一个星期内把它做出来了

总结:百度是个好东西,不过必应更好

 

我实现的这个功能还是比较基础的,无非就是:

录音 -> 语音识别 ->数据库 -> 语音合成 -> 播放

 

软件需求:

科大讯飞在线SDK , VS2015 , MySQL , 录音DirectX

 

录音:

 

录音是用DirectX

这个软件的话可以去网上下载,都有的,教程也有,我就不多飞口舌了

 

这个的教程,我写在这里:

http://blog.csdn.net/jerry_csdn_yzr/article/details/74451437

 

wav文件会生成在D:\workspace(VS)\dididi\dididi\bin\Debug里面 , 自己可以去找找看

 

 

语音识别:

 

语音合成:

 

可以到官方下载SDK , 按照它的步骤来一般都是可以执行的


 

这个简单的嘛,重点是要去看懂它的代码

那么多的函数怎么看?mmp,一个都不认识

 

可以看看官方给的API,慢慢来,我都看了挺久的

这里可以下载:

http://download.csdn.net/detail/jerry_csdn_yzr/9889554

不收你们钱

 

一些官方的参数可以在下载下来的SDK中找到,doc文档里面有!!!


 

 

然后就是它的语法,

这就得你自己学习了,不多不多,也就十几页

 

科大讯飞ABNF文法规范

 http://download.csdn.net/detail/jerry_csdn_yzr/9889560

 

数据库:

 

http://blog.csdn.net/grand910616/article/details/50197859

 

可以自己看看,怎么连的

 

 

 

这个评论是关键!!!

 

 

播放:

 

这个简单的嘛

上代码:

 

 

#include
#include
#include
#pragma comment(lib, "WINMM.LIB")
int main()
{
	printf("the answer of your question , and it will be shown as a wav:\n");
	PlaySound(TEXT("yzr1.wav"), 0, SND_FILENAME | SND_ASYNC);
	
	system("pause");

	return 0;
}

 

 

部分源代码:

/*
* 语音合成(Text To Speech,TTS)技术能够自动将任意文字实时转换为连续的
* 自然语音,是一种能够在任何时间、任何地点,向任何人提供语音信息服务的
* 高效便捷手段,非常符合信息时代海量数据、动态更新和个性化查询的需求。
*/

#include 
#include 
#include 
#include 
#include 

#include "qtts.h"
#include "msp_cmn.h"
#include "msp_errors.h"

#ifdef _WIN64
#pragma comment(lib,"../libs/msc_x64.lib")//x64
#else
#pragma comment(lib,"../libs/msc.lib")//x86
#endif

/* wav音频头部格式 */
typedef struct _wave_pcm_hdr
{
	char            riff[4];                // = "RIFF"
	int				size_8;                 // = FileSize - 8
	char            wave[4];                // = "WAVE"
	char            fmt[4];                 // = "fmt "
	int				fmt_size;				// = 下一个结构体的大小 : 16

	short int       format_tag;             // = PCM : 1
	short int       channels;               // = 通道数 : 1
	int				samples_per_sec;        // = 采样率 : 8000 | 6000 | 11025 | 16000
	int				avg_bytes_per_sec;      // = 每秒字节数 : samples_per_sec * bits_per_sample / 8
	short int       block_align;            // = 每采样点字节数 : wBitsPerSample / 8
	short int       bits_per_sample;        // = 量化比特数: 8 | 16

	char            data[4];                // = "data";
	int				data_size;              // = 纯数据长度 : FileSize - 44 
} wave_pcm_hdr;

/* 默认wav音频头部数据 */
wave_pcm_hdr default_wav_hdr =
{
	{ 'R', 'I', 'F', 'F' },
	0,
	{ 'W', 'A', 'V', 'E' },
	{ 'f', 'm', 't', ' ' },
	16,
	1,
	1,
	16000,
	32000,
	2,
	16,
	{ 'd', 'a', 't', 'a' },
	0
};
/* 文本合成 */
int text_to_speech(const char* src_text, const char* des_path, const char* params)
{
	int          ret = -1;
	FILE*        fp = NULL;
	const char*  sessionID = NULL;
	unsigned int audio_len = 0;
	wave_pcm_hdr wav_hdr = default_wav_hdr;
	int          synth_status = MSP_TTS_FLAG_STILL_HAVE_DATA;

	if (NULL == src_text || NULL == des_path)
	{
		printf("params is error!\n");
		return ret;
	}
	fp = fopen(des_path, "wb");
	if (NULL == fp)
	{
		printf("open %s error.\n", des_path);
		return ret;
	}
	/* 开始合成 */
	sessionID = QTTSSessionBegin(params, &ret);
	if (MSP_SUCCESS != ret)
	{
		printf("QTTSSessionBegin failed, error code: %d.\n", ret);
		fclose(fp);
		return ret;
	}
	ret = QTTSTextPut(sessionID, src_text, (unsigned int)strlen(src_text), NULL);
	if (MSP_SUCCESS != ret)
	{
		printf("QTTSTextPut failed, error code: %d.\n", ret);
		QTTSSessionEnd(sessionID, "TextPutError");
		fclose(fp);
		return ret;
	}
	printf("正在合成 ...\n");
	fwrite(&wav_hdr, sizeof(wav_hdr), 1, fp); //添加wav音频头,使用采样率为16000
	while (1)
	{
		/* 获取合成音频 */
		const void* data = QTTSAudioGet(sessionID, &audio_len, &synth_status, &ret);
		if (MSP_SUCCESS != ret)
			break;
		if (NULL != data)
		{
			fwrite(data, audio_len, 1, fp);
			wav_hdr.data_size += audio_len; //计算data_size大小
		}
		if (MSP_TTS_FLAG_DATA_END == synth_status)
			break;
		printf(">");
		Sleep(150); //防止频繁占用CPU
	}
	printf("\n");
	if (MSP_SUCCESS != ret)
	{
		printf("QTTSAudioGet failed, error code: %d.\n", ret);
		QTTSSessionEnd(sessionID, "AudioGetError");
		fclose(fp);
		return ret;
	}
	/* 修正wav文件头数据的大小 */
	wav_hdr.size_8 += wav_hdr.data_size + (sizeof(wav_hdr) - 8);

	/* 将修正过的数据写回文件头部,音频文件为wav格式 */
	fseek(fp, 4, 0);
	fwrite(&wav_hdr.size_8, sizeof(wav_hdr.size_8), 1, fp); //写入size_8的值
	fseek(fp, 40, 0); //将文件指针偏移到存储data_size值的位置
	fwrite(&wav_hdr.data_size, sizeof(wav_hdr.data_size), 1, fp); //写入data_size的值
	fclose(fp);
	fp = NULL;
	/* 合成完毕 */
	ret = QTTSSessionEnd(sessionID, "Normal");
	if (MSP_SUCCESS != ret)
	{
		printf("QTTSSessionEnd failed, error code: %d.\n", ret);
	}

	return ret;
}

int main(int argc, char* argv[])
{
	int         ret = MSP_SUCCESS;
	const char* login_params = "appid = 594be451, work_dir = .";//登录参数,appid与msc库绑定,请勿随意改动
																/*
																* rdn:           合成音频数字发音方式
																* volume:        合成音频的音量
																* pitch:         合成音频的音调
																* speed:         合成音频对应的语速
																* voice_name:    合成发音人
																* sample_rate:   合成音频采样率
																* text_encoding: 合成文本编码格式
																*
																*/
	const char* session_begin_params = "voice_name = babyxu, text_encoding = gb2312, sample_rate = 16000, speed = 50, volume = 50, pitch = 50, rdn = 2";
	const char* filename = "yzr1.wav"; //合成的语音文件名称
	const char* text = "房子价格"; //合成文本
																							 /* 用户登录 */
	ret = MSPLogin(NULL, NULL, login_params); //第一个参数是用户名,第二个参数是密码,第三个参数是登录参数,用户名和密码可在http://www.xfyun.cn注册获取
	if (MSP_SUCCESS != ret)
	{
		printf("MSPLogin failed, error code: %d.\n", ret);
		goto exit;//登录失败,退出登录
	}

	printf("\n###########################################################################\n");
	printf("## 语音合成(Text To Speech,TTS)技术能够自动将任意文字实时转换为连续的 ##\n");
	printf("## 自然语音,是一种能够在任何时间、任何地点,向任何人提供语音信息服务的  ##\n");
	printf("## 高效便捷手段,非常符合信息时代海量数据、动态更新和个性化查询的需求。  ##\n");
	printf("###########################################################################\n\n");

	/* 文本合成 */
	printf("开始合成 ...\n");
	ret = text_to_speech(text, filename, session_begin_params);
	if (MSP_SUCCESS != ret)
	{
		printf("text_to_speech failed, error code: %d.\n", ret);
	}
	printf("合成完毕\n");

exit:
	printf("按任意键退出 ...\n");
	_getch();
	MSPLogout(); //退出登录

	return 0;
}




 

2017-04-05 15:11:39 qq_38125123 阅读数 18212
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5905 人正在学习 去看看 杨波

1、概述

   通过微信小程序wx.startRecord()和wx.stopRecord()接口录音并上传silk录音文件至服务器,通过ffmpeg将silk录音文件转成wav录音文件,再通过百度语音识别 REST API 获取语音识别后的结果。

2、代码实现

   录音和语音文件上传


   node.js服务端接收语音文件代码

   silk文件转wav文件

   我使用的是silk-v3-decoder将silk文件转wav文件


silk-v3-decoder 使用方法


   百度语音识别 REST API识别wav文件

1、通过API Key和Secret Key获取的access_token


通过API Key和Secret Key获取的access_token文档


2、通过token 调用百度语音识别 REST API识别接口


3、语音识别优化

   通过上述操作后,发现识别的内容和实际内容差别很大


百度语音识别 REST API文档

   查看文档可知:采样率:8000/16000 仅支持单通道

   在ffmpeg里对应的设置方式分别是:

   -ar rate 设置采样率

   -ac channels 设置声道数

   修改converter.sh文件,修改为下图所示


修改后的converter.sh文件

2016-07-07 08:46:56 guchuanhang 阅读数 6882
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5905 人正在学习 去看看 杨波

高德地图官方导航部分Demo使用android sdk 24编译,执行会崩溃。经过和高德工程师的交涉得知,地图中使用了科大讯飞的语音模块,崩溃的就是语音部分。探究一下科大讯飞语音识别,在此记录一下成长点滴!
这里使用的是科大讯飞

科大讯飞API提供的功能

  • 语音合成

    将一段文字转换为成语音,可根据需要合成出不同音色、语速和语调的声音,让机器像人一样开口说话。

  • 语音听写

    将一段语音转换成文本,把语音中包含文字信息提取出来,并可以优先识别用户手机特有的联系人和个性化数据。

  • 语法识别

    判断用户所说的内容是否与预定义的语法相符合, 主要用于识别用户是否下达某项指令,使用语法识别前,需要先定义语法。

  • 语义理解

    在语音听写基础上,分析理解用户的说话意图,返回结构化的指令信息。开发者可在语义开放平台定义专属的问答格式。

  • 语音评测

    通过智能语音技术自动对发音水平进行评价,给出用户综合得分和发音信息。

  • 声纹密码

    据语音波形反映说话人生理和行为特征的语音参数,自动识别说话人身份,声纹识别所提供的安全性可与其他生物识别技术(指纹、掌形和虹膜)相媲美。

  • 人脸识别

    基于人的脸部特征信息进行身份识别的一种生物识别技术,可以自动在图像中检测和跟踪人脸,进而对检测到的人脸进行检测和验证。系统同时支持人脸关键点检出、视频流人脸检测等功能,识别率高达 99%。

由于时间和能力限制,这里仅仅对语音听写&&语音合成中的云服务部分进行简单探究

环境搭建

讯飞官网,申请一个开发者账号,创建一个应用,下载相应的sdk,添加相关的jar和so文件。
1.在Application中完成讯飞模块的初始化

 @Override
    public void onCreate() {
        super.onCreate();
        // 将“12345678”替换成您申请的 APPID
// 请勿在“ =” 与 appid 之间添加任务空字符或者转义符
SpeechUtility.createUtility(context, SpeechConstant.APPID +"=12345678");
        SpeechUtility.createUtility(this, SpeechConstant.APPID +"=12345678");
    }

2.添加相应的权限

  <!--连接网络权限,用于执行云端语音能力 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <!--读取网络信息状态 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!--获取当前wifi状态 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!--允许程序改变网络连接状态 -->
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <!--读取手机信息权限 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <!--读取联系人权限,上传联系人需要用到此权限 -->
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <!--外存储写权限, 构建语法需要用到此权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!--外存储读权限,构建语法需要用到此权限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!--配置权限,用来记录应用配置信息 -->
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />

    <!--摄相头权限, 拍照需要用到 -->
    <uses-permission android:name="android.permission.CAMERA" />

语音合成

就是将文本读出来
使用的布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
    <!--activity_text2speech.xml-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:paddingLeft="10dp"
    android:paddingRight="10dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="讯飞合成示例"
        android:textSize="30sp" />

    <EditText
        android:id="@+id/tts_text"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="top|left"
        android:text="科大讯飞作为中国最大的智能语音技术提供商,在智能语音技术领域有着长期的研究积累,并在中文语音合成、语音识别、
    口语评测等多项技术上拥有国际领先的成果。科大讯飞是我国唯一以语音技术为产业化方向的“国家863计划成果产业化基地”…"
        android:textSize="20sp" />


    <Button
        android:id="@+id/tts_play"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始合成"
        android:textSize="20sp" />

</LinearLayout>

java代码如下:

package com.iflytek.voicedemo;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.EditText;
import android.widget.Toast;

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SynthesizerListener;

public class Text2SpeechActivity extends Activity implements OnClickListener {
    // 语音合成对象
    private SpeechSynthesizer mTts;
    private Toast mToast;

    @SuppressLint("ShowToast")
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_text2speech);

        findViewById(R.id.tts_play).setOnClickListener(this);
        // 初始化合成对象
        mTts = SpeechSynthesizer.createSynthesizer(this, null);

        mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
        applyPermission();
    }

    //获取权限,将语音保存到sd卡
    private void applyPermission() {
        ActivityCompat.requestPermissions(this, new String[]{
                Manifest.permission.READ_EXTERNAL_STORAGE
        }, 12);

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            // 开始合成
            // 收到onCompleted 回调时,合成结束、生成合成音频
            // 合成的音频格式:只支持pcm格式
            case R.id.tts_play: {
                String text = ((EditText) findViewById(R.id.tts_text)).getText().toString();
                // 设置参数
                setParam();
                int code = mTts.startSpeaking(text, mTtsListener);
//          /** 
//           * 只保存音频不进行播放接口,调用此接口请注释startSpeaking接口
//           * text:要合成的文本,uri:需要保存的音频全路径,listener:回调接口
//          */
//          String path = Environment.getExternalStorageDirectory()+"/tts.pcm";
//          int code = mTts.synthesizeToUri(text, path, mTtsListener);
                if (code != ErrorCode.SUCCESS) {
                    showTip("语音合成失败,错误码: " + code);
                }
            }
            break;
        }

    }

    /**
     * 合成回调监听。
     */
    private SynthesizerListener mTtsListener = new SynthesizerListener() {

        @Override
        public void onSpeakBegin() {
            showTip("开始播放");
        }

        @Override
        public void onSpeakPaused() {
            showTip("暂停播放");
        }

        @Override
        public void onSpeakResumed() {
            showTip("继续播放");
        }

        @Override
        public void onBufferProgress(int percent, int beginPos, int endPos,
                                     String info) {
            // 合成进度
        }

        @Override
        public void onSpeakProgress(int percent, int beginPos, int endPos) {
            // 播放进度
        }

        @Override
        public void onCompleted(SpeechError error) {
            if (error == null) {
                showTip("播放完成");
            } else if (error != null) {
                showTip(error.getPlainDescription(true));
            }
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
            // 若使用本地能力,会话id为null
 // if (SpeechEvent.EVENT_SESSION_ID == eventType) {
//      String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
            //      Log.d(TAG, "session id =" + sid);
            //  }
        }
    };

    private void showTip(final String str) {
        mToast.setText(str);
        mToast.show();
    }

    /**
     * 参数设置
     *
     * @return
     */
    private void setParam() {
        // 清空参数
        mTts.setParameter(SpeechConstant.PARAMS, null);
        // 根据合成引擎设置相应参数
        mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
        // 设置在线合成发音人
        mTts.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");
        //设置合成语速
        mTts.setParameter(SpeechConstant.SPEED,
                "50");
        //设置合成音调
        mTts.setParameter(SpeechConstant.PITCH, "50");
        //设置合成音量
        mTts.setParameter(SpeechConstant.VOLUME,
                "50");
        //设置播放器音频流类型
        mTts.setParameter(SpeechConstant.STREAM_TYPE,
                "3");
        // 设置播放合成音频打断音乐播放,默认为true
        mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");

        // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
        mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/tts.wav");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mTts.stopSpeaking();
        // 退出时释放连接
        mTts.destroy();
    }

}

使用官方封装的UI,进行语音听写

为了便于开发者调用,讯飞封装了一套用于语音输入的UI。在使用之前需要将官方Demo中的assets目录下的iflytek放到你的项目的assets目录下。其内容如下:

这里写图片描述
展示界面的布局文件

<?xml version="1.0" encoding="utf-8"?>
    <!--activity_speech2text_ui.xml-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:paddingLeft="10dp"
    android:paddingRight="10dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="讯飞听写示例"
        android:textSize="30sp" />

    <EditText
        android:id="@+id/iat_text"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="top|left"
        android:paddingBottom="20dp"
        android:textSize="20sp" />

    <Button
        android:id="@+id/iat_recognize"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始"
        android:textSize="20sp" />

</LinearLayout>

java代码:

package com.iflytek.voicedemo;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.EditText;
import android.widget.Toast;

import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;
import com.iflytek.speech.util.JsonParser;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.LinkedHashMap;

public class Speech2TextUIActivity extends Activity implements OnClickListener {
    private static String TAG = Speech2TextUIActivity.class.getSimpleName();
    // 语音听写UI
    private RecognizerDialog mIatDialog;
    // 用HashMap存储听写结果
    private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();

    private EditText mResultText;
    private Toast mToast;

    @SuppressLint("ShowToast")
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_speech2text_ui);

        findViewById(R.id.iat_recognize).setOnClickListener(this);
        // 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer
        // 使用UI听写功能,放置布局文件和图片资源
        //使用云服务InitListener参数写成null
        mIatDialog = new RecognizerDialog(this, null);

        mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
        mResultText = ((EditText) findViewById(R.id.iat_text));
        applyPermission();
    }

    private void applyPermission() {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, 12);

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            // 开始听写
            // 如何判断一次听写结束:OnResult isLast=true 或者 onError
            case R.id.iat_recognize:
                mResultText.setText(null);// 清空显示内容
                mIatResults.clear();
                // 显示听写对话框
                mIatDialog.setListener(mRecognizerDialogListener);
                mIatDialog.show();
                showTip("请开始说话…");
                break;
            default:
                break;
        }
    }


    private void printResult(RecognizerResult results) {
        String text = JsonParser.parseIatResult(results.getResultString());

        String sn = null;
        // 读取json结果中的sn字段
        try {
            JSONObject resultJson = new JSONObject(results.getResultString());
            sn = resultJson.optString("sn");
        } catch (JSONException e) {
            e.printStackTrace();
        }

        mIatResults.put(sn, text);

        StringBuffer resultBuffer = new StringBuffer();
        for (String key : mIatResults.keySet()) {
            resultBuffer.append(mIatResults.get(key));
        }

        mResultText.setText(resultBuffer.toString());
        mResultText.setSelection(mResultText.length());
    }

    /**
     * 听写UI监听器
     */
    private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {
        public void onResult(RecognizerResult results, boolean isLast) {
            printResult(results);
        }

        /**
         * 识别回调错误.
         */
        public void onError(SpeechError error) {
            showTip(error.getPlainDescription(true));
        }

    };


    private void showTip(final String str) {
        mToast.setText(str);
        mToast.show();
    }

}

解释服务器返回数据,用到的工具类

package com.iflytek.speech.util;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;

import android.util.Log;

/**
 * Json结果解析类
 */
public class JsonParser {

    public static String parseIatResult(String json) {
        StringBuffer ret = new StringBuffer();
        try {
            JSONObject joResult = new JSONObject(json);

            JSONArray words = joResult.getJSONArray("ws");
            for (int i = 0; i < words.length(); i++) {
                // 转写结果词,默认使用第一个结果
                JSONArray items = words.getJSONObject(i).getJSONArray("cw");
                JSONObject obj = items.getJSONObject(0);
                ret.append(obj.getString("w"));
//              如果需要多候选结果,解析数组其他字段
//              for(int j = 0; j < items.length(); j++)
//              {
//                  JSONObject obj = items.getJSONObject(j);
//                  ret.append(obj.getString("w"));
//              }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return ret.toString();
    }

    public static String parseGrammarResult(String json) {
        StringBuffer ret = new StringBuffer();
        try {
            JSONTokener tokener = new JSONTokener(json);
            JSONObject joResult = new JSONObject(tokener);

            JSONArray words = joResult.getJSONArray("ws");
            for (int i = 0; i < words.length(); i++) {
                JSONArray items = words.getJSONObject(i).getJSONArray("cw");
                for(int j = 0; j < items.length(); j++)
                {
                    JSONObject obj = items.getJSONObject(j);
                    if(obj.getString("w").contains("nomatch"))
                    {
                        ret.append("没有匹配结果.");
                        return ret.toString();
                    }
                    ret.append("【结果】" + obj.getString("w"));
                    ret.append("【置信度】" + obj.getInt("sc"));
                    ret.append("\n");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            ret.append("没有匹配结果.");
        } 
        return ret.toString();
    }

    public static String parseLocalGrammarResult(String json) {
        StringBuffer ret = new StringBuffer();
        try {
            JSONTokener tokener = new JSONTokener(json);
            JSONObject joResult = new JSONObject(tokener);

            JSONArray words = joResult.getJSONArray("ws");
            for (int i = 0; i < words.length(); i++) {
                JSONArray items = words.getJSONObject(i).getJSONArray("cw");
                for(int j = 0; j < items.length(); j++)
                {
                    JSONObject obj = items.getJSONObject(j);
                    if(obj.getString("w").contains("nomatch"))
                    {
                        ret.append("没有匹配结果.");
                        return ret.toString();
                    }
                    ret.append("【结果】" + obj.getString("w"));
                    ret.append("\n");
                }
            }
            ret.append("【置信度】" + joResult.optInt("sc"));

        } catch (Exception e) {
            e.printStackTrace();
            ret.append("没有匹配结果.");
        } 
        return ret.toString();
    }
}

这里写图片描述
官方定制的UI还是挺漂亮的!

不使用官方UI控件进行语音听写

使用到的布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
    <!--activity_speech2text.xml-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:paddingLeft="10dp"
    android:paddingRight="10dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="讯飞听写示例"
        android:textSize="30sp" />

    <EditText
        android:id="@+id/iat_text"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="top|left"
        android:paddingBottom="20dp"
        android:textSize="20sp" />


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="2dp"
        android:layout_marginTop="10dp"
        android:gravity="center_horizontal"
        android:orientation="horizontal">

        <Button
            android:id="@+id/iat_recognize"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="开始"
            android:textSize="20sp" />

        <Button
            android:id="@+id/iat_stop"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="停止"
            android:textSize="20sp" />

        <Button
            android:id="@+id/iat_cancel"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="取消"
            android:textSize="20sp" />
    </LinearLayout>

</LinearLayout>

java代码:

package com.iflytek.voicedemo;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.EditText;
import android.widget.Toast;

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.speech.util.JsonParser;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.LinkedHashMap;

public class Speech2TextActivity extends Activity implements OnClickListener {
    private static String TAG = Speech2TextActivity.class.getSimpleName();
    // 语音听写对象
    private SpeechRecognizer mIat;
    // 用HashMap存储听写结果
    private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();

    private EditText mResultText;
    private Toast mToast;

    @SuppressLint("ShowToast")
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_speech2text);

        findViewById(R.id.iat_recognize).setOnClickListener(Speech2TextActivity.this);
        findViewById(R.id.iat_stop).setOnClickListener(Speech2TextActivity.this);
        findViewById(R.id.iat_cancel).setOnClickListener(Speech2TextActivity.this);
        mIat = SpeechRecognizer.createRecognizer(this, null);

        mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
        mResultText = ((EditText) findViewById(R.id.iat_text));
        applyPermission();
    }

    private void applyPermission() {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, 12);

    }

    int ret = 0; // 函数调用返回值

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            // 开始听写
            // 如何判断一次听写结束:OnResult isLast=true 或者 onError
            case R.id.iat_recognize:
                mResultText.setText(null);// 清空显示内容
                mIatResults.clear();
                // 设置参数
                setParam();
                ret = mIat.startListening(mRecognizerListener);
                if (ret != ErrorCode.SUCCESS) {
                    showTip("听写失败,错误码:" + ret);
                }
                break;
            case R.id.iat_stop:
                mIat.stopListening();
                showTip("停止听写");
                break;
            case R.id.iat_cancel:
                mIat.cancel();
                showTip("取消听写");
                break;
            default:
                break;
        }
    }


    /**
     * 听写监听器。
     */
    private RecognizerListener mRecognizerListener = new RecognizerListener() {

        @Override
        public void onBeginOfSpeech() {
            // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
            showTip("开始说话");
        }

        @Override
        public void onError(SpeechError error) {
            // Tips:
            // 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
            // 如果使用本地功能(语记)需要提示用户开启语记的录音权限。
            showTip(error.getPlainDescription(true));
        }

        @Override
        public void onEndOfSpeech() {
            // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
            showTip("结束说话");
        }

        @Override
        public void onResult(RecognizerResult results, boolean isLast) {
            Log.d(TAG, results.getResultString());
            printResult(results);
        }

        @Override
        public void onVolumeChanged(int volume, byte[] data) {
            showTip("当前正在说话,音量大小:" + volume);
            Log.d(TAG, "返回音频数据:" + data.length);
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
            // 若使用本地能力,会话id为null
            //  if (SpeechEvent.EVENT_SESSION_ID == eventType) {
            //      String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
            //      Log.d(TAG, "session id =" + sid);
            //  }
        }
    };

    private void printResult(RecognizerResult results) {
        String text = JsonParser.parseIatResult(results.getResultString());

        String sn = null;
        // 读取json结果中的sn字段
        try {
            JSONObject resultJson = new JSONObject(results.getResultString());
            sn = resultJson.optString("sn");
        } catch (JSONException e) {
            e.printStackTrace();
        }

        mIatResults.put(sn, text);

        StringBuffer resultBuffer = new StringBuffer();
        for (String key : mIatResults.keySet()) {
            resultBuffer.append(mIatResults.get(key));
        }

        mResultText.setText(resultBuffer.toString());
        mResultText.setSelection(mResultText.length());
    }


    private void showTip(final String str) {
        mToast.setText(str);
        mToast.show();
    }

    /**
     * 参数设置
     */
    public void setParam() {
        // 清空参数
        mIat.setParameter(SpeechConstant.PARAMS, null);
        // 设置听写引擎
        mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
        // 设置返回结果格式
        mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");

        // 设置语言
        mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
        // 设置语言区域
        mIat.setParameter(SpeechConstant.ACCENT, "mandarin");

        // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
        mIat.setParameter(SpeechConstant.VAD_BOS, "4000");

        // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
        mIat.setParameter(SpeechConstant.VAD_EOS, "1000");

        // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
        mIat.setParameter(SpeechConstant.ASR_PTT, "1");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 退出时释放连接
        mIat.cancel();
        mIat.destroy();
    }

}
2016-12-27 11:04:56 weixin_36429334 阅读数 6193
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5905 人正在学习 去看看 杨波

1,首先打开百度语音识别官网,注册一个账户成为开发者,接着创建一个应用,下载百度提供源代码 。

下载地址: http://yuyin.baidu.com/sdk/
官方文档地址:http://yuyin.baidu.com/docs/asr/54

sdk下载

下载demo

2,打开源代码,进行配置参数或修改要识别的语言文件

demo1

<?php 
define('AUDIO_FILE', "./text2audio_1.wav"); //语音文件地址,值支持本地

$url = "http://vop.baidu.com/server_api";

//put your params here
$cuid = "";
$apiKey = "";
$secretKey = "";

$auth_url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=".$apiKey."&client_secret=".$secretKey;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $auth_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
$response = curl_exec($ch);
if(curl_errno($ch))
{
    print curl_error($ch);
}
curl_close($ch);
$response = json_decode($response, true);
$token = $response['access_token'];

$audio = file_get_contents(AUDIO_FILE);
$base_data = base64_encode($audio);
$array = array(
        "format" => "wav",
        "rate" => 8000,
        "channel" => 1,
//        "lan" => "zh",
        "token" => $token,
        "cuid"=> $cuid,
        //"url" => "http://www.xxx.com/sample.pcm",
        //"callback" => "http://www.xxx.com/audio/callback",
        "len" => filesize(AUDIO_FILE),
        "speech" => $base_data,
        );
$json_array = json_encode($array);
$content_len = "Content-Length: ".strlen($json_array);
$header = array ($content_len, 'Content-Type: application/json; charset=utf-8');

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_array);
$response = curl_exec($ch);
if(curl_errno($ch))
{
    print curl_error($ch);
}
curl_close($ch);
echo $response;
$response = json_decode($response, true);
var_dump($response);

demo2


define('AUDIO_FILE', "./text.wav");

//put your params here
$cuid = "";
$apiKey = "";
$secretKey = "";

$auth_url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=".$apiKey."&client_secret=".$secretKey;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $auth_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
$response = curl_exec($ch);
if(curl_errno($ch))
{
    print curl_error($ch);
}
curl_close($ch);
$response = json_decode($response, true);
$token = $response['access_token'];

$url = "http://vop.baidu.com/server_api?cuid=".$cuid."&token=".$token;
$url = $url."&lan=zh";
$audio = file_get_contents(AUDIO_FILE);
$content_len = "Content-Length: ".strlen($audio);
$header = array ($content_len,'Content-Type: audio/pcm; rate=8000',);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_POSTFIELDS, $audio);
$response = curl_exec($ch);
if(curl_errno($ch))
{
    print curl_error($ch);
}
curl_close($ch);
echo $response;
$response = json_decode($response, true);
echo '<pre>';
var_dump($response);

3、运行文件识别,运行后发现调取接口成功,但是识别出来的正确率百分之一都不到,于是查看原因发现,百度语音识别只支持 8k/16k 采样率 16bit 位深的单声道语音,进行音频格式转换后正确率可达成80% 。

注意事项:
语音识别接口支持 POST 方式
目前 API 仅支持整段语音识别的模式,即需要上传整段语音进行识别
语音数据上传方式有两种:隐示发送和显示发送
原始语音的录音格式目前只支持评测 8k/16k 采样率 16bit 位深的单声道语音
压缩格式支持:pcm(不压缩)、wav、opus、speex、amr、x-flac
系统支持语言种类:中文(zh)、粤语(ct)、英文(en)

4、因为是调用接口测试所以在转换音频格式使用的是格式工厂,如果项目需要可使用代码自动转换(自行百度)

这里写图片描述

这里写图片描述

这里写图片描述

然后进行确认转换得出来的格式再进行测试即可,谢谢~

2019-08-23 14:41:13 u011560555 阅读数 116
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5905 人正在学习 去看看 杨波

最近研究了一下百度云AI,和科大讯飞、阿里、腾讯,各大公司都提供了全面的ai接口和文档,对一位入门或者初学者来说挺好的,如果想深入研究的还可以直接翻源码学习。这里就简单写了一个语音识别的功能。后面会不断更新人脸识别等相关ai方面的东西。

首先,上百度云注册账号,然后再“人工智能”-“语音识别”下创建一个自己的应用,创建完后会得到,APPID,APIKEY,SERET KEY, 这几个熟悉对于一个经常写接口的人都应该会知道,是用来获取百度ai提供的token的,然后通过token才能方位百度云AI上面的相关接口。

在这里插入图片描述

接着,创建完用户后,就可以左边的下拉菜单中查找对应的技术文档,和下载SDK。
在这里插入图片描述

SDK,地址https://github.com/Baidu-AIP/java-sdk,目前版本是 4.8.0最新的,里面有相关源码。

继续,阅读完技术文档后,开始写demo,本人使用eclipse,创建maven项目,然后pom
文件引入百度ai包,

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
	    <groupId>com.baidu.aip</groupId>
	    <artifactId>java-sdk</artifactId>
	    <version>4.8.0</version>
	</dependency>
    <dependency>
        <groupId>com.googlecode.soundlibs</groupId>
        <artifactId>mp3spi</artifactId>
        <version>1.9.5.4</version>
     </dependency>
  </dependencies>

然后,创建demo 代码;

package com.ai.asr.util;

import org.json.JSONException;
import org.json.JSONObject;

import com.baidu.aip.speech.AipSpeech;

public class Sample2 {
	//设置APPID/AK/SK
    public static final String APP_ID = "你的 ID";
    public static final String API_KEY = "你懂的";
    public static final String SECRET_KEY = "你的";
    private static final String testFileName = "C:\\Users\\johndgj\\Desktop\\20190101学习记录表\\test.pcm"; // 百度语音提供技术支持

    public static void main(String[] args) {
        // 初始化一个AipSpeech
        AipSpeech client = new AipSpeech(APP_ID, API_KEY, SECRET_KEY);

        // 可选:设置网络连接参数
        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");

        // 调用接口
        JSONObject res = client.asr(testFileName, "pcm", 16000, null);
        try {
			System.out.println(res.toString(2));
		} catch (JSONException e) {
			e.printStackTrace();
		}
        
    }

}

最后,跑一下,完成了

{
  "corpus_no": "6728201278371111763",
  "err_msg": "success.",
  "err_no": 0,
  "result": ["北京科技馆。"],
  "sn": "285721224311566531434"
}

总结,这是比较简单的案例,想了解更深的,没有比研究源码更好的了。还有另外一个问题就是 现在的录音等文件都是 MP3,或MP4等其他格式的,要把这些转换成PCM文件,才能识别。后面会更新如果将MP3或其他文件转换为PCM,并进行识别。

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