Skip to content

Commit

Permalink
add keyboard trigger + example
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkParker5 committed Sep 20, 2023
1 parent a783d6f commit ea0e82f
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 1 deletion.
2 changes: 1 addition & 1 deletion stark_place/commands/general_manager.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from stark import CommandsManager


general_manager = CommandsManager()
general_manager = CommandsManager('Stark-Place')
# general_manager.extend(...)
56 changes: 56 additions & 0 deletions stark_place/examples/keyboard_trigger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import asyncer
from stark import CommandsContext, CommandsManager, Response
from stark.general.blockage_detector import BlockageDetector
from stark.interfaces.protocols import SpeechRecognizer, SpeechSynthesizer
from stark.interfaces.vosk import VoskSpeechRecognizer
from stark.interfaces.silero import SileroSpeechSynthesizer
from stark.voice_assistant import VoiceAssistant, Mode

from stark_place.triggers import keyboard_key # import the trigger


VOSK_MODEL_URL = "YOUR_CHOSEN_VOSK_MODEL_URL"
SILERO_MODEL_URL = "YOUR_CHOSEN_SILERO_MODEL_URL"

recognizer = VoskSpeechRecognizer(model_url=VOSK_MODEL_URL)
synthesizer = SileroSpeechSynthesizer(model_url=SILERO_MODEL_URL)

manager = CommandsManager()

@manager.new('hello')
async def hello_command() -> Response:
text = voice = 'Hello, world!'
return Response(text=text, voice=voice)

async def run(
manager: CommandsManager,
speech_recognizer: SpeechRecognizer,
speech_synthesizer: SpeechSynthesizer
):
async with asyncer.create_task_group() as main_task_group:
context = CommandsContext(
task_group = main_task_group,
commands_manager = manager
)
voice_assistant = VoiceAssistant(
speech_recognizer = speech_recognizer,
speech_synthesizer = speech_synthesizer,
commands_context = context
)
speech_recognizer.delegate = voice_assistant
context.delegate = voice_assistant

voice_assistant.mode = Mode.external() # stop listening after first response

main_task_group.soonify(keyboard_key.start)(main_task_group.soonify(speech_recognizer.start_listening)) # add trigger to the main loop
# main_task_group.soonify(speech_recognizer.start_listening)() # don't start listening until the hotkey is pressed
main_task_group.soonify(context.handle_responses)()

detector = BlockageDetector()
main_task_group.soonify(detector.monitor)()

async def main():
await run(manager, recognizer, synthesizer)

if __name__ == '__main__':
asyncer.runnify(main)() # or anyio.run(main), same thing
40 changes: 40 additions & 0 deletions stark_place/triggers/keyboard_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from typing import Callable, Any
import os
from pynput.keyboard import Key, KeyCode, Listener, HotKey
import anyio
from asyncer import asyncify
from threading import Event


async def start(callback: Callable[[], Any | None]):
hotkey_event = Event()

def on_release(key: Key):
# this function is called in a separate thread, so we need to use a thread-safe way to communicate with the main thread
nonlocal hotkey_event
if key == KeyCode(63): # macos globe button
hotkey_event.set()

listener = Listener(on_release = on_release)
listener.start() # start listening in a separate thread

while True: # this loop runs in the main thread

await anyio.sleep(0.1) # release the thread for other tasks

if hotkey_event.is_set():
'''
optional: play a sound to indicate that the hotkey was pressed
play all sounds in macos using shell: sh`for s in /System/Library/Sounds/*; do echo "$s" && afplay "$s"; done`
for linux: check the `/usr/share/sounds/` directory and use `aplay` instead of `afplay`
as an alternative, you can use the system-sounds pypi library to list and play sounds
pypi.org/project/system-sounds
or github.com/MarkParker5/system-sounds
or use the a SpeechSynthesizer to say something like "Yes, sir?"
'''
os.system('afplay /System/Library/Sounds/Blow.aiff &') # play the sound in the background (macos)
callback()
hotkey_event.clear()

0 comments on commit ea0e82f

Please sign in to comment.