2019-08-15 11:18:50 minthemir 阅读数 1338
  • micropython基础入门(esp32/esp8266单片机开发)

    micropython语法和python3一样,编写起来非常方便。如果你快速入门单片机玩物联网而且像轻松实现各种功能,那绝力推荐使用micropython。方便易懂易学。 同时如果你懂C语音,也可以用C写好函数并编译进micropython固件里然后进入micropython调用(非必须)。 能通过WIFI联网(2.1章),也能通过sim卡使用2G/3G/4G/5G联网(4.5章)。 为实现语音控制,本教程会教大家使用tensorflow利用神经网络训练自己的语音模型并应用。 为实现通过网页控制,本教程会教大家linux(debian10 nginx->uwsgi->python3->postgresql)网站前后台入门。 为记录单片机传输过来的数据, 本教程会教大家入门数据库。 本教程会通过通俗易懂的比喻来讲解各种原理与思路,并手把手编写程序来实现各项功能。 micropython版本是 2019年6月发布的1.11; 更多内容请看视频列表。 学习这门课程之前你需要至少掌握: 1: python3基础(变量, 循环, 函数, 常用库, 常用方法)。 本视频使用到的零件与淘宝上大致价格:     1: 超声波传感器(3)     2: MAX9814麦克风放大模块(8)     3: DHT22(15)     4: LED(0.1)     5: 8路5V低电平触发继电器(12)     6: HX1838红外接收模块(2)     7:红外发射管(0.1),HX1838红外接收板(1)     other: 电表, 排线, 面包板(2)*2,ESP32(28)

    668 人正在学习 去看看 陈恩棋
最近在学习如何应用API来实现语言交互系统的功能,所以打算写一篇文章来整理和记录自己了解API使用的过程。
有很多平台提供语音识别等功能的API,文章使用的是科大讯飞开发的API。

讯飞开放平台简介

本文所使用的资料和基础代码均来自科大讯飞的 讯飞开放平台开放平台论坛社区讯飞开放平台上提供了很多产品和项目解决方案,一些SDK以及基础使用方法。你只需注册一个账号(或进一步实名制来申请更多资源)就可获取一个APPID,就可以在一定的每日免费使用量下完成本文的demo。

讯飞开放平台
讯飞开放平台–论坛社区

SDK的下载

实际上讯飞开放平台提供的SDK会根据你的选中的功能自动生成一个包含你APPID的压缩包,里面会有已经实现你选中功能的例程sample的整个工程:
如果使用语音唤醒需要提前在控制台的页面内设置唤醒词,然后再下载SDK
在这里插入图片描述
平台已经提供了相关的文档来支持你跑动所有你可以下载到的例程,并且你的APPID已经设置到相应的文件里,你无需再自行修改(如果出现问题,可参照平台文档内流程设置或重新下载SDK)。本文默认认为你已经了解讯飞开放平台的基本使用方法因此这里就不再过多的提及。
由于文章写的是Windows平台的demo,所以在这里贴一个Windows下的API文档:

MSC for Windows&Linux API

文档里面详尽的提供了API文档应该提供的内容,但是如果之前没有相关经验或者和我一样是那种没有认真写过代码的CS本科生,那么你需要通过一定的实践和认真阅读代码来熟悉和理解。

Visual Studio工程

在这里插入图片描述
如你所见,压缩包里的工程已经整理好你所选中的所有功能,你可以每一个都把玩一下,看看他们运行起来的样子。这有助于理解API函数运行的逻辑,并给你提供一个设计应用的思路。
如你所见,官方提供的Windows\Linux平台API全部都是C语言编写,如果你要根据具体项目开发使用其他编程语言(或许可以使用WebAPI)。
同时,例程项目都是单独生成的,因此每一个功能的例程都是单独运行的。

离线语音识别

我实现的demo是通过本地离线命令词识别来进行语音识别,讯飞开放平台对这个原理的介绍如下:

语法(命令词)识别,是基于语法规则,将与语法一致的自然语言音频转换为文本输出的技术。语法识别的结果值域只在语法文件所列出的规则里,故有很好的匹配率,另外,语法识别结果携带了结果的置信度,应用可以根据置信分数,决定这个结果是否有效。语法识别多用于要更准确结果且有限说法的语音控制,如空调的语音控制等。在使用语法识别时,应用需要先编写一个语法文件,然后通过调用QISRBuildGrammar接口编译本地语法文件,以及获得语法ID,并在会话时,传入语法ID,以使用该语法。

后面我会在讲语法开发怎么做,首先要把拼凑出来的代码跑通。

主函数

