diff --git a/recognition/v1/python3/README.md b/recognition/v1/python3/README.md index 11fb43a..72b7427 100644 --- a/recognition/v1/python3/README.md +++ b/recognition/v1/python3/README.md @@ -1,6 +1,6 @@ # Installation - $ pip3 install grpcio-tools + $ pip3 install grpcio-tools requests pyaudio $ python3 -m grpc_tools.protoc -I .. -I ../../../task/v1 --python_out=. --grpc_python_out=. ../recognition.proto ../../../task/v1/{storage,task}.proto # Usage diff --git a/recognition/v1/python3/recognize.py b/recognition/v1/python3/recognize.py index 434eab5..29a77b1 100755 --- a/recognition/v1/python3/recognize.py +++ b/recognition/v1/python3/recognize.py @@ -9,6 +9,11 @@ import recognition_pb2 import recognition_pb2_grpc +import requests +import pyaudio +import wave +import uuid +import base64 CHUNK_SIZE = 2048 SLEEP_TIME = 0.1 @@ -25,22 +30,60 @@ } +def auth(client_id, client_secret): + auth_code = base64.b64encode(bytes(f"{client_id}:{client_secret}", "ascii")).decode('ascii') + headers = { + "Content-Type": "application/x-www-form-urlencoded", + "RqUID": str(uuid.uuid4()), + "Authorization": f"Basic {auth_code}" + } + res = requests.post('https://salute.online.sberbank.ru:9443/api/v2/oauth', headers=headers, data="scope=SBER_SPEECH") + if res.ok: + data = res.json() + return res.json().get("access_token", None) + else: + print(f"Error {res.status_code}, {res.text}") + return None + def try_printing_request_id(md): for m in md: if m.key == 'x-request-id': print('RequestID:', m.value) -def generate_audio_chunks(path, chunk_size=CHUNK_SIZE, sleep_time=SLEEP_TIME): - with open(path, 'rb') as f: - for data in iter(lambda: f.read(chunk_size), b''): +def generate_audio_chunks(path, mic, recognition_options, chunk_size=CHUNK_SIZE, sleep_time=SLEEP_TIME): + if path: + with open(path, 'rb') as f: + for data in iter(lambda: f.read(chunk_size), b''): + yield recognition_pb2.RecognitionRequest(audio_chunk=data) + time.sleep(sleep_time) + elif mic: + audio = pyaudio.PyAudio() + stream = audio.open(format=pyaudio.paInt16, channels=1, + rate=recognition_options.sample_rate, input=True, + frames_per_buffer=CHUNK_SIZE) + print("Recording...") + while True: + data = stream.read(CHUNK_SIZE) yield recognition_pb2.RecognitionRequest(audio_chunk=data) - time.sleep(sleep_time) + else: + print("User --file or --mic argument") + exit(1) def recognize(args): + token = None + if not hasattr(args, "token"): + if not hasattr(args, "client_id") and not hasattr(args, "client_secret"): + print("Use token or client_id + client_secret arguments.") + exit(1) + else: + token = auth(args.client_id, args.client_secret) + else: + token = args.token + ssl_cred = grpc.ssl_channel_credentials() - token_cred = grpc.access_token_call_credentials(args.token) + token_cred = grpc.access_token_call_credentials(token) channel = grpc.secure_channel( args.host, @@ -51,7 +94,7 @@ def recognize(args): con = stub.Recognize(itertools.chain( (recognition_pb2.RecognitionRequest(options=args.recognition_options),), - generate_audio_chunks(args.file), + generate_audio_chunks(args.file, args.mic, args.recognition_options), )) try: @@ -82,7 +125,7 @@ def recognize(args): class Arguments: - NOT_RECOGNITION_OPTIONS = {'host', 'token', 'file', 'normalized_result', 'emotions_result'} + NOT_RECOGNITION_OPTIONS = {'host', 'token', 'client_id', 'client_secret', 'file', 'mic', 'normalized_result', 'emotions_result'} NOT_RECOGNITION_OPTIONS.update({'ca', 'cert', 'key'}) # diff DURATIONS = {'no_speech_timeout', 'max_speech_timeout', 'eou_timeout'} REPEATED = {'words'} @@ -114,8 +157,11 @@ def create_parser(): parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('--host', default='smartspeech.sber.ru', help='host:port of gRPC endpoint') - parser.add_argument('--token', required=True, default=argparse.SUPPRESS, help='access token') - parser.add_argument('--file', required=True, default=argparse.SUPPRESS, help='audio file for recognition') + parser.add_argument('--token', required=False, default=argparse.SUPPRESS, help='access token') + parser.add_argument('--client_id', required=False, default=argparse.SUPPRESS, help='client id (instead of token)') + parser.add_argument('--client_secret', required=False, default=argparse.SUPPRESS, help='client id (instead of token)') + parser.add_argument('--file', required=False, default="", help='audio file for recognition') + parser.add_argument('--mic', action='store_true', help=' ') parser.add_argument('--normalized-result', action='store_true', help='show normalized text') parser.add_argument('--emotions-result', action='store_true', help='show emotions result')