diff options
Diffstat (limited to 'modules/input_handlers')
-rw-r--r-- | modules/input_handlers/__init__.py | 0 | ||||
-rw-r--r-- | modules/input_handlers/input_handler.py | 11 | ||||
-rw-r--r-- | modules/input_handlers/pipewire_record.py | 72 | ||||
-rw-r--r-- | modules/input_handlers/stdin_input.py | 16 |
4 files changed, 99 insertions, 0 deletions
diff --git a/modules/input_handlers/__init__.py b/modules/input_handlers/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/modules/input_handlers/__init__.py diff --git a/modules/input_handlers/input_handler.py b/modules/input_handlers/input_handler.py new file mode 100644 index 0000000..3db042c --- /dev/null +++ b/modules/input_handlers/input_handler.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod + +class InputHandler(ABC): + + @abstractmethod + def get_input(self) -> str: + pass + + @abstractmethod + def cleanup(self) -> None: + pass
\ No newline at end of file diff --git a/modules/input_handlers/pipewire_record.py b/modules/input_handlers/pipewire_record.py new file mode 100644 index 0000000..0a767e1 --- /dev/null +++ b/modules/input_handlers/pipewire_record.py @@ -0,0 +1,72 @@ +import subprocess +import os.path +import signal +from time import sleep + +import whisper + +from .input_handler import InputHandler + +FIFO_PATH = "/tmp/hestia-listening" +RECORD_PATH = "/tmp/hestia-record.mp3" + +class PipeWireRecord(InputHandler): + def cleanup(self) -> None: + if os.path.exists(FIFO_PATH): + os.remove(FIFO_PATH) + + + def get_input(self) -> str: + device = PipeWireRecord.get_device() + + self.cleanup() + os.mkfifo(FIFO_PATH) + + while True: + with open(FIFO_PATH): + pass + # TODO "I'm listening" + + try: + ps = subprocess.Popen((f"pw-record --target {device} {RECORD_PATH}",), shell=True) + with open(FIFO_PATH): + print("finished") + ps.send_signal(signal.SIGINT) + # TODO "acknowledged" + except: + if "ps" in locals(): + ps.kill() + # TODO "error" + # TODO exit gracefully or try to recover + raise StopIteration + + model = whisper.load_model("base") + + audio = whisper.load_audio(RECORD_PATH) + audio = whisper.pad_or_trim(audio) + + mel = whisper.log_mel_spectrogram(audio).to(model.device) + options = whisper.DecodingOptions(language="en", fp16=False) + result = whisper.decode(model, mel, options) + result_text = result.text.replace(",", "").replace(".", "").lower() + + print(result_text) + + yield result_text + + @staticmethod + def get_device() -> str: + already_warned = False + + while True: + ps = subprocess.Popen(('pw-cli ls | \\grep -Poi "(?<=node.name = \\").*mic.*(?=\\")"',), shell=True, stdout=subprocess.PIPE) + ps.wait() + + if ps.returncode == 0: + return ps.stdout.read().decode().strip() + + elif not already_warned: + already_warned = True + # TODO warn about device not found + + sleep(3)
\ No newline at end of file diff --git a/modules/input_handlers/stdin_input.py b/modules/input_handlers/stdin_input.py new file mode 100644 index 0000000..3d338c1 --- /dev/null +++ b/modules/input_handlers/stdin_input.py @@ -0,0 +1,16 @@ +import sys + +from .input_handler import InputHandler + + +class StdinInput(InputHandler): + def cleanup(self) -> None: + pass + + def get_input(self) -> str: + for line in sys.stdin: + line = line.strip() + if not line: + continue + + yield line
\ No newline at end of file |