int main(int argc, char* argv[])
{
	const char *login_config    = "appid = 123456789"; //登录参数,这里写你的APPID
	UserData asr_data; 
	int ret                    = 0 ;

	ret = MSPLogin(NULL, NULL, login_config); //第一个参数为用户名,第二个参数为密码,传NULL即可,第三个参数是登录参数
	if (MSP_SUCCESS != ret) {
		printf("登录失败:%d\n", ret);
		goto exit;
	}

	memset(&asr_data, 0, sizeof(UserData));
	printf("构建离线识别语法网络...\n");
	ret = build_grammar(&asr_data);  //第一次使用某语法进行识别,需要先构建语法网络,获取语法ID,之后使用此语法进行识别,无需再次构建
	if (MSP_SUCCESS != ret) {
		printf("构建语法调用失败!\n");
		goto exit;
	}
	while (1 != asr_data.build_fini)
		_sleep(300);
	if (MSP_SUCCESS != asr_data.errcode)
		goto exit;
	printf("离线识别语法网络构建完成,开始识别...\n");	
	ret = run_asr(&asr_data);		//执行封装好的语音识别函数
	if (MSP_SUCCESS != ret) {
		printf("离线语法识别出错: %d \n", ret);
		goto exit;
	}

	printf("请按任意键继续\n");
	_getch();
	printf("更新离线语法词典...\n");
	ret = update_lexicon(&asr_data);  //当语法词典槽中的词条需要更新时,调用QISRUpdateLexicon接口完成更新
	if (MSP_SUCCESS != ret) {
		printf("更新词典调用失败!\n");
		goto exit;
	}
	while (1 != asr_data.update_fini)
		_sleep(300);
	if (MSP_SUCCESS != asr_data.errcode)
		goto exit;
	printf("更新离线语法词典完成,开始识别...\n");
	ret = run_asr(&asr_data);
	if (MSP_SUCCESS != ret) {
		printf("离线语法识别出错: %d \n", ret);
		goto exit;
	}

exit:
	MSPLogout();
	printf("请按任意键退出...\n");
	_getch();
	return 0;
}

API提供的函数,几乎所有的函数返回值都是通过宏定义的错误码,而这个错误码可以在官方的查询链接里查询:
错误码查询–讯飞开放平台
对于错误码的及时和解决方法都说的比较笼统,如果你跟我一样缺乏相关经验,估计要花时间来猜测分析错误的原因。

run_asr运行整套流程:

int run_asr(UserData *udata)
{
	char asr_params[MAX_PARAMS_LEN]    = {NULL};
	//离线唤醒的参数设置
	const char *ssb_param = "ivw_threshold=0:1450,sst=wakeup,ivw_res_path =fo|res/ivw/wakeupresource.jet";
	const char *rec_rslt               = NULL;
	const char *session_id             = NULL;
	const char *asr_audiof             = NULL;
	FILE *f_pcm                        = NULL;
	char *pcm_data                     = NULL;
	long pcm_count                     = 0;
	long pcm_size                      = 0;
	int last_audio                     = 0;
	int aud_stat                       = MSP_AUDIO_SAMPLE_CONTINUE;
	int ep_status                      = MSP_EP_LOOKING_FOR_SPEECH;
	int rec_status                     = MSP_REC_STATUS_INCOMPLETE;
	int rss_status                     = MSP_REC_STATUS_INCOMPLETE;
	int errcode                        = -1;
	int aud_src                        = 0;
	const char res[] = "id=\"001\"";
	//离线语法识别参数设置
	_snprintf(asr_params, MAX_PARAMS_LEN - 1, 
		"engine_type = local, \
		asr_res_path = %s, sample_rate = %d, \
		grm_build_path = %s, local_grammar = %s, \
		result_type = xml, result_encoding = GB2312,vad_eos=1000 ",
		ASR_RES_PATH,
		SAMPLE_RATE_16K,
		GRM_BUILD_PATH,
		udata->grammar_id
		);
	//printf("音频数据在哪? \n0: 从文件读入\n1:从MIC说话\n");
	//scanf("%d", &aud_src);
	
	//Getid(res);
	if(1) {
		while (1) //保持运行
		{
			printf("等待唤醒:\n");
			run_ivw(NULL, ssb_param);	//运行唤醒函数
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("你好!小恩正在听……\n");	
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
			run_asr_mic(asr_params);	//运行麦克风语音识别
		}
	} else {
		asr_audiof = get_audio_file();	//获取本地录音文件
		demo_file(asr_audiof, asr_params); 	//运行本地录音识别
	}
	return 0;
}

在原版的例程中是有一个函数是用本地录音进行语音识别,你也可以去掉或者保留用作调试。

唤醒功能的参数设置:

const char *ssb_param = "ivw_threshold=0:1450,\
sst=wakeup,\
ivw_res_path =fo|res/ivw/wakeupresource.jet";

识别功能的参数设置:

_snprintf(asr_params, MAX_PARAMS_LEN - 1, 
		"engine_type = local, \
		asr_res_path = %s, sample_rate = %d, \
		grm_build_path = %s, local_grammar = %s, \
		result_type = xml, result_encoding = GB2312,vad_eos=1000 ",
		ASR_RES_PATH,
		SAMPLE_RATE_16K,
		GRM_BUILD_PATH,
		udata->grammar_id
		);

我在这里将engine_type 参数设置为 local,表示我使用的是本地离线识别。
结果类型为XML类型,result_type = xml,结果编码为result_encoding = GB2312。你也可以设置为json或plain,但要注意更改encoding的类型
这里我增加了允许尾部静音的最长时间这个参数,vad_eos=1000,主要是根据我的需要,默认值为2000。(单位毫秒)

run_ivw运行唤醒:

//======================================================唤醒部分=====================================================
int awkeFlag = 0;	//唤醒状态flag,默认0未唤醒,1已换醒	
struct recorder *recorder;	//初始化录音对象
int record_state = MSP_AUDIO_SAMPLE_FIRST;	//初始化录音状态
int ISR_STATUS = 0;//oneshot专用,用来标识命令词识别结果是否已返回。

//唤醒状态消息提示,喂给回调函数QIVWRegisterNotify
int cb_ivw_msg_proc(const char *sessionID, int msg, int param1, int param2, const void *info, void *userData)
{
	if (MSP_IVW_MSG_ERROR == msg) //唤醒出错消息
	{
		//printf("\n\nMSP_IVW_MSG_ERROR errCode = %d\n\n", param1);
		printf("唤醒失败!");
		awkeFlag = 0;
	}
	else if (MSP_IVW_MSG_WAKEUP == msg) //唤醒成功消息
	{
		//printf("\n\nMSP_IVW_MSG_WAKEUP result = %s\n\n", info);
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("唤醒成功!");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
		awkeFlag = 1;		
	}
	
	return 0;
}

//读取录音内容的函数,用于喂给创建录音的函数create_recorder
static void iat_cb(char *data, unsigned long len, void *user_para)
{
	int errcode;
	int ret = 0;
	const char *session_id = (const char *)user_para;//初始化本次识别的句柄。
	//printf("进入录音读取");
	if (len == 0 || data == NULL)
		return;
	
	errcode = QIVWAudioWrite(session_id, (const void *)data, len, record_state);
	
	if (MSP_SUCCESS != errcode)
	{
		printf("QIVWAudioWrite failed! error code:%d\n", errcode);
		ret = stop_record(recorder);
		if (ret != 0) {
			printf("Stop failed! \n");
			//return -E_SR_RECORDFAIL;
		}
		wait_for_rec_stop(recorder, (unsigned int)-1);
		QIVWAudioWrite(session_id, NULL, 0, MSP_AUDIO_SAMPLE_LAST);
		record_state = MSP_AUDIO_SAMPLE_LAST;
		//g_is_awaken_succeed = FALSE;
	}
	if (record_state == MSP_AUDIO_SAMPLE_FIRST) {
		record_state = MSP_AUDIO_SAMPLE_CONTINUE;
	}
}

//运行唤醒的本体
void run_ivw(const char *grammar_list, const char* session_begin_params)//运行唤醒步骤
{
	const char *session_id = NULL;	
	int err_code = MSP_SUCCESS;
	WAVEFORMATEX wavfmt = DEFAULT_FORMAT;
	char sse_hints[128];	//用于设置结束时显示的信息
	int count = 0;
	
	//开始唤醒session
	session_id = QIVWSessionBegin(grammar_list, session_begin_params, &err_code);
	if (err_code != MSP_SUCCESS)
	{
		printf("QIVWSessionBegin failed! error code:%d\n", err_code);
		goto exit;
	}
	err_code = QIVWRegisterNotify(session_id, cb_ivw_msg_proc, NULL);	//为避免丢失句柄,回掉函数应当在此调用
	if (err_code != MSP_SUCCESS)
	{
		_snprintf(sse_hints, sizeof(sse_hints), "QIVWRegisterNotify errorCode=%d", err_code);
		printf("QIVWRegisterNotify failed! error code:%d\n", err_code);
		goto exit;
	}
	//开始录音
	err_code = create_recorder(&recorder, iat_cb, (void*)session_id);
	err_code = open_recorder(recorder, get_default_input_dev(), &wavfmt);
	err_code = start_record(recorder);
	
	//循环监听,保持录音状态
	while (record_state != MSP_AUDIO_SAMPLE_LAST)
	{
		Sleep(200); //阻塞直到唤醒结果出现
		//printf("正在监听%d\n", record_state);
		if (awkeFlag == 1)
		{
			awkeFlag = 0;	//恢复标志位方便下次唤醒
			break;			//跳出循环
		}
		count++;
		if (count == 20)	//为了防止循环监听时写入到缓存中的数据过大
		{
			//先释放当前录音资源
			stop_record(recorder);
			close_recorder(recorder);
			destroy_recorder(recorder);
			recorder = NULL;
			//printf("防止音频资源过大,重建\n");
			//struct recorder *recorder;
			//重建录音资源
			err_code = create_recorder(&recorder, iat_cb, (void*)session_id);
			err_code = open_recorder(recorder, get_default_input_dev(), &wavfmt);
			err_code = start_record(recorder);
			count = 0;
		}
	}

exit:
	if (recorder) {
		if (!is_record_stopped(recorder))
			stop_record(recorder);
		close_recorder(recorder);
		destroy_recorder(recorder);
		recorder = NULL;
	}
	if (NULL != session_id)
	{
		QIVWSessionEnd(session_id, sse_hints); //结束一次唤醒会话
	}
}

QIVWAudioWrite()其实在流程中基本都是在循环调用的:

写入本次唤醒的音频,本接口需要反复调用直到音频写完为止。调用本接口时,推荐用户在写入音频时采取"边录边写"的方式,即每隔一小段时间将采集到的音频通过本接口写入MSC。

