diff --git a/.gitignore b/.gitignore index 952646f..d88f73d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ __pycache__ audio/* -Text2Speech/tts-gc-key.json +tts-gc-key.json test.py +sandbox.py +logs.txt diff --git a/Command.py b/Command.py index 03c231f..697a6ec 100644 --- a/Command.py +++ b/Command.py @@ -16,6 +16,20 @@ from abc import ABC, abstractmethod # for abstract class and methods from fuzzywuzzy import fuzz +from threading import Thread, Event + +class RThread(Thread): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._return = None + + def run(self): + if self._target is not None: + self._return = self._target(*self._args, **self._kwargs) + + def join(self, *args, **kwargs): + super().join(*args, **kwargs) + return self._return class Command(ABC): _list = [] # list of all commands @@ -69,11 +83,11 @@ class Command(ABC): # abstract @abstractmethod - def start(this, string): # main method + def start(this, string): # main method pass @abstractmethod - def confirm(this): # optional method + def confirm(this): # optional method pass # static @@ -103,9 +117,27 @@ class Command(ABC): top = max( chances.values() ) / sum( chances.values() ) * 100 else: return list[0] - if( max( chances.values() ) < 1000 or top < 80): return list[0] print(chances) print(top) + #if( max( chances.values() ) < 800 or top < 80): return list[0] for i, chance in chances.items(): if chance == max( chances.values() ): return list[i] + + @staticmethod + def background(answer = ''): + def decorator(cmd): + def wrapper(text): + finish_event = Event() + thread = RThread(target=cmd, args=(text, finish_event)) + thread.start() + return { + 'type': 'background', + 'text': answer, + 'thread': { + 'thread': thread, + 'finish_event': finish_event, + } + } + return wrapper + return decorator diff --git a/SmallTalk/__init__.py b/SmallTalk/__init__.py index 032d576..74ca978 100644 --- a/SmallTalk/__init__.py +++ b/SmallTalk/__init__.py @@ -20,15 +20,20 @@ from .SmallTalk import * import datetime, time import math +from Command import Command +import time ################################################################################ -def method(): - return 'Я не понимаю' +def method(text): + return { + 'type': 'simple', + 'text': 'Я не понимаю', + } keywords = {} void = SmallTalk('Undefined', keywords) void.setStart(method) ################################################################################ -def method(): +def method(text): now = datetime.datetime.now() hours = now.hour%12 if now.hour else 12 minutes = now.minute @@ -92,7 +97,10 @@ def method(): return ' '.join(result) answer = f'Сейчас {get_str_num(hours, 0)} {str_hour}' if(minutes): answer += f', {get_str_num(minutes, 1)} {str_minute}' - return answer + return { + 'type': 'simple', + 'text': answer + } keywords = { 10: ['который час', 'сколько времени'], @@ -102,3 +110,20 @@ keywords = { ctime = SmallTalk('Current Time', keywords) ctime.setStart(method) ################################################################################ +# Only for tests +@Command.background('Запускаю фоновый процесс') +def method(text, finish_event): + time.sleep(10) + finish_event.set() + return { + 'text': 'Фоновый процесс завершен', + } + + +keywords = { + 10: ['тестирование', 'проверка', 'потоков', 'фоновых'], + 5: ['процессов',] +} +test = SmallTalk('Test threads', keywords) +test.setStart(method) +################################################################################ diff --git a/Text2Speech/TTS.py b/Text2Speech/TTS.py index 8b6bdf7..b4ddf1e 100644 --- a/Text2Speech/TTS.py +++ b/Text2Speech/TTS.py @@ -3,7 +3,7 @@ import os from pygame import mixer import time import mmap -os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "Text2Speech/archie-test-key.json" +import config class Speech: _list = [] @@ -35,14 +35,15 @@ class Speech: return Speech._list class Engine: - def __init__(this, name = 'ru-RU-Wavenet-B'): - os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "Text2Speech/tts-gc-key.json" - this._name = name + def __init__(this, name = 'ru-RU-Wavenet-B', language_code = config.language_code): + os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = config.goole_tts_json_key this._client = texttospeech.TextToSpeechClient() this._audio_config = texttospeech.AudioConfig( audio_encoding = texttospeech.AudioEncoding.MP3 ) + this._language_code= language_code + this._name = name this._voice = texttospeech.VoiceSelectionParams( - language_code = 'ru-RU', - name = name, + language_code = this._language_code, + name = this._name, ssml_gender = texttospeech.SsmlVoiceGender.FEMALE) def generate(this, text, standart = False): diff --git a/config.py b/config.py new file mode 100644 index 0000000..ee321cf --- /dev/null +++ b/config.py @@ -0,0 +1,2 @@ +goole_tts_json_key = "tts-gc-key.json" +language_code = "ru-RU" diff --git a/main.py b/main.py new file mode 100644 index 0000000..7a1d618 --- /dev/null +++ b/main.py @@ -0,0 +1,40 @@ +import SpeechRecognition +import Text2Speech +import SmallTalk +from Command import Command + +listener = SpeechRecognition.SpeechToText() +voice = Text2Speech.Engine() +threads = [] +memory = [] +listener.listen_noise() + +def check_threads(): + for thread in threads: + if thread['finish_event'].is_set(): + responce = thread['thread'].join() + if responce['text']: + voice.generate(responce['text']).speak() + thread['finish_event'].clear() + del thread + +while True: # main loop + check_threads() + print('Listening...') + speech = listener.listen() + text = speech['text'] + print('You: ') + if text: + cmd = Command.find(text) + responce = cmd.start(text) + memory.insert(0, { + 'text': text, + 'cmd': cmd, + 'responce': responce + }) + if responce['type'] == 'background': # add background thread to list + threads.append(responce['thread']) + if responce['text']: + voice.generate(responce['text']).speak() + else: + print(speech['status'])