From 713cd5d128119c1494d1274c7addf1972d8aa4d0 Mon Sep 17 00:00:00 2001 From: dyyzhmm Date: Mon, 6 Mar 2023 22:50:44 +0800 Subject: [PATCH 1/9] grpc onnx cpp first commit --- funasr/runtime/grpc/CMakeLists.txt | 73 +++++++++ funasr/runtime/grpc/Readme.md | 49 ++++++ funasr/runtime/grpc/common.cmake | 125 +++++++++++++++ funasr/runtime/grpc/paraformer_server.cc | 193 +++++++++++++++++++++++ funasr/runtime/grpc/paraformer_server.h | 47 ++++++ funasr/runtime/grpc/rebuild.sh | 13 ++ 6 files changed, 500 insertions(+) create mode 100644 funasr/runtime/grpc/CMakeLists.txt create mode 100644 funasr/runtime/grpc/Readme.md create mode 100644 funasr/runtime/grpc/common.cmake create mode 100644 funasr/runtime/grpc/paraformer_server.cc create mode 100644 funasr/runtime/grpc/paraformer_server.h create mode 100644 funasr/runtime/grpc/rebuild.sh diff --git a/funasr/runtime/grpc/CMakeLists.txt b/funasr/runtime/grpc/CMakeLists.txt new file mode 100644 index 000000000..237ff4745 --- /dev/null +++ b/funasr/runtime/grpc/CMakeLists.txt @@ -0,0 +1,73 @@ +# Copyright 2018 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# cmake build file for C++ paraformer example. +# Assumes protobuf and gRPC have been installed using cmake. +# See cmake_externalproject/CMakeLists.txt for all-in-one cmake build +# that automatically builds all the dependencies before building paraformer. + +cmake_minimum_required(VERSION 3.10) + +project(ASR C CXX) + +include(common.cmake) + +# Proto file +get_filename_component(rg_proto "../python/grpc/proto/paraformer.proto" ABSOLUTE) +get_filename_component(rg_proto_path "${rg_proto}" PATH) + +# Generated sources +set(rg_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/paraformer.pb.cc") +set(rg_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/paraformer.pb.h") +set(rg_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/paraformer.grpc.pb.cc") +set(rg_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/paraformer.grpc.pb.h") +add_custom_command( + OUTPUT "${rg_proto_srcs}" "${rg_proto_hdrs}" "${rg_grpc_srcs}" "${rg_grpc_hdrs}" + COMMAND ${_PROTOBUF_PROTOC} + ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" + --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" + -I "${rg_proto_path}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" + "${rg_proto}" + DEPENDS "${rg_proto}") + + +# Include generated *.pb.h files +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + +# rg_grpc_proto +add_library(rg_grpc_proto + ${rg_grpc_srcs} + ${rg_grpc_hdrs} + ${rg_proto_srcs} + ${rg_proto_hdrs}) + + +target_link_libraries(rg_grpc_proto + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) + +# Targets paraformer_(server) +foreach(_target + paraformer_server) + add_executable(${_target} + "${_target}.cc") + target_link_libraries(${_target} + rg_grpc_proto + ${EXTRA_LIBS} + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) +endforeach() diff --git a/funasr/runtime/grpc/Readme.md b/funasr/runtime/grpc/Readme.md new file mode 100644 index 000000000..aabb79c54 --- /dev/null +++ b/funasr/runtime/grpc/Readme.md @@ -0,0 +1,49 @@ +## paraformer grpc onnx server + + + +#### compile and install grpc v1.52.0 in case of grpc bugs +``` +export GRPC_INSTALL_DIR=/data/soft/grpc +export PKG_CONFIG_PATH=$GRPC_INSTALL_DIR/lib/pkgconfig + +git clone -b v1.52.0 --depth=1 https://github.com/grpc/grpc.git +cd grpc +git submodule update --init --recursive + +mkdir -p cmake/build +pushd cmake/build +cmake -DgRPC_INSTALL=ON \ + -DgRPC_BUILD_TESTS=OFF \ + -DCMAKE_INSTALL_PREFIX=$GRPC_INSTALL_DIR \ + ../.. +make +popd + +echo "export GRPC_INSTALL_DIR=/data/soft/grpc" >> ~/.bashrc +echo "export PKG_CONFIG_PATH=\$GRPC_INSTALL_DIR/lib/pkgconfig" >> ~/.bashrc +echo "export PATH=\$GRPC_INSTALL_DIR/bin/:\$PKG_CONFIG_PATH:\$PATH" >> ~/.bashrc +source ~/.bashrc + +``` + + + +#### compile grpc onnx paraformer server +``` +#depends on ../onnxruntime +#file vocab.txt : UTF-8 Unicode text + +./rebuild.sh + +``` + + + +#### start grpc python paraformer client on PC with MIC +``` +cd ../python/grpc +python grpc_main_client_mic.py --host 127.0.0.1 --port 10108 +``` + + diff --git a/funasr/runtime/grpc/common.cmake b/funasr/runtime/grpc/common.cmake new file mode 100644 index 000000000..1326a5be3 --- /dev/null +++ b/funasr/runtime/grpc/common.cmake @@ -0,0 +1,125 @@ +# Copyright 2018 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# cmake build file for C++ route_guide example. +# Assumes protobuf and gRPC have been installed using cmake. +# See cmake_externalproject/CMakeLists.txt for all-in-one cmake build +# that automatically builds all the dependencies before building route_guide. + +cmake_minimum_required(VERSION 3.5.1) + +if (NOT DEFINED CMAKE_CXX_STANDARD) + set (CMAKE_CXX_STANDARD 14) +endif() + +if(MSVC) + add_definitions(-D_WIN32_WINNT=0x600) +endif() + +find_package(Threads REQUIRED) + +if(GRPC_AS_SUBMODULE) + # One way to build a projects that uses gRPC is to just include the + # entire gRPC project tree via "add_subdirectory". + # This approach is very simple to use, but the are some potential + # disadvantages: + # * it includes gRPC's CMakeLists.txt directly into your build script + # without and that can make gRPC's internal setting interfere with your + # own build. + # * depending on what's installed on your system, the contents of submodules + # in gRPC's third_party/* might need to be available (and there might be + # additional prerequisites required to build them). Consider using + # the gRPC_*_PROVIDER options to fine-tune the expected behavior. + # + # A more robust approach to add dependency on gRPC is using + # cmake's ExternalProject_Add (see cmake_externalproject/CMakeLists.txt). + + # Include the gRPC's cmake build (normally grpc source code would live + # in a git submodule called "third_party/grpc", but this example lives in + # the same repository as gRPC sources, so we just look a few directories up) + add_subdirectory(../../.. ${CMAKE_CURRENT_BINARY_DIR}/grpc EXCLUDE_FROM_ALL) + message(STATUS "Using gRPC via add_subdirectory.") + + # After using add_subdirectory, we can now use the grpc targets directly from + # this build. + set(_PROTOBUF_LIBPROTOBUF libprotobuf) + set(_REFLECTION grpc++_reflection) + if(CMAKE_CROSSCOMPILING) + find_program(_PROTOBUF_PROTOC protoc) + else() + set(_PROTOBUF_PROTOC $) + endif() + set(_GRPC_GRPCPP grpc++) + if(CMAKE_CROSSCOMPILING) + find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) + else() + set(_GRPC_CPP_PLUGIN_EXECUTABLE $) + endif() +elseif(GRPC_FETCHCONTENT) + # Another way is to use CMake's FetchContent module to clone gRPC at + # configure time. This makes gRPC's source code available to your project, + # similar to a git submodule. + message(STATUS "Using gRPC via add_subdirectory (FetchContent).") + include(FetchContent) + FetchContent_Declare( + grpc + GIT_REPOSITORY https://github.com/grpc/grpc.git + # when using gRPC, you will actually set this to an existing tag, such as + # v1.25.0, v1.26.0 etc.. + # For the purpose of testing, we override the tag used to the commit + # that's currently under test. + GIT_TAG vGRPC_TAG_VERSION_OF_YOUR_CHOICE) + FetchContent_MakeAvailable(grpc) + + # Since FetchContent uses add_subdirectory under the hood, we can use + # the grpc targets directly from this build. + set(_PROTOBUF_LIBPROTOBUF libprotobuf) + set(_REFLECTION grpc++_reflection) + set(_PROTOBUF_PROTOC $) + set(_GRPC_GRPCPP grpc++) + if(CMAKE_CROSSCOMPILING) + find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) + else() + set(_GRPC_CPP_PLUGIN_EXECUTABLE $) + endif() +else() + # This branch assumes that gRPC and all its dependencies are already installed + # on this system, so they can be located by find_package(). + + # Find Protobuf installation + # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. + set(protobuf_MODULE_COMPATIBLE TRUE) + find_package(Protobuf CONFIG REQUIRED) + message(STATUS "Using protobuf ${Protobuf_VERSION}") + + set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) + set(_REFLECTION gRPC::grpc++_reflection) + if(CMAKE_CROSSCOMPILING) + find_program(_PROTOBUF_PROTOC protoc) + else() + set(_PROTOBUF_PROTOC $) + endif() + + # Find gRPC installation + # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. + find_package(gRPC CONFIG REQUIRED) + message(STATUS "Using gRPC ${gRPC_VERSION}") + + set(_GRPC_GRPCPP gRPC::grpc++) + if(CMAKE_CROSSCOMPILING) + find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) + else() + set(_GRPC_CPP_PLUGIN_EXECUTABLE $) + endif() +endif() diff --git a/funasr/runtime/grpc/paraformer_server.cc b/funasr/runtime/grpc/paraformer_server.cc new file mode 100644 index 000000000..870cc1801 --- /dev/null +++ b/funasr/runtime/grpc/paraformer_server.cc @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "paraformer.grpc.pb.h" +#include "paraformer_server.h" + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::ServerReader; +using grpc::ServerReaderWriter; +using grpc::ServerWriter; +using grpc::Status; + + +using paraformer::Request; +using paraformer::Response; +using paraformer::ASR; + +ASRServicer::ASRServicer() { + std::cout << "ASRServicer init" << std::endl; + init_flag = 0; +} + +void ASRServicer::clear_states(const std::string& user) { + clear_buffers(user); + clear_transcriptions(user); +} + +void ASRServicer::clear_buffers(const std::string& user) { + if (client_buffers.count(user)) { + client_buffers.erase(user); + } +} + +void ASRServicer::clear_transcriptions(const std::string& user) { + if (client_transcription.count(user)) { + client_transcription.erase(user); + } +} + +void ASRServicer::disconnect(const std::string& user) { + clear_states(user); + std::cout << "Disconnecting user: " << user << std::endl; +} + +grpc::Status ASRServicer::Recognize( + grpc::ServerContext* context, + grpc::ServerReaderWriter* stream) { + + Request req; + while (stream->Read(&req)) { + if (req.isend()) { + std::cout << "asr end" << std::endl; + disconnect(req.user()); + Response res; + res.set_sentence( + R"({"success": true, "detail": "asr end"})" + ); + res.set_user(req.user()); + res.set_action("terminate"); + res.set_language(req.language()); + stream->Write(res); + } else if (req.speaking()) { + if (req.audio_data().size() > 0) { + auto& buf = client_buffers[req.user()]; + buf.insert(buf.end(), req.audio_data().begin(), req.audio_data().end()); + } + Response res; + res.set_sentence( + R"({"success": true, "detail": "speaking"})" + ); + res.set_user(req.user()); + res.set_action("speaking"); + res.set_language(req.language()); + stream->Write(res); + } else if (!req.speaking()) { + if (client_buffers.count(req.user()) == 0) { + Response res; + res.set_sentence( + R"({"success": true, "detail": "waiting_for_voice"})" + ); + res.set_user(req.user()); + res.set_action("waiting"); + res.set_language(req.language()); + stream->Write(res); + }else { + auto begin_time = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + std::string tmp_data = this->client_buffers[req.user()]; + this->clear_states(req.user()); + + Response res; + res.set_sentence( + R"({"success": true, "detail": "decoding data: " + std::to_string(tmp_data.length()) + " bytes"})" + ); + std::string data_len = std::to_string(tmp_data.length()); + std::stringstream ss; + ss << R"({"success": true, "detail": "decoding data: )" << data_len << R"( bytes")" << R"("})"; + std::string result = ss.str(); + res.set_sentence(result); + res.set_user(req.user()); + res.set_action("decoding"); + res.set_language(req.language()); + stream->Write(res); + if (tmp_data.length() < 800) { //min input_len for asr model + auto end_time = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + std::string delay_str = std::to_string(end_time - begin_time); + std::cout << "user: " << req.user() << " , delay(ms): " << delay_str << ", error: data_is_not_long_enough" << std::endl; + Response res; + std::stringstream ss; + std::string asr_result = ""; + ss << R"({"success": true, "detail": "finish_sentence","server_delay_ms":)" << delay_str << R"(,"text":")" << asr_result << R"("})"; + std::string result = ss.str(); + res.set_sentence(result); + res.set_user(req.user()); + res.set_action("finish"); + res.set_language(req.language()); + + + + stream->Write(res); + } + else { + + // asr_result = onnx.infer(tmp_data) + /* if (asr_result.find("text") != asr_result.end()) { + asr_result = asr_result["text"]; + } + else { + asr_result = ""; + } */ + + std::string asr_result = "你好你好,我是asr识别结果。static"; + + auto end_time = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + std::string delay_str = std::to_string(end_time - begin_time); + + std::cout << "user: " << req.user() << " , delay(ms): " << delay_str << ", text: " << asr_result << std::endl; + Response res; + std::stringstream ss; + ss << R"({"success": true, "detail": "finish_sentence","server_delay_ms":)" << delay_str << R"(,"text":")" << asr_result << R"("})"; + std::string result = ss.str(); + res.set_sentence(result); + res.set_user(req.user()); + res.set_action("finish"); + res.set_language(req.language()); + + + stream->Write(res); + } + } + }else { + Response res; + res.set_sentence( + R"({"success": false, "detail": "error, no condition matched! Unknown reason."})" + ); + res.set_user(req.user()); + res.set_action("terminate"); + res.set_language(req.language()); + stream->Write(res); + } + } + return Status::OK; +} + + +void RunServer() { + std::string server_address("0.0.0.0:10108"); + ASRServicer service; + + ServerBuilder builder; + builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); + builder.RegisterService(&service); + std::unique_ptr server(builder.BuildAndStart()); + std::cout << "Server listening on " << server_address << std::endl; + server->Wait(); +} + +int main(int argc, char** argv) { + RunServer(); + return 0; +} diff --git a/funasr/runtime/grpc/paraformer_server.h b/funasr/runtime/grpc/paraformer_server.h new file mode 100644 index 000000000..515f060b6 --- /dev/null +++ b/funasr/runtime/grpc/paraformer_server.h @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "paraformer.grpc.pb.h" + +#include +#include + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::ServerReader; +using grpc::ServerReaderWriter; +using grpc::ServerWriter; +using grpc::Status; + + +using paraformer::Request; +using paraformer::Response; +using paraformer::ASR; + + +class ASRServicer final : public ASR::Service { + private: + int init_flag; + std::unordered_map client_buffers; + std::unordered_map client_transcription; + + public: + ASRServicer(); + void clear_states(const std::string& user); + void clear_buffers(const std::string& user); + void clear_transcriptions(const std::string& user); + void disconnect(const std::string& user); + grpc::Status Recognize(grpc::ServerContext* context, grpc::ServerReaderWriter* stream); + +}; diff --git a/funasr/runtime/grpc/rebuild.sh b/funasr/runtime/grpc/rebuild.sh new file mode 100644 index 000000000..411c3d722 --- /dev/null +++ b/funasr/runtime/grpc/rebuild.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +rm cmake -rf +mkdir -p cmake/build + +cd cmake/build + +cmake ../.. +make + + +echo "Build cmake/build/paraformer_server successfully!" +echo "Let's start the server: cd cmake/build/ && ./paraformer_server" From d14daa8331573b638b0ab1e680632e39d67f180b Mon Sep 17 00:00:00 2001 From: dyyzhmm Date: Mon, 6 Mar 2023 22:55:00 +0800 Subject: [PATCH 2/9] Update Readme.md --- funasr/runtime/grpc/Readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/funasr/runtime/grpc/Readme.md b/funasr/runtime/grpc/Readme.md index aabb79c54..03f6f78ac 100644 --- a/funasr/runtime/grpc/Readme.md +++ b/funasr/runtime/grpc/Readme.md @@ -2,7 +2,7 @@ -#### compile and install grpc v1.52.0 in case of grpc bugs +#### Step 1. Compile and install grpc v1.52.0 in case of grpc bugs ``` export GRPC_INSTALL_DIR=/data/soft/grpc export PKG_CONFIG_PATH=$GRPC_INSTALL_DIR/lib/pkgconfig @@ -29,7 +29,7 @@ source ~/.bashrc -#### compile grpc onnx paraformer server +#### Step 2. Compile grpc onnx paraformer server ``` #depends on ../onnxruntime #file vocab.txt : UTF-8 Unicode text @@ -40,7 +40,7 @@ source ~/.bashrc -#### start grpc python paraformer client on PC with MIC +#### Step 3. Start grpc python paraformer client on PC with MIC ``` cd ../python/grpc python grpc_main_client_mic.py --host 127.0.0.1 --port 10108 From 9100825c0698abec2e49dd67a5360dc56d40a309 Mon Sep 17 00:00:00 2001 From: huangmingming Date: Tue, 7 Mar 2023 15:03:50 +0800 Subject: [PATCH 3/9] adjust include header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 去除重复的include --- funasr/runtime/grpc/paraformer_server.cc | 24 ------------------------ funasr/runtime/grpc/paraformer_server.h | 6 ++++-- 2 files changed, 4 insertions(+), 26 deletions(-) diff --git a/funasr/runtime/grpc/paraformer_server.cc b/funasr/runtime/grpc/paraformer_server.cc index 870cc1801..0ae241d1a 100644 --- a/funasr/runtime/grpc/paraformer_server.cc +++ b/funasr/runtime/grpc/paraformer_server.cc @@ -1,32 +1,8 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include "paraformer.grpc.pb.h" #include "paraformer_server.h" -using grpc::Server; -using grpc::ServerBuilder; -using grpc::ServerContext; -using grpc::ServerReader; -using grpc::ServerReaderWriter; -using grpc::ServerWriter; -using grpc::Status; - - -using paraformer::Request; -using paraformer::Response; -using paraformer::ASR; ASRServicer::ASRServicer() { std::cout << "ASRServicer init" << std::endl; diff --git a/funasr/runtime/grpc/paraformer_server.h b/funasr/runtime/grpc/paraformer_server.h index 515f060b6..614dd04be 100644 --- a/funasr/runtime/grpc/paraformer_server.h +++ b/funasr/runtime/grpc/paraformer_server.h @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #include #include @@ -13,8 +16,7 @@ #include "paraformer.grpc.pb.h" -#include -#include + using grpc::Server; using grpc::ServerBuilder; From 6de8dfea1c4d8bc8d2108af6f2fb6d807436c720 Mon Sep 17 00:00:00 2001 From: huangmingming Date: Wed, 8 Mar 2023 16:32:16 +0800 Subject: [PATCH 4/9] call api call rapidasr api --- funasr/runtime/grpc/CMakeLists.txt | 10 +++++++ funasr/runtime/grpc/Readme.md | 20 ++++++------- funasr/runtime/grpc/paraformer_server.cc | 38 +++++++++++++++++------- funasr/runtime/grpc/paraformer_server.h | 10 ++++--- funasr/runtime/grpc/rebuild.sh | 3 +- 5 files changed, 55 insertions(+), 26 deletions(-) diff --git a/funasr/runtime/grpc/CMakeLists.txt b/funasr/runtime/grpc/CMakeLists.txt index 237ff4745..56e307482 100644 --- a/funasr/runtime/grpc/CMakeLists.txt +++ b/funasr/runtime/grpc/CMakeLists.txt @@ -46,6 +46,13 @@ add_custom_command( # Include generated *.pb.h files include_directories("${CMAKE_CURRENT_BINARY_DIR}") +include_directories(../onnxruntime/include/) +link_directories(../onnxruntime/build/src/) +link_directories(../onnxruntime/build/third_party/webrtc/) + +link_directories(${ONNXRUNTIME_DIR}/lib) +add_subdirectory("../onnxruntime/src" onnx_src) + # rg_grpc_proto add_library(rg_grpc_proto ${rg_grpc_srcs} @@ -54,6 +61,7 @@ add_library(rg_grpc_proto ${rg_proto_hdrs}) + target_link_libraries(rg_grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} @@ -66,6 +74,8 @@ foreach(_target "${_target}.cc") target_link_libraries(${_target} rg_grpc_proto + rapidasr + webrtcvad ${EXTRA_LIBS} ${_REFLECTION} ${_GRPC_GRPCPP} diff --git a/funasr/runtime/grpc/Readme.md b/funasr/runtime/grpc/Readme.md index 03f6f78ac..57e86d1a2 100644 --- a/funasr/runtime/grpc/Readme.md +++ b/funasr/runtime/grpc/Readme.md @@ -1,8 +1,14 @@ ## paraformer grpc onnx server +#### build ../onnxruntime as it's document +``` +#put onnx lib and model into /data/asrmodel +ls /data/asrmodel/ +onnxruntime-linux-x64-1.14.0 speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch +``` -#### Step 1. Compile and install grpc v1.52.0 in case of grpc bugs +#### compile and install grpc v1.52.0 in case of grpc bugs ``` export GRPC_INSTALL_DIR=/data/soft/grpc export PKG_CONFIG_PATH=$GRPC_INSTALL_DIR/lib/pkgconfig @@ -24,26 +30,20 @@ echo "export GRPC_INSTALL_DIR=/data/soft/grpc" >> ~/.bashrc echo "export PKG_CONFIG_PATH=\$GRPC_INSTALL_DIR/lib/pkgconfig" >> ~/.bashrc echo "export PATH=\$GRPC_INSTALL_DIR/bin/:\$PKG_CONFIG_PATH:\$PATH" >> ~/.bashrc source ~/.bashrc - ``` - - -#### Step 2. Compile grpc onnx paraformer server +#### compile grpc onnx paraformer server ``` #depends on ../onnxruntime #file vocab.txt : UTF-8 Unicode text ./rebuild.sh - ``` -#### Step 3. Start grpc python paraformer client on PC with MIC +#### start grpc python paraformer client on PC with MIC ``` cd ../python/grpc -python grpc_main_client_mic.py --host 127.0.0.1 --port 10108 +python grpc_main_client_mic.py --host $server_ip --port 10108 ``` - - diff --git a/funasr/runtime/grpc/paraformer_server.cc b/funasr/runtime/grpc/paraformer_server.cc index 0ae241d1a..b721f0564 100644 --- a/funasr/runtime/grpc/paraformer_server.cc +++ b/funasr/runtime/grpc/paraformer_server.cc @@ -1,9 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "paraformer.grpc.pb.h" #include "paraformer_server.h" +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::ServerReader; +using grpc::ServerReaderWriter; +using grpc::ServerWriter; +using grpc::Status; + + +using paraformer::Request; +using paraformer::Response; +using paraformer::ASR; + ASRServicer::ASRServicer() { std::cout << "ASRServicer init" << std::endl; init_flag = 0; @@ -80,7 +105,8 @@ grpc::Status ASRServicer::Recognize( res.set_sentence( R"({"success": true, "detail": "decoding data: " + std::to_string(tmp_data.length()) + " bytes"})" ); - std::string data_len = std::to_string(tmp_data.length()); + int data_len_int = tmp_data.length(); + std::string data_len = std::to_string(data_len_int); std::stringstream ss; ss << R"({"success": true, "detail": "decoding data: )" << data_len << R"( bytes")" << R"("})"; std::string result = ss.str(); @@ -108,15 +134,7 @@ grpc::Status ASRServicer::Recognize( stream->Write(res); } else { - - // asr_result = onnx.infer(tmp_data) - /* if (asr_result.find("text") != asr_result.end()) { - asr_result = asr_result["text"]; - } - else { - asr_result = ""; - } */ - + RPASR_RESULT Result= RapidAsrRecogPCMBuffer(AsrHanlde, tmp_data.c_str(), data_len_int, RASR_NONE, NULL); std::string asr_result = "你好你好,我是asr识别结果。static"; auto end_time = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); diff --git a/funasr/runtime/grpc/paraformer_server.h b/funasr/runtime/grpc/paraformer_server.h index 614dd04be..f7cc7a60a 100644 --- a/funasr/runtime/grpc/paraformer_server.h +++ b/funasr/runtime/grpc/paraformer_server.h @@ -4,9 +4,6 @@ #include #include #include -#include -#include -#include #include #include @@ -14,8 +11,11 @@ #include #include -#include "paraformer.grpc.pb.h" +#include +#include +#include "paraformer.grpc.pb.h" +#include "librapidasrapi.h" using grpc::Server; @@ -45,5 +45,7 @@ class ASRServicer final : public ASR::Service { void clear_transcriptions(const std::string& user); void disconnect(const std::string& user); grpc::Status Recognize(grpc::ServerContext* context, grpc::ServerReaderWriter* stream); + int nThreadNum = 4; + RPASR_HANDLE AsrHanlde=RapidAsrInit("/data/asrmodel/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/", nThreadNum); }; diff --git a/funasr/runtime/grpc/rebuild.sh b/funasr/runtime/grpc/rebuild.sh index 411c3d722..9b41ed6d1 100644 --- a/funasr/runtime/grpc/rebuild.sh +++ b/funasr/runtime/grpc/rebuild.sh @@ -5,9 +5,8 @@ mkdir -p cmake/build cd cmake/build -cmake ../.. +cmake -DCMAKE_BUILD_TYPE=release ../.. -DONNXRUNTIME_DIR=/data/asrmodel/onnxruntime-linux-x64-1.14.0 make echo "Build cmake/build/paraformer_server successfully!" -echo "Let's start the server: cd cmake/build/ && ./paraformer_server" From 3972e3e4c34957164b6931ce49303aef3d58a5c9 Mon Sep 17 00:00:00 2001 From: huangmingming Date: Wed, 8 Mar 2023 16:42:25 +0800 Subject: [PATCH 5/9] Update Readme.md --- funasr/runtime/grpc/Readme.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/funasr/runtime/grpc/Readme.md b/funasr/runtime/grpc/Readme.md index 57e86d1a2..97b780dd8 100644 --- a/funasr/runtime/grpc/Readme.md +++ b/funasr/runtime/grpc/Readme.md @@ -1,14 +1,17 @@ ## paraformer grpc onnx server -#### build ../onnxruntime as it's document +#### Build ../onnxruntime as it's document ``` -#put onnx lib and model into /data/asrmodel +#put onnx-lib & onnx-asr-model & vocab.txt into /data/asrmodel ls /data/asrmodel/ onnxruntime-linux-x64-1.14.0 speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch + +file /data/asrmodel/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/vocab.txt +UTF-8 Unicode text ``` -#### compile and install grpc v1.52.0 in case of grpc bugs +#### Compile and install grpc v1.52.0 in case of grpc bugs ``` export GRPC_INSTALL_DIR=/data/soft/grpc export PKG_CONFIG_PATH=$GRPC_INSTALL_DIR/lib/pkgconfig @@ -32,17 +35,14 @@ echo "export PATH=\$GRPC_INSTALL_DIR/bin/:\$PKG_CONFIG_PATH:\$PATH" >> ~/.bashrc source ~/.bashrc ``` -#### compile grpc onnx paraformer server +#### Compile grpc onnx paraformer server ``` -#depends on ../onnxruntime -#file vocab.txt : UTF-8 Unicode text - ./rebuild.sh ``` -#### start grpc python paraformer client on PC with MIC +#### Start grpc python paraformer client on PC with MIC ``` cd ../python/grpc python grpc_main_client_mic.py --host $server_ip --port 10108 From ca55d704bd14fe0aea5dd395a56dfc725d07771d Mon Sep 17 00:00:00 2001 From: huangmingming Date: Wed, 8 Mar 2023 16:43:14 +0800 Subject: [PATCH 6/9] Update Readme.md --- funasr/runtime/grpc/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/funasr/runtime/grpc/Readme.md b/funasr/runtime/grpc/Readme.md index 97b780dd8..8f8612c68 100644 --- a/funasr/runtime/grpc/Readme.md +++ b/funasr/runtime/grpc/Readme.md @@ -1,4 +1,4 @@ -## paraformer grpc onnx server +## paraformer grpc onnx server in c++ #### Build ../onnxruntime as it's document From 49c00a7d6cb9c05d4bd0bb0fc8b59a2eed4b8950 Mon Sep 17 00:00:00 2001 From: huangmingming Date: Mon, 13 Mar 2023 12:07:11 +0800 Subject: [PATCH 7/9] grpc client remove VAD Remove webrtc-vad in grpc, do it with specified vad-model in server instead. --- .../python/grpc/grpc_main_client_mic.py | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/funasr/runtime/python/grpc/grpc_main_client_mic.py b/funasr/runtime/python/grpc/grpc_main_client_mic.py index acbe90bc2..220e8b5e1 100644 --- a/funasr/runtime/python/grpc/grpc_main_client_mic.py +++ b/funasr/runtime/python/grpc/grpc_main_client_mic.py @@ -1,7 +1,6 @@ import pyaudio import grpc import json -import webrtcvad import time import asyncio import argparse @@ -11,24 +10,16 @@ from paraformer_pb2_grpc import ASRStub async def deal_chunk(sig_mic): global stub,SPEAKING,asr_user,language,sample_rate - if vad.is_speech(sig_mic, sample_rate): #speaking - SPEAKING = True - response = transcribe_audio_bytes(stub, sig_mic, user=asr_user, language=language, speaking = True, isEnd = False) #speaking, send audio to server. - else: #silence - begin_time = 0 - if SPEAKING: #means we have some audio recorded, send recognize order to server. - SPEAKING = False - begin_time = int(round(time.time() * 1000)) - response = transcribe_audio_bytes(stub, None, user=asr_user, language=language, speaking = False, isEnd = False) #speak end, call server for recognize one sentence - resp = response.next() - if "decoding" == resp.action: - resp = response.next() #TODO, blocking operation may leads to miss some audio clips. C++ multi-threading is preferred. - if "finish" == resp.action: - end_time = int(round(time.time() * 1000)) - print (json.loads(resp.sentence)) - print ("delay in ms: %d " % (end_time - begin_time)) - else: - pass + + SPEAKING = True + resp = transcribe_audio_bytes(stub, sig_mic, user=asr_user, language=language, speaking = True, isEnd = False) #speaking, send audio to server. + + if "decoding" == resp.action: #partial result + print(json.loads(resp.sentence)) + elif "finish" == resp.action: #final result + print (json.loads(resp.sentence)) + + async def record(host,port,sample_rate,mic_chunk,record_seconds,asr_user,language): @@ -88,8 +79,6 @@ if __name__ == '__main__': language = 'zh-CN' - vad = webrtcvad.Vad() - vad.set_mode(1) FORMAT = pyaudio.paInt16 CHANNELS = 1 From 6866a649162b90b49d64c6ec264f2fdbd1309c91 Mon Sep 17 00:00:00 2001 From: huangmingming Date: Thu, 16 Mar 2023 15:22:13 +0800 Subject: [PATCH 8/9] update readme update readme --- funasr/runtime/grpc/Readme.md | 8 ++++---- funasr/runtime/grpc/rebuild.sh | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/funasr/runtime/grpc/Readme.md b/funasr/runtime/grpc/Readme.md index 8f8612c68..b8722c733 100644 --- a/funasr/runtime/grpc/Readme.md +++ b/funasr/runtime/grpc/Readme.md @@ -1,7 +1,7 @@ ## paraformer grpc onnx server in c++ -#### Build ../onnxruntime as it's document +#### Step 1. Build ../onnxruntime as it's document ``` #put onnx-lib & onnx-asr-model & vocab.txt into /data/asrmodel ls /data/asrmodel/ @@ -11,7 +11,7 @@ file /data/asrmodel/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-p UTF-8 Unicode text ``` -#### Compile and install grpc v1.52.0 in case of grpc bugs +#### Step 2. Compile and install grpc v1.52.0 in case of grpc bugs ``` export GRPC_INSTALL_DIR=/data/soft/grpc export PKG_CONFIG_PATH=$GRPC_INSTALL_DIR/lib/pkgconfig @@ -35,14 +35,14 @@ echo "export PATH=\$GRPC_INSTALL_DIR/bin/:\$PKG_CONFIG_PATH:\$PATH" >> ~/.bashrc source ~/.bashrc ``` -#### Compile grpc onnx paraformer server +#### Step 3. Compile and start grpc onnx paraformer server ``` ./rebuild.sh ``` -#### Start grpc python paraformer client on PC with MIC +#### Step 4. Start grpc python paraformer client on PC with MIC ``` cd ../python/grpc python grpc_main_client_mic.py --host $server_ip --port 10108 diff --git a/funasr/runtime/grpc/rebuild.sh b/funasr/runtime/grpc/rebuild.sh index 9b41ed6d1..4b7601267 100644 --- a/funasr/runtime/grpc/rebuild.sh +++ b/funasr/runtime/grpc/rebuild.sh @@ -10,3 +10,7 @@ make echo "Build cmake/build/paraformer_server successfully!" + +echo "Start server" + +./paraformer_server \ No newline at end of file From cd6d7d4ef09308dacea89cf7d5b4ce80cf84c456 Mon Sep 17 00:00:00 2001 From: huangmingming Date: Thu, 16 Mar 2023 15:37:08 +0800 Subject: [PATCH 9/9] resume vad in client resume vad in client --- .../python/grpc/grpc_main_client_mic.py | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/funasr/runtime/python/grpc/grpc_main_client_mic.py b/funasr/runtime/python/grpc/grpc_main_client_mic.py index 220e8b5e1..acbe90bc2 100644 --- a/funasr/runtime/python/grpc/grpc_main_client_mic.py +++ b/funasr/runtime/python/grpc/grpc_main_client_mic.py @@ -1,6 +1,7 @@ import pyaudio import grpc import json +import webrtcvad import time import asyncio import argparse @@ -10,16 +11,24 @@ from paraformer_pb2_grpc import ASRStub async def deal_chunk(sig_mic): global stub,SPEAKING,asr_user,language,sample_rate - - SPEAKING = True - resp = transcribe_audio_bytes(stub, sig_mic, user=asr_user, language=language, speaking = True, isEnd = False) #speaking, send audio to server. - - if "decoding" == resp.action: #partial result - print(json.loads(resp.sentence)) - elif "finish" == resp.action: #final result - print (json.loads(resp.sentence)) - - + if vad.is_speech(sig_mic, sample_rate): #speaking + SPEAKING = True + response = transcribe_audio_bytes(stub, sig_mic, user=asr_user, language=language, speaking = True, isEnd = False) #speaking, send audio to server. + else: #silence + begin_time = 0 + if SPEAKING: #means we have some audio recorded, send recognize order to server. + SPEAKING = False + begin_time = int(round(time.time() * 1000)) + response = transcribe_audio_bytes(stub, None, user=asr_user, language=language, speaking = False, isEnd = False) #speak end, call server for recognize one sentence + resp = response.next() + if "decoding" == resp.action: + resp = response.next() #TODO, blocking operation may leads to miss some audio clips. C++ multi-threading is preferred. + if "finish" == resp.action: + end_time = int(round(time.time() * 1000)) + print (json.loads(resp.sentence)) + print ("delay in ms: %d " % (end_time - begin_time)) + else: + pass async def record(host,port,sample_rate,mic_chunk,record_seconds,asr_user,language): @@ -79,6 +88,8 @@ if __name__ == '__main__': language = 'zh-CN' + vad = webrtcvad.Vad() + vad.set_mode(1) FORMAT = pyaudio.paInt16 CHANNELS = 1