得到唤醒结果后,会通过回调注册的函数QIVWRegisterNotify()这样一个异步的机制给你返回结果。
所以QIVWRegisterNotify()函数应当在QIVWSessionBegin()函数执行过后就立即执行。否则会出现丢失句柄的状况。
建议在每执行一个接口后就进行error_code的判断和返回。由于函数的数据传递过程都封装好了,这样可以方便进行调试。
QIVWSessionEnd()主要用于释放这个会话的资源,同时可以给你展示一个你自己定义的结束信息,意味着它正常结束。
当你流程的接口调用方法和顺序不当时,多半会返回这个错误码:
在这里插入图片描述

run_asr_mic麦克风语音识别:

static void run_asr_mic(const char* session_begin_params)
{
	int errcode;
	int i = 0;
	HANDLE helper_thread = NULL;

	struct speech_rec asr;
	DWORD waitres;
	char isquit = 0;
	struct speech_rec_notifier recnotifier = {
		on_result,
		on_speech_begin,
		on_speech_end
	};
	errcode = sr_init(&asr, session_begin_params, SR_MIC, DEFAULT_INPUT_DEVID, &recnotifier);
	if (errcode = sr_start_listening(&asr)) {
		printf("start listen failed %d\n", errcode);
		isquit = 1;
	}
	//Sleep(3000);

	if (errcode = sr_stop_listening(&asr)) {
		printf("stop listening failed %d\n", errcode);
		isquit = 1;
	}
	sr_stop_listening(&asr);
	sr_uninit(&asr);
}

你可以通过单独建立一个Sleep()延时来设置一个你规定的录音时间,
也可以完全依赖API的VAD机制。
官方例程采用的方式是通过按键开始,按键结束这样一个方法来限定录音的时间。
为了有更好的体验,我在sr_stop_listening()函数中,是用了VAD:

int sr_stop_listening(struct speech_rec *sr)
{
	int ret = 0;
	const char * rslt = NULL;
	char rslt_str[2048] = { '\0' };
	int count = 0;
	//如果未开始录音就错误调用了本函数那么返回报错
	if (sr->state < SR_STATE_STARTED) {
		sr_dbg("Not started or already stopped.\n");
		return 0;
	}

	while (1)			//进程阻塞
	{
		if (sr->ep_stat == MSP_EP_AFTER_SPEECH)		//VAD检测为音频末尾
		{
			break;
		}
		
	}
	//采用录音参数为NULL,0,MSP_AUDIO_SAMPLE_LAST
	ret = QISRAudioWrite(sr->session_id, NULL, 0, MSP_AUDIO_SAMPLE_LAST, &sr->ep_stat, &sr->rec_stat);
	if (ret != 0) {
		sr_dbg("write LAST_SAMPLE failed: %d\n", ret);
		QISRSessionEnd(sr->session_id, "write err");
		return ret;
	}

	//反复调用结果函数,直至获取结果
	while (sr->rec_stat != MSP_REC_STATUS_COMPLETE) {
		rslt = QISRGetResult(sr->session_id, &sr->rec_stat, 0, &ret);
		if (MSP_SUCCESS != ret)	{
			sr_dbg("\nQISRGetResult failed! error code: %d\n", ret);
			end_sr_on_error(sr, ret);
			return ret;
		}
		if (NULL != rslt && sr->notif.on_result)
			sr->notif.on_result(rslt, sr->rec_stat == MSP_REC_STATUS_COMPLETE ? 1 : 0);
		Sleep(100);
	}
	strcat(rslt_str, rslt);	//存储结果内容
	printf(rslt_str);	//展示结果
	Getid(rslt_str);	//解析出ID
	GetRawText(rslt_str);	//解析出原文
	//结束本次录音,释放资源
	if (sr->aud_src == SR_MIC) {
		ret = stop_record(sr->recorder);
#ifdef __FILE_SAVE_VERIFY__
		safe_close_file();
#endif
		if (ret != 0) {
			sr_dbg("Stop failed! \n");
			return -E_SR_RECORDFAIL;
		}
		wait_for_rec_stop(sr->recorder, (unsigned int)-1);
	}
	sr->state = SR_STATE_INIT;
	QISRSessionEnd(sr->session_id, "normal");
	sr->session_id = NULL;
	return 0;
}

语法规则:

本文使用的是离线命令词识别,官方使用的语法规则是巴克斯范式BNF。
可以在论坛下载pdf文件去系统学习如何定义规则:
语法开发指南
当你是用本地语法规则是,应当将你的BNF文件编辑好,并在代码中指定文件路径:
在这里插入图片描述
在这里插入图片描述
例程中附带BNF可以给你一个很好范本,作为你“照葫芦画瓢”的对象。

运行效果:

在这里插入图片描述
实际上API只会给你返回一个XML的字符串,如果你要解析你需要的信息,可以尝试用一些库去尝试。其中需要注意的是,如果你的部分语法中的词汇没有指定id,那么在xml中会返回一个默认的最大值65535。所以在编制id的时候应当避免编制到65535这个最大的数值,而且尽量在解析的时候滤除65535的关键词。

