Update __main__.py
(Major change) main() function completely refactored into helpers. _init_controllers now handles decoupled initialization. _process_audio loop logic was fixed to correctly initialize wake words on startup. mic.recorder() loop is now much more robust against OS buffering issue when the microphone is muted and wakewords were detected and processed after unmute.
This commit is contained in:
@@ -134,7 +134,7 @@ async def main() -> None:
|
|||||||
finally:
|
finally:
|
||||||
# --- 10. Cleanup ---
|
# --- 10. Cleanup ---
|
||||||
_LOGGER.debug("Shutting down...")
|
_LOGGER.debug("Shutting down...")
|
||||||
state.mic_muted = True # Signal audio thread to stop
|
state.shutdown = True # Signal audio thread to stop
|
||||||
audio_thread.join()
|
audio_thread.join()
|
||||||
|
|
||||||
if hasattr(state, "mqtt_controller") and state.mqtt_controller:
|
if hasattr(state, "mqtt_controller") and state.mqtt_controller:
|
||||||
@@ -404,11 +404,39 @@ def _process_audio(state: ServerState, mic, block_size: int):
|
|||||||
last_active: Optional[float] = None
|
last_active: Optional[float] = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
while True:
|
||||||
|
# --- THIS IS THE FIX ---
|
||||||
|
# Wait while muted. This loop will spin until unmuted.
|
||||||
|
if state.mic_muted:
|
||||||
|
_LOGGER.debug("Audio thread muted.")
|
||||||
|
while state.mic_muted:
|
||||||
|
if state.shutdown:
|
||||||
|
_LOGGER.debug("Shutdown signal received, stopping audio thread.")
|
||||||
|
return # Exit thread
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
# --- Just unmuted ---
|
||||||
|
_LOGGER.debug("Audio thread unmuted, clearing buffers.")
|
||||||
|
micro_features.reset()
|
||||||
|
if oww_features is not None:
|
||||||
|
oww_features.reset()
|
||||||
|
last_active = time.monotonic() # Start refractory period
|
||||||
|
|
||||||
|
# Re-open microphone to flush OS buffer
|
||||||
|
_LOGGER.debug("Re-opening microphone to flush OS buffers...")
|
||||||
|
with mic.recorder(samplerate=16000, channels=1, blocksize=block_size) as mic_in:
|
||||||
|
mic_in.flush() # Discard any stale data
|
||||||
|
_LOGGER.debug("Microphone flushed.")
|
||||||
|
# Fall through to the main recording loop
|
||||||
|
# --- END FIX ---
|
||||||
|
|
||||||
_LOGGER.debug("Opening audio input device: %s", mic.name)
|
_LOGGER.debug("Opening audio input device: %s", mic.name)
|
||||||
with mic.recorder(samplerate=16000, channels=1, blocksize=block_size) as mic_in:
|
with mic.recorder(samplerate=16000, channels=1, blocksize=block_size) as mic_in:
|
||||||
while True:
|
# --- This is now the main recording loop ---
|
||||||
if state.mic_muted:
|
while not state.mic_muted:
|
||||||
break
|
if state.shutdown:
|
||||||
|
_LOGGER.debug("Shutdown signal received, stopping audio thread.")
|
||||||
|
return # Exit thread
|
||||||
|
|
||||||
audio_chunk_array = mic_in.record(block_size).reshape(-1)
|
audio_chunk_array = mic_in.record(block_size).reshape(-1)
|
||||||
audio_chunk = (
|
audio_chunk = (
|
||||||
@@ -421,9 +449,7 @@ def _process_audio(state: ServerState, mic, block_size: int):
|
|||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# --- THIS IS THE FIX ---
|
|
||||||
if (not wake_words) or (state.wake_words_changed):
|
if (not wake_words) or (state.wake_words_changed):
|
||||||
# --- END FIX ---
|
|
||||||
state.wake_words_changed = False
|
state.wake_words_changed = False
|
||||||
wake_words = [
|
wake_words = [
|
||||||
ww for ww in state.wake_words.values()
|
ww for ww in state.wake_words.values()
|
||||||
|
|||||||
Reference in New Issue
Block a user