parent
aa637d53b5
commit
52d88fd72c
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,101 @@
|
|||||||
|
import asyncio
|
||||||
|
import websockets
|
||||||
|
import pyaudio
|
||||||
|
from pynput import keyboard
|
||||||
|
import json
|
||||||
|
from yaspin import yaspin
|
||||||
|
|
||||||
|
CHUNK = 1024
|
||||||
|
FORMAT = pyaudio.paInt16
|
||||||
|
CHANNELS = 1
|
||||||
|
RECORDING_RATE = 16000
|
||||||
|
PLAYBACK_RATE = 24000
|
||||||
|
|
||||||
|
class Device:
|
||||||
|
def __init__(self):
|
||||||
|
self.server_url = "0.0.0.0:10001"
|
||||||
|
self.p = pyaudio.PyAudio()
|
||||||
|
self.websocket = None
|
||||||
|
self.recording = False
|
||||||
|
self.input_stream = None
|
||||||
|
self.output_stream = None
|
||||||
|
self.spinner = yaspin()
|
||||||
|
self.play_audio = True
|
||||||
|
|
||||||
|
async def connect_with_retry(self, max_retries=50, retry_delay=2):
|
||||||
|
for attempt in range(max_retries):
|
||||||
|
try:
|
||||||
|
self.websocket = await websockets.connect(f"ws://{self.server_url}")
|
||||||
|
print("Connected to server.")
|
||||||
|
|
||||||
|
# Send auth, which the server requires (docs.openinterpreter.com/server/usage)
|
||||||
|
await self.websocket.send(json.dumps({"auth": True}))
|
||||||
|
|
||||||
|
return
|
||||||
|
except ConnectionRefusedError:
|
||||||
|
if attempt % 4 == 0:
|
||||||
|
print(f"Waiting for the server to be ready...")
|
||||||
|
await asyncio.sleep(retry_delay)
|
||||||
|
raise Exception("Failed to connect to the server after multiple attempts")
|
||||||
|
|
||||||
|
async def send_audio(self):
|
||||||
|
self.input_stream = self.p.open(format=FORMAT, channels=CHANNELS, rate=RECORDING_RATE, input=True, frames_per_buffer=CHUNK)
|
||||||
|
while True:
|
||||||
|
if self.recording:
|
||||||
|
try:
|
||||||
|
# Send start flag
|
||||||
|
await self.websocket.send(json.dumps({"role": "user", "type": "audio", "format": "bytes.wav", "start": True}))
|
||||||
|
# print("Sending audio start message")
|
||||||
|
|
||||||
|
while self.recording:
|
||||||
|
data = self.input_stream.read(CHUNK, exception_on_overflow=False)
|
||||||
|
await self.websocket.send(data)
|
||||||
|
|
||||||
|
# Send stop flag
|
||||||
|
await self.websocket.send(json.dumps({"role": "user", "type": "audio", "format": "bytes.wav", "end": True}))
|
||||||
|
# print("Sending audio end message")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error in send_audio: {e}")
|
||||||
|
await asyncio.sleep(0.01)
|
||||||
|
|
||||||
|
async def receive_audio(self):
|
||||||
|
self.output_stream = self.p.open(format=FORMAT, channels=CHANNELS, rate=PLAYBACK_RATE, output=True, frames_per_buffer=CHUNK)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = await self.websocket.recv()
|
||||||
|
if self.play_audio and isinstance(data, bytes) and not self.recording:
|
||||||
|
self.output_stream.write(data)
|
||||||
|
except Exception as e:
|
||||||
|
await self.connect_with_retry()
|
||||||
|
|
||||||
|
def on_press(self, key):
|
||||||
|
if key == keyboard.Key.ctrl and not self.recording:
|
||||||
|
#print("Space pressed, starting recording")
|
||||||
|
print("\n")
|
||||||
|
self.spinner.start()
|
||||||
|
self.recording = True
|
||||||
|
|
||||||
|
def on_release(self, key):
|
||||||
|
if key == keyboard.Key.ctrl: # TODO: Pass in hotkey
|
||||||
|
self.spinner.stop()
|
||||||
|
#print("Space released, stopping recording")
|
||||||
|
self.recording = False
|
||||||
|
# elif key == keyboard.Key.esc:
|
||||||
|
# print("Esc pressed, stopping the program")
|
||||||
|
# return False
|
||||||
|
|
||||||
|
async def main(self):
|
||||||
|
await self.connect_with_retry()
|
||||||
|
print("Hold CTRL to speak to the assistant. Press 'CTRL-C' to quit.")
|
||||||
|
listener = keyboard.Listener(on_press=self.on_press, on_release=self.on_release)
|
||||||
|
listener.start()
|
||||||
|
await asyncio.gather(self.send_audio(), self.receive_audio())
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
asyncio.run(self.main())
|
||||||
|
|
||||||
|
def run(server_url, debug):
|
||||||
|
device = Device()
|
||||||
|
device.server_url = server_url
|
||||||
|
device.debug = debug
|
||||||
|
device.start()
|
Loading…
Reference in new issue