2017-12-01 17:00:49 zhenghongzhi6 阅读数 8032
  • micropython基础入门(esp32/esp8266单片机开发)

    micropython语法和python3一样,编写起来非常方便。如果你快速入门单片机玩物联网而且像轻松实现各种功能,那绝力推荐使用micropython。方便易懂易学。 同时如果你懂C语音,也可以用C写好函数并编译进micropython固件里然后进入micropython调用(非必须)。 能通过WIFI联网(2.1章),也能通过sim卡使用2G/3G/4G/5G联网(4.5章)。 为实现语音控制,本教程会教大家使用tensorflow利用神经网络训练自己的语音模型并应用。 为实现通过网页控制,本教程会教大家linux(debian10 nginx->uwsgi->python3->postgresql)网站前后台入门。 为记录单片机传输过来的数据, 本教程会教大家入门数据库。 本教程会通过通俗易懂的比喻来讲解各种原理与思路,并手把手编写程序来实现各项功能。 micropython版本是 2019年6月发布的1.11; 更多内容请看视频列表。 学习这门课程之前你需要至少掌握: 1: python3基础(变量, 循环, 函数, 常用库, 常用方法)。 本视频使用到的零件与淘宝上大致价格:     1: 超声波传感器(3)     2: MAX9814麦克风放大模块(8)     3: DHT22(15)     4: LED(0.1)     5: 8路5V低电平触发继电器(12)     6: HX1838红外接收模块(2)     7:红外发射管(0.1),HX1838红外接收板(1)     other: 电表, 排线, 面包板(2)*2,ESP32(28)

    668 人正在学习 去看看 陈恩棋

本文首发于“洪流学堂”公众号。
洪流学堂,让你快人几步!你好,我是你的技术探路者郑洪智,你可以叫我大智(vx: zhz11235)。

源码地址

https://github.com/zhenghongzhi/WitBaiduAip

功能概述

1 语音识别

  1. 从麦克风录制音频
  2. AudioClip的音频数据转换为百度语音识别的PCM16格式
  3. 百度语音识别Restful接口的封装以及一个测试场景

2 语音合成

  1. 百度语音合成Restful接口的封装以及一个测试场景
  2. mp3格式运行时转为AudioClip进行播放

为什么不使用百度的C# SDK
百度的C# SDK使用了一些Unity不支持的特性,直接导入unity不能用
而且百度C# SDK只是封装了Restful的接口,功能上并没有增多
自己编写更简洁

更新说明

2018-08-22更新

根据百度API的更新,语音合成性能优化,直接使用原生格式,移除第三方插件

2018-03-28更新

加入平台判断,更好的支持android和ios

2018-01-11更新

在工程中加入了语音合成

2018-01-02更新

应广大小伙伴的要求,对工程进行了重构,放出github源码
https://github.com/zhenghongzhi/WitBaiduAip

2017-12-23更新

教程首发


洪流学堂,让你快人几步
欢迎关注“洪流学堂”微信公众号

2019-08-25 09:48:51 qq_18351157 阅读数 303
  • micropython基础入门(esp32/esp8266单片机开发)

    micropython语法和python3一样,编写起来非常方便。如果你快速入门单片机玩物联网而且像轻松实现各种功能,那绝力推荐使用micropython。方便易懂易学。 同时如果你懂C语音,也可以用C写好函数并编译进micropython固件里然后进入micropython调用(非必须)。 能通过WIFI联网(2.1章),也能通过sim卡使用2G/3G/4G/5G联网(4.5章)。 为实现语音控制,本教程会教大家使用tensorflow利用神经网络训练自己的语音模型并应用。 为实现通过网页控制,本教程会教大家linux(debian10 nginx->uwsgi->python3->postgresql)网站前后台入门。 为记录单片机传输过来的数据, 本教程会教大家入门数据库。 本教程会通过通俗易懂的比喻来讲解各种原理与思路,并手把手编写程序来实现各项功能。 micropython版本是 2019年6月发布的1.11; 更多内容请看视频列表。 学习这门课程之前你需要至少掌握: 1: python3基础(变量, 循环, 函数, 常用库, 常用方法)。 本视频使用到的零件与淘宝上大致价格:     1: 超声波传感器(3)     2: MAX9814麦克风放大模块(8)     3: DHT22(15)     4: LED(0.1)     5: 8路5V低电平触发继电器(12)     6: HX1838红外接收模块(2)     7:红外发射管(0.1),HX1838红外接收板(1)     other: 电表, 排线, 面包板(2)*2,ESP32(28)

    668 人正在学习 去看看 陈恩棋

Speech Recogintion

7行 ,python语音识别

  1. 安装两个packages
# 安装语音识别packages
  $ pip install SpeechRecognition
#安装使用麦克风packages
  $ pip install pyaudio

安装使用麦克风packages
安装语音识别packages
安装使用麦克风packages
安装使用麦克风packages

2.语音识别

import speech_recognition as sr #导包

r = sr.Recognizer()  
mic = sr.Microphone()

with mic as source:
    r.adjust_for_ambient_noise(source)
    audio = r.listen(source)

print(r.recognize_google(audio, language='zh-CN')) #language='zh-CN'识别成中文

识别结果如下图识别结果如下图
3.结果
一个简单的小程序。
7行实现了语音识别。

2020-03-01 13:41:22 weixin_44895651 阅读数 568
  • micropython基础入门(esp32/esp8266单片机开发)

    micropython语法和python3一样,编写起来非常方便。如果你快速入门单片机玩物联网而且像轻松实现各种功能,那绝力推荐使用micropython。方便易懂易学。 同时如果你懂C语音,也可以用C写好函数并编译进micropython固件里然后进入micropython调用(非必须)。 能通过WIFI联网(2.1章),也能通过sim卡使用2G/3G/4G/5G联网(4.5章)。 为实现语音控制,本教程会教大家使用tensorflow利用神经网络训练自己的语音模型并应用。 为实现通过网页控制,本教程会教大家linux(debian10 nginx->uwsgi->python3->postgresql)网站前后台入门。 为记录单片机传输过来的数据, 本教程会教大家入门数据库。 本教程会通过通俗易懂的比喻来讲解各种原理与思路,并手把手编写程序来实现各项功能。 micropython版本是 2019年6月发布的1.11; 更多内容请看视频列表。 学习这门课程之前你需要至少掌握: 1: python3基础(变量, 循环, 函数, 常用库, 常用方法)。 本视频使用到的零件与淘宝上大致价格:     1: 超声波传感器(3)     2: MAX9814麦克风放大模块(8)     3: DHT22(15)     4: LED(0.1)     5: 8路5V低电平触发继电器(12)     6: HX1838红外接收模块(2)     7:红外发射管(0.1),HX1838红外接收板(1)     other: 电表, 排线, 面包板(2)*2,ESP32(28)

    668 人正在学习 去看看 陈恩棋

语音识别工作原理简介

语音识别源于 20 世纪 50 年代早期在贝尔实验室所做的研究。早期语音识别系统仅能识别单个讲话者以及只有约十几个单词的词汇量。现代语音识别系统已经取得了很大进步,可以识别多个讲话者,并且拥有识别多种语言的庞大词汇表。
语音识别的首要部分当然是语音。通过麦克风,语音便从物理声音被转换为电信号,然后通过模数转换器转换为数据。一旦被数字化,就可适用若干种模型,将音频转录为文本。
大多数现代语音识别系统都依赖于隐马尔可夫模型(HMM)。其工作原理为:语音信号在非常短的时间尺度上(比如 10 毫秒)可被近似为静止过程,即一个其统计特性不随时间变化的过程。
许多现代语音识别系统会在 HMM 识别之前使用神经网络,通过特征变换和降维的技术来简化语音信号。也可以使用语音活动检测器(VAD)将音频信号减少到可能仅包含语音的部分。
幸运的是,对于 Python 使用者而言,一些语音识别服务可通过 API 在线使用,且其中大部分也提供了 Python SDK。

选择合适的python语音识别包

PyPI中有一些现成的语音识别软件包。其中包括:
•apiai
•google-cloud-speech
•pocketsphinx
•SpeechRcognition
•watson-developer-cloud
•wit
一些软件包(如 wit 和 apiai )提供了一些超出基本语音识别的内置功能,如识别讲话者意图的自然语言处理功能。其他软件包,如谷歌云语音,则专注于语音向文本的转换。
其中,SpeechRecognition 就因便于使用脱颖而出。
识别语音需要输入音频,而在 SpeechRecognition 中检索音频输入是非常简单的,它无需构建访问麦克风和从头开始处理音频文件的脚本,只需几分钟即可自动完成检索并运行。

安装SpeechRecognition

