一、SDK下载

讯飞开放平台:https://www.xfyun.cn/快速链接
控制台——创建新应用——下载Linux MSC

找到Linux MSC,点击下载

点击回到老版

得到一个名为Linux_xtts_exp1227_iat1227_tts_online1227_1d36319c.zip的压缩包

在Linux下运行

unzip Linux_xtts_exp1227_iat1227_tts_online1227_1d36319c.zip -d /home/用户名/Linux_xtts_exp1227_iat1227_tts_online1227_1d36319c

进入文件夹可以看到sample文件夹

二、SDKSDK编译与样例运行

语音转文字操作

1.编译SDK

        首先安装依赖 sudo apt-get install libasound2-dev

  在samples/iat_online_record_sample文件夹下执行编译命令编译source 64bit_make.sh 

gcc -c -g -Wall -I../../include linuxrec.c -o linuxrec.o
linuxrec.c:529:12: warning: ‘list_pcm’ defined but not used [-Wunused-function]
 static int list_pcm(snd_pcm_stream_t stream, char**name_out, 
            ^
gcc -c -g -Wall -I../../include speech_recognizer.c -o speech_recognizer.o
gcc -c -g -Wall -I../../include iat_online_record_sample.c -o iat_online_record_sample.o
gcc -g -Wall -I../../include linuxrec.o speech_recognizer.o iat_online_record_sample.o -o ../../bin/iat_online_record_sample -L../../libs/x64 -lmsc -lrt -ldl -lpthread -lasound -lstdc++

看到上面显示就是正常的

2.运行语音转文字例程

在bin文件夹下会生成一个iat_online_record_sample,我们运行./iat_online_record_sample看看这个例程。

运行例程时会报错如下:

./iat_online_record_sample: error while loading shared libraries: libmsc.so: cannot open shared object file: No such file or directory

解决方法是把libmsc.so文件复制到usr/lib文件夹下:

sudo cp libs/x64/libmsc.so /usr/lib/
sudo ldconfig

复制完后重新运行./iat_online_record_sample会有两步配置,如下所示
①是否上传使用者的字符库,选择 No

②语音从哪里来,选择From microphone

最后,对着麦克风讲话,将识别并转换为文字。

文字转语音操作

1.编译SDK

  到samples/tts_online_sample文件夹下执行编译命令source 64bit_make.sh ,然后到bin/文件夹下执行./tts_online_sample

2.运行例程

运行之后按任意键退出,在bin/文件夹下生成一个tts_sample.wav,可以双击运行播放。如果想要运行上述指令后自动播放wav文件,则需要修改源码,找到 samples/tts_online_sample/tts_online_sample.c文件,在第174行(printf("合成完毕\n");这句后面)添加如下代码,就可以在合成之后自动播放合成的文件。
 

三、集成ros

1.ROS语音转文字功能

利用科大讯飞开放平台来实现ROS的语音输入功能。任务流程图如下,在终端中,通过/voiceWakeup话题发布一个唤醒词,开启语音转文字的功能。随后通过修改iat_publish.cpp实现语音转文字的功能,转化出来的文字送入到/voiceWords话题中发布出来。

在ros空间下新建功能包exhibition_nav,依赖是roscpp rospy std_msgs

把sdk中的include的.h头文件(6个)复制到功能包下的exhibition_nav/include/exhibition_nav

将sdk中/samples/iat_online_record_sample/*.h文件夹中所有的.h文件(共3个)也复制到工作空间/src/exhibition_nav/include/exhibition_nav/中,如下:

将sdk中/samples/iat_online_record_sample/*.c文件夹中所有的.c文件(共3个)复制到工作空间/src/exhibition_nav/src/中,并将iat_online_record_sample.c改名为iat_publish.cpp,如下:

修改cpp功能文件

  接下来我们修改iat_publish.cpp文件以实现语音转文字的功能。首先是修改头文件,将下面四个头文件进行修改。

#include "qisr.h"
#include "msp_cmn.h"
#include "msp_errors.h"
#include "speech_recognizer.h"

修改为

#include "exhibition_nav/qisr.h"
#include "exhibition_nav/msp_cmn.h"
#include "exhibition_nav/msp_errors.h"
#include "exhibition_nav/speech_recognizer.h"

这里要改成功能包下的名字

linuxrec.cspeech_recognizer.c中也需要修改头文件(加上exhibition_nav/)

回到iat_publish.cpp文件中,为其添加ROS的头文件,并定义两个标志,一个是唤醒标志,一个是转换标志:

#include "ros/ros.h"
#include "std_msgs/String.h"

int wakeupFlag   = 0 ;
int resultFlag   = 0 ;

以及修改show_result()函数,添加

resultFlag=1;

在main函数里面添加ros初始化

	// 初始化ROS
    ros::init(argc, argv, "voiceRecognition");
    ros::NodeHandle n;
    ros::Rate loop_rate(10);

    // 声明Publisher和Subscriber
    // 订阅唤醒语音识别的信号
    ros::Subscriber wakeUpSub = n.subscribe("voiceWakeup", 1000, WakeUp);   
    // 订阅唤醒语音识别的信号    
    ros::Publisher voiceWordsPub = n.advertise<std_msgs::String>("voiceWords", 1000);  

    ROS_INFO("Sleeping...");
    int count=0;

在主函数中继续往下找,找到下面的这几行删掉,我们重新编写唤醒代码和语音转文字代码。

删除后的位置添加如下代码:

	while(ros::ok())
	{
		// 语音识别唤醒     
        if(wakeupFlag)
        {
			printf("Demo recognizing the speech from microphone\n");
			printf("Speak in 8 seconds\n");

			demo_mic(session_begin_params);

			printf("8 sec passed\n");
			wakeupFlag=0;
		}

		// 语音识别完成
		if(resultFlag){
			resultFlag=0;
			std_msgs::String msg;
			msg.data = g_result;
			voiceWordsPub.publish(msg);
		}
		ros::spinOnce();
        loop_rate.sleep();
        count++;
	}

最后在main函数之前添加一个唤醒WakeUp()代码:

void WakeUp(const std_msgs::String::ConstPtr& msg)
{
    printf("waking up\r\n");
    usleep(700*1000);
    wakeupFlag=1;
}


至此语音转文字的代码修改就完成了,可以实现15s的语音转文字,如果需要修改15s为其他,例如8s,需要修改三处(主要是一处,另外两处只是可视化):
在主函数刚刚写的while循环中修改两处:

printf("Demo recognizing the speech from microphone\n");
printf("Speak in 8 seconds\n");

demo_mic(session_begin_params);

printf("8 sec passed\n");

demo_mic()函数中修改一处:

	/* demo 8 seconds recording */
	while(i++ < 8)
		sleep(1);

配置CMakeLists.txt文件

接下来是配置CMakeLists.txt文件:
第5行注释打开。

add_compile_options(-std=c++11)

第118行include头文件路径注释打开

include_directories(
 include
  ${catkin_INCLUDE_DIRS}
)

第136行添加可执行文件

add_executable(iat_publish src/iat_publish.cpp src/speech_recognizer.c src/linuxrec.c)

第149行添加编译链接库

target_link_libraries(iat_publish
  ${catkin_LIBRARIES}
  libmsc.so -ldl -lpthread -lm -lrt -lasound
)

运行语音转文字

至此配置完成,可以编译并运行功能包:
rosrun exhibition_nav iat_publish
出现如下说明需要唤醒词进行唤醒,然后方可用麦克风输入语音。

hnu@hnu-NA17:~/Guidance_Robot_ws$ rosrun exhibition_nav iat_publish 
[INFO] [1758784956.559722751]: Sleeping...

重新开启一个终端,查看当前话题rostopic list

hnu@hnu-NA17:~/Guidance_Robot_ws$ rostopic list
/rosout
/rosout_agg
/voiceWakeup
/voiceWords

可以看到有一个/voiceWakeup话题,输入任意字符,运行这个话题即可。

hnu@hnu-NA17:~/Guidance_Robot_ws$ rostopic pub /voiceWakeup std_msgs/String "data: 'test'" 
hnu@hnu-NA17:~/Guidance_Robot_ws$ rosrun exhibition_nav iat_publish 
[INFO] [1758785177.518087420]: Sleeping...
waking up
Demo recognizing the speech from microphone
Speak in 8 seconds
Start Listening...
Result: [ 这是一个测试案例。 ]

Speaking done 
Not started or already stopped.
8 sec passed

出现这个说明成功了!!!!

2.ROS文字转语音输出功能


  利用科大讯飞开放平台来实现ROS的语音输出功能。任务流程图如下,在终端中,通过终端往/voiceWords话题发布一个字符串,开启文字转语音的功能。随后通过修改tts_subscribe.cpp实现文字转语音的功能,转化出来的语音进行实时播报。

创建工作空间
  工作空间仍采用上一小节建立好的工作空间,在此基础上进行添加相关功能。将科大讯飞的sdk中/samples/tts_online_sample/文件夹下的tts_online_sample.c文件复制到工作空间下/src/exhibition_nav/src/中,并改名字为tts_subscribe.cpp。

修改tts_subscribe.cpp

首先还是头文件的修改:

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

//修改为
#include "exhibition_nav/qtts.h"
#include "exhibition_nav/msp_cmn.h"
#include "exhibition_nav/msp_errors.h"

#include "ros/ros.h"
#include "std_msgs/String.h"

修改main函数,删除169-176行

添加ros初始化节点

ros::init(argc,argv,"robot_voice");
ros::NodeHandle n;
ros::Subscriber sub =n.subscribe("voiceWords", 1000, voiceWordsCallback);
ros::spin();

注释176-80这几个

修复一个错误,将用户登陆中的goto exit删除,改为调用toExit()函数。,以及删除下面

配置CMakeLists.txt文件

下面进行配置文件,仍在上一节的CMakeLists.txt基础上添加下面两行。

add_executable(tts_subscribe src/tts_subscribe.cpp)
target_link_libraries(tts_subscribe
  ${catkin_LIBRARIES}
  libmsc.so -ldl -pthread 
)

catin_make编译,运行rosrun robot_voice tts_subscribe

等待输入字符串进行文字转语音,运行rostopic list查看话题,然后往/voiceWords中发布一条字符串:这是一个测试案例。可以发现扬声器开始播报。

hnu@hnu-NA17:~/Guidance_Robot_ws$ rostopic pub /voiceWords std_msgs/String "data: ' 这是一个测试案例'" 

报错信息 sh: 1: play: not found 可以看出,问题出在音频播放环节

sudo apt-get install sox  # 安装基础工具
sudo apt-get install libsox-fmt-all  # 安装所有音频格式支持(避免播放 wav 失败)

文字转语音也成功实现了

3.使用launch文件将语音与文字实现相互转换

利用科大讯飞开放平台来实现ROS同时输入输出语音功能。任务流程图如下,在终端中,往/voiceWakeup话题发布唤醒词,开启语音转文字功能。接着开启文字转语音功能从/voiceWords话题中获取文字转化成语音播放出来。

建立launch启动文件

我们建立一个launch启动文件,将前面两节的功能包包含进来即可,repeat_voice.launch内容如下

<launch>

	<node name="iat_publish" pkg="exhibition_nav " type="iat_publish" output="screen"/>
	<node name="tts_subscribe" pkg="exhibition_nav " type="tts_subscribe" output="screen"/>

</launch>

运行roslaunch exhibition_nav repeat_voice.launch

发布唤醒词:

 rostopic pub /voiceWakeup std_msgs/String "data: 'any words'" 
成功了

ROS实现语音交互功能(只能实现处理预设的固定指令(如 “你是谁”“时间” 等),这是因为代码中使用了if-else结构对特定关键词进行匹配,只能响应预先定义好的对话逻辑。)

语音交互功能是前面案例的综合,通过唤醒词启动交互功能,语音输入一段音频后,根据输入的音频取执行响应的动作,例如返回另一端音频,或者发布一个指定的话题等等

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