Updates to the assistants overall abilities, like always listening, and only responding on messages when activated.
This commit is contained in:
+36
-1
@@ -30,7 +30,42 @@ def open_mic(on_frame: Callable[[bytes], None]):
|
||||
|
||||
def play(chunks: Iterable[bytes], sample_rate: int = config.TTS_SAMPLE_RATE,
|
||||
should_stop: Callable[[], bool] = lambda: False) -> bool:
|
||||
"""Play PCM16 mono chunks as they arrive. False if stopped early."""
|
||||
"""Play PCM16 mono chunks as they arrive. False if stopped early.
|
||||
|
||||
Through `pacat`, not sounddevice: PortAudio only sees raw ALSA devices,
|
||||
so a Bluetooth or PipeWire sink is invisible to it and the audio goes
|
||||
somewhere nobody can hear. pacat talks to the audio server, so it
|
||||
follows the system's default sink like every other player.
|
||||
"""
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
if shutil.which("pacat") is None:
|
||||
return _play_sounddevice(chunks, sample_rate, should_stop)
|
||||
|
||||
proc = subprocess.Popen(
|
||||
["pacat", "--rate", str(sample_rate), "--channels", "1",
|
||||
"--format", "s16le", "--latency-msec", "60"],
|
||||
stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
||||
)
|
||||
try:
|
||||
for chunk in chunks:
|
||||
if should_stop():
|
||||
return False
|
||||
proc.stdin.write(chunk)
|
||||
proc.stdin.close()
|
||||
proc.wait(timeout=10)
|
||||
except (BrokenPipeError, OSError):
|
||||
return False
|
||||
finally:
|
||||
if proc.poll() is None:
|
||||
proc.kill()
|
||||
return True
|
||||
|
||||
|
||||
def _play_sounddevice(chunks: Iterable[bytes], sample_rate: int,
|
||||
should_stop: Callable[[], bool]) -> bool:
|
||||
"""Fallback for a machine without pacat."""
|
||||
import sounddevice as sd
|
||||
|
||||
with sd.RawOutputStream(samplerate=sample_rate, channels=1, dtype="int16",
|
||||
|
||||
Reference in New Issue
Block a user