6 changed files with 112 additions and 301 deletions
-
6cmakepc.cmake
-
2dep/zlinuxcomponents
-
128src/service/voiceprocess/asr_service.cpp
-
90src/service/voiceprocess/asr_service.hpp
-
108src/test_aiui_service.cpp
-
79src/test_asr_main.cpp
@ -1 +1 @@ |
|||
Subproject commit 2344b60385743afbe743660579ee72e8e9760552 |
|||
Subproject commit a72b77a07bfe7c79abaf603998d98c63a18a7328 |
@ -1,128 +0,0 @@ |
|||
#include "asr_service.hpp"
|
|||
|
|||
#include "iflytopcpp/core/components/audio/wavheader.hpp"
|
|||
#include "zlinuxcomponents/aiui_ws/aiui.h"
|
|||
using namespace iflytop; |
|||
using namespace core; |
|||
using namespace std; |
|||
|
|||
static AiuiService *thisClass = nullptr; |
|||
static string getTTSFileName() { |
|||
static int i = 0; |
|||
i++; |
|||
if (i > 10) i = 0; |
|||
return fmt::format("/tmp/aiui_service_tts{}.wav", i); |
|||
} |
|||
|
|||
/**
|
|||
* aiui的识别结果返回大致如下,先返回一个nlp识别结果的包,然后再返回多个包含tts音频数据的json包 |
|||
* nlp->tts0->tts1->...->ttsn |
|||
* 1. 通过json["data"]["sub"]来判断是什么包,sub的值有:nlp,tts |
|||
* 2. 通过json["data"]["is_last"]判断是否是当前种类的最后一包. |
|||
* 3. 通过json["data"]["is_finish"]判断是否是本次传输的最后一包 |
|||
* |
|||
*/ |
|||
extern "C" { |
|||
extern size_t aiui_base64_decode(char *source, unsigned char *target, size_t targetlen); |
|||
} |
|||
void aiui_message_cb(const char *data, int len) { |
|||
if (thisClass) { |
|||
thisClass->call_aiui_message_cb(data, len); |
|||
} |
|||
} |
|||
void aiui_error_cb(int code, const char *str) { |
|||
if (thisClass) { |
|||
thisClass->call_aiui_error_cb(code, str); |
|||
} |
|||
} |
|||
AiuiService::AiuiService() { thisClass = this; } |
|||
int AiuiService::aiuiInit(const char *appid, const char *key, const char *param) { |
|||
thisClass = this; |
|||
return aiui_init(appid, key, param, aiui_message_cb, aiui_error_cb); |
|||
} |
|||
int AiuiService::aiuiWrite(const char *audio, int len) { return aiui_write(audio, len); } |
|||
int AiuiService::aiuiFinished() { return aiui_finished(); } |
|||
void AiuiService::aiuiDestroy() { |
|||
aiui_destroy(); |
|||
thisClass = nullptr; |
|||
} |
|||
void AiuiService::parseTTSContent(json &rxjson) { |
|||
if (!oneAsrResultTransmition) { |
|||
logger->error("oneAsrResultTransmition is null"); |
|||
return; |
|||
} |
|||
/**
|
|||
* @brief 解码base64数据,并保存起来 |
|||
*/ |
|||
string base64Data = rxjson["data"]["content"].get<string>(); |
|||
size_t size = base64Data.size() * 3 / 4 + 50; |
|||
shared_ptr<Binary> binary = make_shared<Binary>(size); |
|||
size_t realsize = aiui_base64_decode((char *)base64Data.c_str(), binary->data(), size); |
|||
binary->resize(realsize); |
|||
oneAsrResultTransmition->ttsRawData.push_back(binary); |
|||
} |
|||
|
|||
void AiuiService::endOneAsrResultTransmition() { |
|||
/**
|
|||
* @brief 如果是最后一包,则将接收到的tts保存成文件,然后同nlp结果打包在一起,然后上报。 |
|||
*/ |
|||
string ttsFileName = getTTSFileName(); |
|||
FILE *fp = fopen(ttsFileName.c_str(), "wb"); |
|||
size_t ttsframetotalsize = 0; |
|||
for (auto &binary : oneAsrResultTransmition->ttsRawData) { |
|||
ttsframetotalsize += binary->size(); |
|||
} |
|||
WAVHeader wavHeader(16000, 16, 1, ttsframetotalsize / 2); |
|||
if (fp) { |
|||
fwrite(wavHeader.data(), 1, wavHeader.size(), fp); |
|||
for (auto &binary : oneAsrResultTransmition->ttsRawData) { |
|||
fwrite(binary->data(), 1, binary->size(), fp); |
|||
ttsframetotalsize += binary->size(); |
|||
} |
|||
fclose(fp); |
|||
} |
|||
oneAsrResultTransmition->asrResult["data"]["intent"]["answer"]["ttsurl"] = ttsFileName; |
|||
/**
|
|||
* @brief 上报识别结果 |
|||
*/ |
|||
onAsrResult(oneAsrResultTransmition->asrResult); |
|||
oneAsrResultTransmition.reset(); |
|||
} |
|||
|
|||
void AiuiService::call_aiui_message_cb(const char *data, int len) { |
|||
try { |
|||
if (!oneAsrResultTransmition) { |
|||
oneAsrResultTransmition = make_unique<OneAsrResultTransmition>(); |
|||
logger->info("start rx aiui data"); |
|||
} |
|||
json rxjson = json::parse(data); |
|||
if (rxjson["action"].get<string>() != "result") { |
|||
return; |
|||
} |
|||
|
|||
/**
|
|||
* @brief 处理接收到的数据 |
|||
*/ |
|||
if (rxjson["data"]["sub"].get<string>() == "nlp") { |
|||
// 解析nlpcontent
|
|||
oneAsrResultTransmition->asrResult = rxjson; |
|||
} else if (rxjson["data"]["sub"].get<string>() == "tts") { |
|||
// 解析ttscontent
|
|||
parseTTSContent(rxjson); |
|||
} |
|||
/**
|
|||
* @brief 结束本次接收 |
|||
*/ |
|||
if (rxjson["data"]["is_finish"].get<bool>()) { |
|||
logger->info("end rx aiui data"); |
|||
// will call onAsrResult in this function
|
|||
endOneAsrResultTransmition(); |
|||
} |
|||
} catch (const std::exception &e) { |
|||
logger->error("AiuiService::call_aiui_message_cb error: {}", e.what()); |
|||
} |
|||
} |
|||
void AiuiService::call_aiui_error_cb(int code, const char *str) { |
|||
logger->error("AiuiService::call_aiui_error_cb error: {} => {}", code, str); |
|||
onError(code, str); |
|||
} |
@ -1,90 +0,0 @@ |
|||
//
|
|||
// Created by zwsd
|
|||
//
|
|||
|
|||
#pragma once
|
|||
#include <fstream>
|
|||
#include <iostream>
|
|||
#include <list>
|
|||
#include <map>
|
|||
#include <memory>
|
|||
#include <set>
|
|||
#include <sstream>
|
|||
#include <string>
|
|||
#include <vector>
|
|||
|
|||
#include "iflytopcpp/core/basic/ds/binary.hpp"
|
|||
#include "iflytopcpp/core/basic/nlohmann/json.hpp"
|
|||
#include "iflytopcpp/core/basic/nod/nod.hpp"
|
|||
#include "iflytopcpp/core/spdlogfactory/logger.hpp"
|
|||
#include "iflytopcpp/core/thread/thread.hpp"
|
|||
|
|||
/**
|
|||
* @brief |
|||
* |
|||
* service: AsrService |
|||
* |
|||
* 监听事件: |
|||
* 依赖状态: |
|||
* 依赖服务: |
|||
* 作用: |
|||
* |
|||
*/ |
|||
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
using namespace core; |
|||
using namespace nlohmann; |
|||
|
|||
class OneAsrResultTransmition { |
|||
public: |
|||
json asrResult; |
|||
list<json> ttsResult; |
|||
list<shared_ptr<Binary>> ttsRawData; |
|||
}; |
|||
|
|||
class AiuiService : public enable_shared_from_this<AiuiService> { |
|||
ENABLE_LOGGER(AiuiService); |
|||
|
|||
bool transFinished = false; |
|||
unique_ptr<OneAsrResultTransmition> oneAsrResultTransmition; |
|||
|
|||
public: |
|||
nod::signal<void(json &asrResult)> onAsrResult; |
|||
nod::signal<void(int code, const char *str)> onError; |
|||
|
|||
AiuiService(); |
|||
|
|||
int aiuiInit(const char *appid, const char *key, const char *param); |
|||
int aiuiWrite(const char *audio, int len); |
|||
int aiuiFinished(); |
|||
void aiuiDestroy(); |
|||
|
|||
void call_aiui_message_cb(const char *data, int len); |
|||
void call_aiui_error_cb(int code, const char *str); |
|||
|
|||
private: |
|||
void parseTTSContent(json &rxjson); |
|||
void endOneAsrResultTransmition(); |
|||
}; |
|||
|
|||
class AsrService : public enable_shared_from_this<AsrService> { |
|||
ENABLE_LOGGER(AsrService); |
|||
|
|||
public: |
|||
nod::signal<void(json &asrResult)> onAsrResult; |
|||
nod::signal<void()> onVoiceEnd; |
|||
|
|||
private: |
|||
//
|
|||
public: |
|||
AsrService(){}; |
|||
|
|||
void initialize(string appid, string key); |
|||
void startRequest(); |
|||
void endRequest(); |
|||
void writeVoice(uint16_t *voice, size_t voiceLen); |
|||
void writeVoice(string text); |
|||
void writeVoiceEnd(); |
|||
}; |
|||
} // namespace iflytop
|
@ -0,0 +1,108 @@ |
|||
#include "zlinuxcomponents/zmainhelper.hpp"
|
|||
//
|
|||
#include "configs/config.hpp"
|
|||
#include "iflytopcpp/core/spdlogfactory/logger.hpp"
|
|||
#include "iflytopcpp/core/thread/thread.hpp"
|
|||
#include "spdlog/spdlog.h"
|
|||
#include "version.hpp"
|
|||
#include "zlinuxcomponents/rootfs_auto_update/rootfs_auto_update.hpp"
|
|||
#include "zservice_container/zservice_container.hpp"
|
|||
//
|
|||
#include "service/device_io_service.hpp"
|
|||
#include "service/device_io_service_mock.hpp"
|
|||
#include "service/light_control_service.hpp"
|
|||
#include "service/report_service.hpp"
|
|||
#include "zlinuxcomponents/aiui_ws/aiui_service.hpp"
|
|||
|
|||
//
|
|||
#include "zlinuxcomponents/alsaplayer/AudioPlayerAlsaImpl.hpp"
|
|||
// #include "zlinuxcomponents/audio/audio_recoder.hpp"
|
|||
#include <curl/curl.h>
|
|||
|
|||
#include <iostream>
|
|||
#include <string>
|
|||
|
|||
#include "zlinuxcomponents/aiui_ws/aiui.h"
|
|||
|
|||
//
|
|||
using namespace iflytop; |
|||
using namespace core; |
|||
using namespace std; |
|||
using namespace clipp; |
|||
|
|||
ZMAIN(); |
|||
void Main::onSIGINT() { exit(0); } |
|||
int Main::main(int argc, char *argv[]) { |
|||
string g_host_server_ip; |
|||
string g_device_id; |
|||
spdlog::flush_on(spdlog::level::debug); |
|||
|
|||
const char *appid = "5938b7c7"; // 应用ID,在AIUI开放平台创建并设置
|
|||
const char *key = "19c1f7becc78eedc7826b485aabe30de"; // 接口密钥,在AIUI开放平台查看
|
|||
const char *param = |
|||
"{\"result_level\":\"plain\",\"auth_id\":\"ac30105366ea460f9ff08ddac0c4f71e\",\"data_" |
|||
"type\":\"text\"," |
|||
"\"scene\":\"main_box\",\"sample_rate\":\"16000\", " |
|||
"\"context\":\"{\\\"sdk_support\\\":[\\\"nlp\\\",\\\"tts\\\"]}\"}"; |
|||
|
|||
json paramj; |
|||
paramj["result_level"] = "plain"; |
|||
paramj["auth_id"] = "ac30105366ea460f9ff08ddac0c4f71e"; |
|||
paramj["data_type"] = "text"; |
|||
paramj["scene"] = "main_box"; |
|||
paramj["sample_rate"] = "16000"; |
|||
paramj["context"] = R"({"sdk_support":["nlp","tts","vad","iat"]})"; |
|||
// logger->info("{}", paramj.dump());
|
|||
// logger->info("{}", param);
|
|||
|
|||
shared_ptr<AiuiService> aiuiService(new AiuiService()); |
|||
logger->info("test_asr_main.cpp"); |
|||
aiuiService->initialize(appid, key, paramj.dump()); |
|||
aiuiService->aiuiInit(); |
|||
aiuiService->onMessage.connect([&](json &rxjson) { |
|||
//
|
|||
string action = rxjson["action"]; |
|||
if (action == "started") { |
|||
logger->info("rx started:{}", rxjson.dump()); |
|||
} |
|||
//
|
|||
else if (action == "result") { |
|||
string sub = rxjson["data"]["sub"]; |
|||
if (sub == "nlp") { |
|||
logger->info("rx nlp:{}", rxjson.dump()); |
|||
} else if (sub == "tts") { |
|||
logger->info("rx tts:frame {}", rxjson["data"]["json_args"]["frame_id"].get<int>()); |
|||
bool isendFrame = false; |
|||
string ttsurl; |
|||
aiuiService->parseTTSContent(rxjson, isendFrame, ttsurl); |
|||
if (isendFrame) { |
|||
logger->info("rx tts end,url={}", ttsurl); |
|||
} |
|||
} else if (sub == "iat") { |
|||
logger->info("rx iat:{}", rxjson.dump()); |
|||
} else if (sub == "vad") { |
|||
logger->info("rx vad:{}", rxjson.dump()); |
|||
} else { |
|||
logger->info("rx {}:{}", sub, rxjson.dump()); |
|||
} |
|||
} |
|||
//
|
|||
else if (action == "error") { |
|||
logger->info("rx error:{}", rxjson.dump()); |
|||
} |
|||
//
|
|||
else if (action == "vad") { |
|||
} else { |
|||
logger->info("rx unkown:{}", rxjson.dump()); |
|||
} |
|||
|
|||
try { |
|||
if (rxjson["data"]["is_finish"].get<bool>()) { |
|||
logger->info("end tx"); |
|||
} |
|||
} catch (...) { |
|||
} |
|||
}); |
|||
aiuiService->aiuiWrite("今天天气怎么样", strlen("今天天气怎么样")); |
|||
while (true) sleep(1000); |
|||
} |
@ -1,79 +0,0 @@ |
|||
#include "zlinuxcomponents/zmainhelper.hpp"
|
|||
//
|
|||
#include "configs/config.hpp"
|
|||
#include "iflytopcpp/core/spdlogfactory/logger.hpp"
|
|||
#include "iflytopcpp/core/thread/thread.hpp"
|
|||
#include "spdlog/spdlog.h"
|
|||
#include "version.hpp"
|
|||
#include "zlinuxcomponents/rootfs_auto_update/rootfs_auto_update.hpp"
|
|||
#include "zservice_container/zservice_container.hpp"
|
|||
#include "zwebservice/zwebservice.hpp"
|
|||
//
|
|||
#include "service/device_io_service.hpp"
|
|||
#include "service/device_io_service_mock.hpp"
|
|||
#include "service/light_control_service.hpp"
|
|||
#include "service/main_control_service.hpp"
|
|||
#include "service/report_service.hpp"
|
|||
#include "service/voiceprocess/asr_service.hpp"
|
|||
//
|
|||
#include "zlinuxcomponents/alsaplayer/AudioPlayerAlsaImpl.hpp"
|
|||
// #include "zlinuxcomponents/audio/audio_recoder.hpp"
|
|||
#include <curl/curl.h>
|
|||
|
|||
#include <iostream>
|
|||
#include <string>
|
|||
|
|||
#include "zlinuxcomponents/aiui_ws/aiui.h"
|
|||
|
|||
//
|
|||
using namespace iflytop; |
|||
using namespace core; |
|||
using namespace std; |
|||
using namespace clipp; |
|||
|
|||
ZMAIN(); |
|||
/***********************************************************************************************************************
|
|||
* =======================================================Main======================================================== * |
|||
***********************************************************************************************************************/ |
|||
static void onmessage(const char *data, int len) {} |
|||
static void onerror(int code, const char *str) { printf("aiui_init onerror %d => %s\n", code, str); } |
|||
|
|||
void Main::onSIGINT() { exit(0); } |
|||
|
|||
int Main::main(int argc, char *argv[]) { |
|||
string g_host_server_ip; |
|||
string g_device_id; |
|||
spdlog::flush_on(spdlog::level::debug); |
|||
|
|||
const char *appid = "5938b7c7"; // 应用ID,在AIUI开放平台创建并设置
|
|||
const char *key = "19c1f7becc78eedc7826b485aabe30de"; // 接口密钥,在AIUI开放平台查看
|
|||
const char *param = |
|||
"{\"result_level\":\"plain\",\"auth_id\":\"ac30105366ea460f9ff08ddac0c4f71e\",\"data_" |
|||
"type\":\"text\"," |
|||
"\"scene\":\"main_box\",\"sample_rate\":\"16000\", " |
|||
"\"context\":\"{\\\"sdk_support\\\":[\\\"nlp\\\",\\\"tts\\\"]}\"}"; |
|||
shared_ptr<AiuiService> aiuiService(new AiuiService()); |
|||
logger->info("test_asr_main.cpp"); |
|||
aiuiService->aiuiInit(appid, key, param); |
|||
aiuiService->onAsrResult.connect([this](json j) { |
|||
logger->info("onAsrResult: {}", j.dump(2)); |
|||
}); |
|||
aiuiService->aiuiWrite("今天天气怎么样", strlen("今天天气怎么样")); |
|||
// aiuiService->aiuiFinished();
|
|||
// aiuiService->aiuiDestroy();
|
|||
#if 0
|
|||
|
|||
|
|||
aiui_init(appid, key, param, onmessage, onerror); |
|||
|
|||
const char *text = "播放音乐"; |
|||
|
|||
aiui_write(text, strlen(text)); |
|||
|
|||
aiui_finished(); |
|||
|
|||
aiui_destroy(); |
|||
#endif
|
|||
|
|||
while (true) sleep(1000); |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue