项目:智能语音对话机器人
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                项目:智能语音对话机器人
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                技術點:
● C++STL
 ● http第三方庫
 ● 圖靈機器人
 ● 百度語音識別和語音識別
 ● Linux系統/網絡編程
 ● 各種第三方庫和第三方工具的安裝與使用
項目簡介
- 使用C++編寫一個智能AI對話和語音命令執行的語音管理工具,其中可執行命令支持配置。
- 主要采用C++進程編寫,當程序啟動后,加載配置文件,啟動錄音功能進行錄音,調用百度語音識別平臺對所錄音文件進行識別;再對所識別到的文字進行判斷,是命令還是普通對話,命令則執行系統命令執行模塊;普通對話則交給圖靈機器人進行交流,所返回的文字交給百度語音合成平臺,啟動播放功能,則成功進行對話。
準備工作
- 使用圖靈機器人實現對話,需要注冊圖靈機器人,擁有一個屬于自己的機器人
- 使用百度語音識別和語音合成,同樣也需要注冊,在之后的使用中,我們選擇的技術文檔為C++SDK,需要下載百度C++語音識別SDK
- 安裝jsoncpp、 安裝openssl、安裝libcurl(需要支持https)
- 還要準備錄音和播放工具,在我的Centos 7上有系統自帶的錄音工具arecord,安裝vlc/cvlc播放器
編碼過程
● 先建立項目目錄,創建工程文件,引入百度語音識別SDK
#mkdir Boyfriend #ls build.sh- 構建項目的shell腳本,簡單實現 command.etc
- 語音命令配置文件 Boyfriend.cc
- 源文件 Boyfriend.hpp
- 核心代碼 Makefile speech
- 百度語音識別SDK temp_file
- 保存臨時語音文件目錄
核心代碼
LInux語音AI相關代碼
#Boyfriend.hpp//1、創建相關類,包含相關頭文件 #pragma once#include <map>#include <iostream>#include <cstdio>#include <sstream>#include <memory>#include <fstream>#include <unistd.h>#include <stdlib.h>#include <unordered_map>#include <json/json.h>#include <string>#include <pthread.h>#include "base/http.h"#include "speech.h"//#define TTS_PATH "temp_file/tts.mp3"#define TTS_PATH "temp_file/tts.wav"#define ASR_PATH "temp_file/asr.wav"#define CMD_ETC "command.etc"#define LOG "log.txt"class Util{private:static pthread_t id;public:static bool Exec(std::string command, bool is_print){if(!is_print){command += ">/dev/null 2>&1";}FILE *fp = popen(command.c_str(), "r");if(nullptr == fp){std::cerr << "popen exec \'" << command << "\' Error" << std::endl;return false;}if(is_print){char ch;while(fread(&ch,1,1,fp) >0){fwrite(&ch,1,1,stdout);}}pclose(fp);return true;}static void *ThreadRun(void *arg){const char *tips = (char*)arg;int i = 0;char bar[103] = {0};const char *lable = "|/-\\";for(; i<=50;i++){printf("%s[%-51s][%d%%][%c]\r",tips,bar,i*2,lable[i%4]);fflush(stdout);bar[i] = '=';bar[i+1] = '>';//bar[i+2] = 0;usleep(49000*2);}printf("\n");}static void PrintStart(std::string tips){pthread_create(&id,NULL,ThreadRun,(void*)tips.c_str());}static void PrintEnd(){pthread_cancel(id);}};pthread_t Util::id;//2、采用圖靈機器人,進行智能對話 class Robot{private:std::string url;std::string api_key;std::string user_id;aip::HttpClient client;private:bool IsCodeLegal(int code){bool result = false;switch(code){case 5000:case 6000:break;case 10004:result = true;break;default:result = true;break;}return result;}std::string MessageToJson(std::string &message){Json::Value root;Json::StreamWriterBuilder wb;std::ostringstream ss;Json::Value item_;item_["text"] = message ;Json::Value item;item["inputText"] = item_ ;root["reqType"] = 0;//textroot["perception"] = item;item.clear();item["apiKey"] = api_key;item["userId"] = user_id;root["userInfo"] = item;std::unique_ptr<Json::StreamWriter> sw(wb.newStreamWriter());sw->write(root,&ss);std::string json_string = ss.str();//std::cout<<"debug: "<<json_string<<std::endl;return json_string;}std::string RequestTL(std::string &request_json){std::string response;int status_code = client.post(url,nullptr,request_json,nullptr,&response);if (status_code != CURLcode::CURLE_OK) {std::cerr << "post error" << std::endl;return "";}return response;}std::string JsonToEchoMessage(std::string &str){//std::cout <<"JsonToEchoMessage:"<< str << std::endl;JSONCPP_STRING errs;Json::Value root;Json::CharReaderBuilder rb;std::unique_ptr<Json::CharReader> const cr(rb.newCharReader());bool res = cr->parse(str.data(),str.data()+str.size(), &root,&errs);if(!res || !errs.empty()) {std::cerr << "parse error!"<<std::endl;return "";}int code = root["intent"]["code"].asInt();if(!IsCodeLegal(code)){std::cerr<< "response code error!" <<std::endl;return "";}Json::Value item = root["results"][0];std::string msg = item["values"]["text"].asString();return msg;}public:Robot(std::string id = "1"){this->url = "http://openapi.tuling123.com/openapi/api/v2";this->api_key = "b7fa07e47cbe46a191b8190cc004ed60";this->user_id = id;}std::string Talk(std::string message){std::string json = MessageToJson(message);std::string responce = RequestTL(json);std::string echo_message = JsonToEchoMessage(responce);return echo_message ;}~Robot(){}};//3、語音識別Speech Recognitionclass SpeechRec{private://填寫appid,填寫Api Key,填寫Secret Key.std::string app_id;std::string api_key;std::string secret_key;aip::Speech *client;private:bool IsCodeLegal(int code){bool result = false;switch(code){case 0:result=true;break;default:break;}return result;}public:SpeechRec(){app_id = "16943059";api_key = "q9vkbqwjwKjvoPgt69NTt36F";secret_key = "8lbil7MTruiGKHQdSsIT1WB97rX4ncsl";client = new aip::Speech(app_id, api_key, secret_key);}//4、語音識別Automatic Speech Recognition bool ASR(std::string path,std::string &out){std::map<std::string,std::string> options;options["dev_pid"] = "1536";std::string file_content;aip::get_file_content(ASR_PATH,&file_content);Json::Value result = client->recognize(file_content,"wav",16000,options);//std::cout << "debug: " << result.toStyledString() << std::endl;int code = result["err_no"].asInt();if(!IsCodeLegal(code)){std::cerr << "recognize error" << std::endl;return false;}out = result["result"][0].asString();return true;}//5、語音合成Text To Speechbool TTS(std::string message){bool ret;std::ofstream ofile;std::string ret_file;std::map<std::string,std::string> options;options["spd"]="5"; //speech speed 0~15options["pit"]="7"; //0-15options["vol"]="15"; //0-15options["per"]="110"; //1 0 3 4 度博文=106 度小童=110 度小萌=111 度米朵=103 度小嬌=5options["aue"]="6";ofile.open(TTS_PATH,std::ios::out|std::ios::binary);Json::Value result=client->text2audio(message,options,ret_file);if(!ret_file.empty()){ofile << ret_file;ofile.close();ret = true;}else{std::cerr <<result.toStyledString() << std::endl;ret = false;}ofile.close();return ret;}~SpeechRec(){}};//6、核心代碼-服務器&&系統相關 class Boyfriend{private:Robot rt;SpeechRec sr;std::unordered_map<std::string,std::string> commands;private:bool Record(){//std::cout << "debug:" << "Record ..." << std::endl;Util::PrintStart("錄音中");std::string command = "arecord -t wav -c 1 -r 16000 -d 5 -f S16_LE ";command += ASR_PATH;bool ret = Util::Exec(command,false);//std::cout << "debug:Recoed ... done" <<std::endl;Util::PrintEnd();return ret;}bool Play(){std::string command = "cvlc --play-and-exit ";command += TTS_PATH;return Util::Exec(command,false);}public:Boyfriend(){};bool LoadEtc(){std::ifstream in(CMD_ETC);if(!in.is_open()){std::cerr <<"open error" <<std::endl;return false;}std::string sep = ":";char line[256];while(in.getline(line,sizeof(line))){std::string str = line;std::size_t pos = str.find(sep);if(std::string::npos == pos){std::cerr << "not find :" << std::endl;continue;}std::string k = str.substr(0,pos);std::string v = str.substr(pos+sep.size());k+="。";commands.insert(std::make_pair(k,v));//commands.insert({k,v});}std::cerr <<"Load command erc done ... success"<< std::endl;in.close();return true;}bool IsCommand(std::string message,std::string &cmd){auto iter = commands.find(message);if(iter ==commands.end()){return false;}cmd = iter->second;}void Run(){#ifdef _LOG_int fd = open(LOG,O_WRONLY|O_CREAT,0644);if(fd<0){return 1;}dup2(fd,2);//int fd = open("/dev/null",O_WRONLY);#endifvolatile bool quit = false;while(!quit){if(this->Record()){std::string message;if(sr.ASR(ASR_PATH,message)){//1.commandstd::string cmd="";if(IsCommand(message,cmd)){std::cout << "[Boyfriend@localhost]$ "<<cmd <<std::endl;Util::Exec(cmd,true);continue;}std::cout<<"我# "<<message <<std::endl;if(message =="你走吧。"){std::string quit_message = "那我就走了,不要太想我哦!";std::cout<<"Boyfriend# " << quit_message<< std::endl;if(sr.TTS(quit_message)){this->Play();}exit(0);}//2.Tuling// std::cout<<"我# "<<message <<std::endl;std::string echo = rt.Talk(message);std::cout<<"Boyfriend# " << echo<< std::endl;if(sr.TTS(echo)){this->Play();}}// else{// std::cerr<<"Recognize error..." << std::endl;// }}else{std::cerr << "Record error..." << std::endl;}// sleep(2);}#ifdef _LOG_close(fd);#endif}~Boyfriend(){}};● 調用邏輯
#Boyfriend.cc#include "Boyfriend.hpp"using namespace std;int main(){//Robot r;//string str;//volatile bool quit = false;//while(!quit){// cout << "我# ";// cin >> str;// std::string s = r.Talk(str);// cout << "Tom$ " << s << endl;// }// std::string s = r.Talk("你好嗎?");// cout << s << endl;Boyfriend *bf = new Boyfriend();if(!bf->LoadEtc()){return 1;}bf->Run();return 0;}● command.etc命令配置文件
#command.etc查看當前目錄:ls -l關閉防火墻:systemctl stop firewalld打開防火墻:systemctl start firewalld跑火車:sl黑客帝國:cmatrix -B -C blue查看黑名單:cat black_name.txt你給我閨蜜唱首歌:aplay 李森茂_-_生日快樂歌(吉他改編版).wav● Makefile配置環境變量
#MakefileCC=g++#編譯器bin=Boyfriend#生成的可執行文件src=Boyfriend.cc#依賴的源文件INCLUDE=-Ispeech/LIB=-ljsoncpp -lcurl -lcrypto -lpthread$(bin):$(src)#生成bin,依賴的src$(CC) -o $@ $^ $(INCLUDE) $(LIB)#方法.PHONY:cleanclean:rm -f $(bin)代碼實現
智能語音對話AI
難點
jsoncpp的使用方法講解:
- 什么是json
- 有什么特點
- 為什么要用它
- StreamWriterBuilder、StreamWriter、CharReaderBuilder、CharReader、write函數、parse函數與Json:Value的使用
總結:json還支持嵌套,如json里面包含“json”,甚至json還包含”json數組“等,但是目前jsoncpp我們以簡單使用為主。
總結&項目擴展
- 整體來講,項目的難度不大,核心點在于對各個工具,平臺的熟悉程度。
- 我從這個項目中吸收的東西是: 學會使用第三方平臺,第三方工具,就能完成很有意思的功能。
擴展:
- 將該項目移植到windows中, 語音控制windows上各個軟件的打開和關閉,豈不酷炫
- 能否移植到手機端呢?如找一個js頁面,在服務器上部署服務,使用手機遠程控制服務器(筆記本)
- 可以在樹莓派上,安裝一些第三方驅動或者組件(如,燈),語音控制燈的開啟和關閉燈,再調研一下百度的其他語音或者文本功能做這類項目,就應該玩起來。
總結
以上是生活随笔為你收集整理的项目:智能语音对话机器人的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: linux显示光盘命令行,使用wodim
- 下一篇: linux sql语句传参数,Linux
