summaryrefslogtreecommitdiff
path: root/modules/input_handlers
diff options
context:
space:
mode:
Diffstat (limited to 'modules/input_handlers')
-rw-r--r--modules/input_handlers/__init__.py0
-rw-r--r--modules/input_handlers/input_handler.py11
-rw-r--r--modules/input_handlers/pipewire_record.py72
-rw-r--r--modules/input_handlers/stdin_input.py16
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