chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
# GRPC python Client for 2pass decoding
|
||||
The client can send streaming or full audio data to server as you wish, and get transcribed text once the server respond (depends on mode)
|
||||
|
||||
In the demo client, audio_chunk_duration is set to 1000ms, and send_interval is set to 100ms
|
||||
|
||||
### 1. Install the requirements
|
||||
```shell
|
||||
git clone https://github.com/alibaba/FunASR.git && cd FunASR/funasr/runtime/python/grpc
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 2. Generate protobuf file
|
||||
```shell
|
||||
# paraformer_pb2.py and paraformer_pb2_grpc.py are already generated,
|
||||
# regenerate it only when you make changes to ./proto/paraformer.proto file.
|
||||
python -m grpc_tools.protoc --proto_path=./proto -I ./proto --python_out=. --grpc_python_out=./ ./proto/paraformer.proto
|
||||
```
|
||||
|
||||
### 3. Start grpc client
|
||||
```
|
||||
# Start client.
|
||||
python grpc_main_client.py --host 127.0.0.1 --port 10100 --wav_path /path/to/your_test_wav.wav
|
||||
```
|
||||
|
||||
## Acknowledge
|
||||
1. This project is maintained by [FunASR community](https://github.com/modelscope/FunASR).
|
||||
2. We acknowledge burkliu (刘柏基, liubaiji@xverse.cn) for contributing the grpc service.
|
||||
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
Copyright FunASR (https://github.com/alibaba-damo-academy/FunASR). All Rights
|
||||
Reserved. MIT License (https://opensource.org/licenses/MIT)
|
||||
2023 by burkliu(刘柏基) liubaiji@xverse.cn
|
||||
"""
|
||||
|
||||
import logging
|
||||
import argparse
|
||||
import soundfile as sf
|
||||
import time
|
||||
|
||||
import grpc
|
||||
import paraformer_pb2_grpc
|
||||
from paraformer_pb2 import Request, WavFormat, DecodeMode
|
||||
|
||||
|
||||
class GrpcClient:
|
||||
def __init__(self, wav_path, uri, mode):
|
||||
self.wav, self.sampling_rate = sf.read(wav_path, dtype="int16")
|
||||
self.wav_format = WavFormat.pcm
|
||||
self.audio_chunk_duration = 1000 # ms
|
||||
self.audio_chunk_size = int(self.sampling_rate * self.audio_chunk_duration / 1000)
|
||||
self.send_interval = 100 # ms
|
||||
self.mode = mode
|
||||
|
||||
# connect to grpc server
|
||||
channel = grpc.insecure_channel(uri)
|
||||
self.stub = paraformer_pb2_grpc.ASRStub(channel)
|
||||
|
||||
# start request
|
||||
for respond in self.stub.Recognize(self.request_iterator()):
|
||||
logging.info(
|
||||
"[receive] mode {}, text {}, is final {}".format(
|
||||
DecodeMode.Name(respond.mode), respond.text, respond.is_final
|
||||
)
|
||||
)
|
||||
|
||||
def request_iterator(self, mode=DecodeMode.two_pass):
|
||||
is_first_pack = True
|
||||
is_final = False
|
||||
for start in range(0, len(self.wav), self.audio_chunk_size):
|
||||
request = Request()
|
||||
audio_chunk = self.wav[start : start + self.audio_chunk_size]
|
||||
|
||||
if is_first_pack:
|
||||
is_first_pack = False
|
||||
request.sampling_rate = self.sampling_rate
|
||||
request.mode = self.mode
|
||||
request.wav_format = self.wav_format
|
||||
if request.mode == DecodeMode.two_pass or request.mode == DecodeMode.online:
|
||||
request.chunk_size.extend([5, 10, 5])
|
||||
|
||||
if start + self.audio_chunk_size >= len(self.wav):
|
||||
is_final = True
|
||||
request.is_final = is_final
|
||||
request.audio_data = audio_chunk.tobytes()
|
||||
logging.info(
|
||||
"[request] audio_data len {}, is final {}".format(
|
||||
len(request.audio_data), request.is_final
|
||||
)
|
||||
) # int16 = 2bytes
|
||||
time.sleep(self.send_interval / 1000)
|
||||
yield request
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(filename="", format="%(asctime)s %(message)s", level=logging.INFO)
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--host", type=str, default="127.0.0.1", required=False, help="grpc server host ip"
|
||||
)
|
||||
parser.add_argument("--port", type=int, default=10100, required=False, help="grpc server port")
|
||||
parser.add_argument("--wav_path", type=str, required=True, help="audio wav path")
|
||||
args = parser.parse_args()
|
||||
|
||||
for mode in [DecodeMode.offline, DecodeMode.online, DecodeMode.two_pass]:
|
||||
mode_name = DecodeMode.Name(mode)
|
||||
logging.info("[request] start requesting with mode {}".format(mode_name))
|
||||
|
||||
st = time.time()
|
||||
uri = "{}:{}".format(args.host, args.port)
|
||||
client = GrpcClient(args.wav_path, uri, mode)
|
||||
logging.info("mode {}, time pass: {}".format(mode_name, time.time() - st))
|
||||
@@ -0,0 +1,25 @@
|
||||
```
|
||||
service ASR { //grpc service
|
||||
rpc Recognize (stream Request) returns (stream Response) {} //Stub
|
||||
}
|
||||
|
||||
message Request { //request data
|
||||
bytes audio_data = 1; //audio data in bytes.
|
||||
string user = 2; //user allowed.
|
||||
string language = 3; //language, zh-CN for now.
|
||||
bool speaking = 4; //flag for speaking.
|
||||
bool isEnd = 5; //flag for end. set isEnd to true when you stop asr:
|
||||
//vad:is_speech then speaking=True & isEnd = False, audio data will be appended for the specfied user.
|
||||
//vad:silence then speaking=False & isEnd = False, clear audio buffer and do asr inference.
|
||||
}
|
||||
|
||||
message Response { //response data.
|
||||
string sentence = 1; //json, includes flag for success and asr text .
|
||||
string user = 2; //same to request user.
|
||||
string language = 3; //same to request language.
|
||||
string action = 4; //server status:
|
||||
//terminate:asr stopped;
|
||||
//speaking:user is speaking, audio data is appended;
|
||||
//decoding: server is decoding;
|
||||
//finish: get asr text, most used.
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright FunASR (https://github.com/alibaba-damo-academy/FunASR). All Rights
|
||||
// Reserved. MIT License (https://opensource.org/licenses/MIT)
|
||||
//
|
||||
// 2023 by burkliu(刘柏基) liubaiji@xverse.cn
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
option objc_class_prefix = "paraformer";
|
||||
|
||||
package paraformer;
|
||||
|
||||
service ASR {
|
||||
rpc Recognize (stream Request) returns (stream Response) {}
|
||||
}
|
||||
|
||||
enum WavFormat {
|
||||
pcm = 0;
|
||||
}
|
||||
|
||||
enum DecodeMode {
|
||||
offline = 0;
|
||||
online = 1;
|
||||
two_pass = 2;
|
||||
}
|
||||
|
||||
message Request {
|
||||
DecodeMode mode = 1;
|
||||
WavFormat wav_format = 2;
|
||||
int32 sampling_rate = 3;
|
||||
repeated int32 chunk_size = 4;
|
||||
bool is_final = 5;
|
||||
bytes audio_data = 6;
|
||||
}
|
||||
|
||||
message Response {
|
||||
DecodeMode mode = 1;
|
||||
string text = 2;
|
||||
bool is_final = 3;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1,2 @@
|
||||
grpcio
|
||||
grpcio-tools
|
||||
Reference in New Issue
Block a user