SpeechRecognition 兼容 Python2.6 , 2.7 和 3.3+,但若在 Python 2 中使用还需要一些额外的安装步骤。大家可使用 pip 命令从终端安装 SpeechRecognition:pip3 install SpeechRecognition
安装过程中可能会出现一大片红色字体提示安装错误!我在另一篇博客中有解决方法(https://blog.csdn.net/weixin_44895651/article/details/104276569
安装完成后可以打开解释器窗口进行验证安装:
在这里插入图片描述
注:不要关闭此会话,在后几个步骤中你将要使用它。
若处理现有的音频文件,只需直接调用 SpeechRecognition ,注意具体的用例的一些依赖关系。同时注意,安装 PyAudio 包来获取麦克风输入

识别器类

SpeechRecognition 的核心就是识别器类。
Recognizer API 主要目是识别语音,每个 API 都有多种设置和功能来识别音频源的语音,这里我选择的是recognize_sphinx(): CMU Sphinx - requires installing PocketSphinx(支持离线的语音识别
那么我们就需要通过pip命令来安装PocketSphinx,在安装过程中也容易出现一大串红色字体的错误。因为博主英语不太好,具体啥错误不知道。直接上解决方法吧!在我的另一篇文章有介绍:(https://blog.csdn.net/weixin_44895651/article/details/104445102

音频文件的使用

下载相关的音频文件保存到特定的目录(博主直接保存到ubuntu桌面):
链接:https://pan.baidu.com/s/1oWG1A6JnjpeT_8DhEpoZzw
提取码:sf73
注意:
AudioFile 类可以通过音频文件的路径进行初始化,并提供用于读取和处理文件内容的上下文管理器界面。
SpeechRecognition 目前支持的文件类型有:

  • WAV: 必须是 PCM/LPCM 格式
  • AIFF
  • AIFF-CFLAC: 必须是初始 FLAC 格式;OGG-FLAC 格式不可用

英文的语音识别

在完成以上基础工作以后,就可以进行英文的语音识别了。
(1)打开终端
(2)进入语音测试文件所在目录(博主的是 桌面)
(3)打开python解释器
(4)按照下图输入相关命令
在这里插入图片描述
最后就可以看到语音转文字的内容(this they’ll smell …),其实效果还是很不错的!因为是英文,并且没有噪音。

噪音对语音识别的影响

噪声在现实世界中确实存在,所有录音都有一定程度的噪声,而未经处理的噪音可能会破坏语音识别应用程序的准确性。
要了解噪声如何影响语音识别,请下载 “jackhammer.wav”(链接:https://pan.baidu.com/s/1AvGacwXeiSfMwFUTKer3iA
提取码:3pj7)
通过尝试转录效果并不好,我们可以通过尝试调用 Recognizer 类的adjust_for_ambient_noise()命令。
当然具体的博主没有实践,不知道准确性如何!大家可以借鉴这篇文章(https://mp.weixin.qq.com/s/B1w-ZLwoK1-5wDZW9pJ82g

麦克风的使用

若要使用 SpeechRecognizer 访问麦克风则必须安装 PyAudio 软件包。
如果使用的是基于 Debian的Linux(如 Ubuntu ),则可使用 apt 安装 PyAudio:sudo apt-get install python-pyaudio python3-pyaudio安装完成后可能仍需要启用 pip3 install pyaudio ,尤其是在虚拟情况下运行。
在安装完pyaudio的情况下可以通过python实现语音录入生成相关文件。
pocketsphinx的使用注意
支持文件格式:wav
音频文件的解码要求:16KHZ,单声道
利用python实现录音并生成相关文件程序代码如下:

from pyaudio import PyAudio, paInt16
import numpy as np
import wave
class recoder:
     NUM_SAMPLES = 2000   
     SAMPLING_RATE = 16000  
     LEVEL = 500     
     COUNT_NUM = 20   
     SAVE_LENGTH = 8     
     Voice_String = []
     def savewav(self,filename):
         wf = wave.open(filename, 'wb')
         wf.setnchannels(1)
         wf.setsampwidth(2)
         wf.setframerate(self.SAMPLING_RATE)
         wf.writeframes(np.array(self.Voice_String).tostring())
         wf.close()
     def recoder(self):
         pa = PyAudio()
         stream = pa.open(format=paInt16, channels=1, rate=self.SAMPLING_RATE, input=True,frames_per_buffer=self.NUM_SAMPLES)
         save_count = 0
         save_buffer = []
         while True:
            string_audio_data = stream.read(self.NUM_SAMPLES)
            audio_data = np.fromstring(string_audio_data, dtype=np.short)
            large_sample_count = np.sum(audio_data > self.LEVEL)
            print(np.max(audio_data))
            if large_sample_count > self.COUNT_NUM:
                save_count = self.SAVE_LENGTH
            else:
                save_count -= 1
            if save_count < 0:
                save_count = 0
            if save_count > 0:
                save_buffer.append(string_audio_data )
            else:
                if len(save_buffer) > 0:
                    self.Voice_String = save_buffer
                    save_buffer = []
                    print("Recode a piece of voice successfully!")
                    return True
		 else:
                    return False
if __name__ == "__main__":
    r = recoder()
    r.recoder()
    r.savewav("test.wav")

注意:在利用python解释器实现时一定要注意空格!!!
最后生成的文件就在Python解释器回话所在目录下,可以通过play来播放测试一下,如果没有安装play可以通过apt命令来安装。

中文的语音识别

在进行完以前的工作以后,我们对语音识别的流程大概有了一定的了解,但是作为一个中国人总得做一个中文的语音识别吧!
我们要在CMU Sphinx语音识别工具包里面下载对应的普通话升学和语言模型。在这里插入图片描述
图片中标记的就是普通话!下载相关的语音识别工具包。
但是我们要把zh_broadcastnews_64000_utf8.DMP转化成language-model.lm.bin,这里可以借鉴这篇博主的文章。最后得到chinese.lm.bin
再解压zh_broadcastnews_16k_ptm256_8000.tar.bz2得到zh_broadcastnews_ptm256_8000文件夹。
借鉴刚才那位博主的方法,在Ubuntu下找到speech_recognition文件夹。可能会有很多小伙伴找不到相关的文件夹,其实是在隐藏文件下。大家可以点击文件夹右上角的三条杠。如下图所示:
在这里插入图片描述
然后给显示隐藏文件打个勾,如下图所示:
在这里插入图片描述
然后依次按照以下目录就可以找到啦:在这里插入图片描述
然后把原来的en-US改名成en-US-bak,新建一个文件夹en-US,把解压出来的zh_broadcastnews_ptm256_8000改成acoustic-model,把chinese.lm.bin改成language-model.lm.bin,把pronounciation-dictionary.dic改后缀成dict,复制这三个文件到en-US里。同时把原来en-US文件目录下的LICENSE.txt复制到现在的文件夹下。
最终该文件夹下有以下文件:
在这里插入图片描述
然后我们就可以通过麦克风录入一个语音文件文件(“test.wav”)
在该文件目录下打开python解释器输入以下内容:
在这里插入图片描述
就看到了输出内容,但是我说的是两个中国,也测试了一下其他的发现识别效果很不好!!!
当然有好多同学可能想要语音包,我就分享给大家啦!(链接:https://pan.baidu.com/s/13DTDnv_4NYbKXpkXAXODpw
提取码:zh39)

小范围中文识别

用官方提供的效果太差,几乎不能用!那么我看了很多文章以后就想到了一种优化方法,但是只适合小范围的识别!一些命令啥的应该没有问题,但是聊天什么的可能就效果不太好。
找到刚才复制的4个文件夹,有一个pronounciation-dictionary.dict的文件夹,打开以后是以下内容:
在这里插入图片描述感觉这内容就是类似于一个字典,很多用词和平时交流的用词差距比较大。那么我们改成我们习惯的用词就可以啦! 抱着试一试的想法,结果还真的可以。识别效果真的不错!
我的做法是:
(1)把图片中红色标记以上的内容继续保留,红色以下的内容删除掉。当然处于保险考虑建议大家给该文件备份一下!
(2)给红色线以下输入自己想识别的内容!(按照规则输入,不同于拼音!!!)最近新型肺炎的情况不断的变好,听到最多的一句话就是“中国加油”那么今天的内容就是将“中国加油”实现语音转文字!希望能早日开学,哈哈哈哈。
在这里插入图片描述
(3)输入以下内容:
在这里插入图片描述
就可以看到中国加油啦!同时希望肺炎疫情早日康复!

语音合成

语音合成个人的理解就是文字转语音。这篇文章已经介绍的很详细啦!(https://blog.csdn.net/chadian3912/article/details/81077537)所以我就不多介绍啦!不过这句话中可以设置client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) result = client.synthesis('你好百度', 'zh', 1, { 'vol': 5,'spd': 3,'pit':9,'per': 3})音量、声调、速度、男/女/萝莉/逍遥。
大家快去尝试合成一下吧!最后来欣赏一下语音合成后4种不同风格的语音,你更喜欢那一款呢?

2017-05-23 07:12:32 liuyuehui110 阅读数 1556
  • micropython基础入门(esp32/esp8266单片机开发)

    micropython语法和python3一样,编写起来非常方便。如果你快速入门单片机玩物联网而且像轻松实现各种功能,那绝力推荐使用micropython。方便易懂易学。 同时如果你懂C语音,也可以用C写好函数并编译进micropython固件里然后进入micropython调用(非必须)。 能通过WIFI联网(2.1章),也能通过sim卡使用2G/3G/4G/5G联网(4.5章)。 为实现语音控制,本教程会教大家使用tensorflow利用神经网络训练自己的语音模型并应用。 为实现通过网页控制,本教程会教大家linux(debian10 nginx->uwsgi->python3->postgresql)网站前后台入门。 为记录单片机传输过来的数据, 本教程会教大家入门数据库。 本教程会通过通俗易懂的比喻来讲解各种原理与思路,并手把手编写程序来实现各项功能。 micropython版本是 2019年6月发布的1.11; 更多内容请看视频列表。 学习这门课程之前你需要至少掌握: 1: python3基础(变量, 循环, 函数, 常用库, 常用方法)。 本视频使用到的零件与淘宝上大致价格:     1: 超声波传感器(3)     2: MAX9814麦克风放大模块(8)     3: DHT22(15)     4: LED(0.1)     5: 8路5V低电平触发继电器(12)     6: HX1838红外接收模块(2)     7:红外发射管(0.1),HX1838红外接收板(1)     other: 电表, 排线, 面包板(2)*2,ESP32(28)

    668 人正在学习 去看看 陈恩棋

在.NET4.0中,我可以借助System.Speech组件让电脑来识别我们的声音。

 

1

以上,当我说"name",显示"Darren",我说"age",显示"永远21"。如何做呢?


首先要开启电脑的语音识别功能。


右键电脑右下方的扬声器,选择"录音设备"。


点击默认的"麦克风",再点击左下角的"配置"按钮。

2


点击"启动语音识别"。

3

 

一系列简单设置后,屏幕上出现如下:

4

 

在VS中创建一个窗体应用程序,界面上有一个RichTextBox和2个Button。


添加System.Speech的引用。

 

编写如下:

    public partial class Form1 : Form
    {
        SpeechRecognitionEngine recEngine = new SpeechRecognitionEngine();
        public Form1()
        {
            InitializeComponent();
        }
        private void btnEnable_Click(object sender, EventArgs e)
        {
            recEngine.RecognizeAsync(RecognizeMode.Multiple);
            btnDisable.Enabled = true;
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            Choices preCmd = new Choices();
            preCmd.Add(new string[] { "name", "age" });
            GrammarBuilder gb = new GrammarBuilder();
            gb.Append(preCmd);
            Grammar gr = new Grammar(gb);
            recEngine.LoadGrammarAsync(gr);
            recEngine.SetInputToDefaultAudioDevice();
            recEngine.SpeechRecognized += recEngine_SpeechRecognized;
        }
        void recEngine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            switch (e.Result.Text)
            {
                case "name":
                    richTextBox1.Text += "\nDarren";
                    break;
                case "age":
                    richTextBox1.Text += "\n永远21";
                    break;
            }
        }
        private void btnDisable_Click(object sender, EventArgs e)
        {
            recEngine.RecognizeAsyncStop();
            btnDisable.Enabled = false;
        }
    }

 

当然,中文的语音识别也是可以滴。

  

好玩Y(^_^)Y   

Siri 语音识别 Speech

阅读数 601

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