利用科大讯飞语音合成模块SDK实现ROS语音交互
将科大讯飞的sdk中/samples/tts_online_sample/文件夹下的tts_online_sample.c文件复制到工作空间下/src/exhibition_nav/src/中,并改名字为tts_subscribe.cpp。unzip Linux_xtts_exp1227_iat1227_tts_online1227_1d36319c.zip -d /home/用户名/Linux_
一、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.c
和speech_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
结构对特定关键词进行匹配,只能响应预先定义好的对话逻辑。)
语音交互功能是前面案例的综合,通过唤醒词启动交互功能,语音输入一段音频后,根据输入的音频取执行响应的动作,例如返回另一端音频,或者发布一个指定的话题等等
更多推荐
所有评论(0)