Update __main__.py

Wrong version of file uploaded.
This commit is contained in:
imonlinux
2025-11-18 11:48:04 -08:00
committed by GitHub
parent 2ccda5ac4a
commit 2fdef7d6ce
+72 -74
View File
@@ -134,9 +134,10 @@ async def main() -> None:
finally: finally:
# --- 10. Cleanup --- # --- 10. Cleanup ---
_LOGGER.debug("Shutting down...") _LOGGER.debug("Shutting down...")
state.shutdown = True # Signal audio thread to stop state.shutdown = True
audio_thread.join() audio_thread.join()
# Check for and stop the MQTT controller (set in _init_controllers)
if hasattr(state, "mqtt_controller") and state.mqtt_controller: if hasattr(state, "mqtt_controller") and state.mqtt_controller:
_LOGGER.debug("Stopping MQTT controller...") _LOGGER.debug("Stopping MQTT controller...")
state.mqtt_controller.stop() state.mqtt_controller.stop()
@@ -403,96 +404,93 @@ def _process_audio(state: ServerState, mic, block_size: int):
has_oww = False has_oww = False
last_active: Optional[float] = None last_active: Optional[float] = None
is_muted_flag = False
try: try:
while True: _LOGGER.debug("Opening audio input device: %s", mic.name)
# --- THIS IS THE FIX --- with mic.recorder(samplerate=16000, channels=1, blocksize=block_size) as mic_in:
# Wait while muted. This loop will spin until unmuted. while True:
if state.mic_muted: if state.shutdown:
_LOGGER.debug("Audio thread muted.") _LOGGER.debug("Shutdown signal received, stopping audio thread.")
while state.mic_muted: break
if state.shutdown:
_LOGGER.debug("Shutdown signal received, stopping audio thread.") if state.mic_muted:
return # Exit thread if not is_muted_flag:
_LOGGER.debug("Audio thread muted.")
is_muted_flag = True
time.sleep(0.1) time.sleep(0.1)
continue
# --- Just unmuted --- if is_muted_flag:
_LOGGER.debug("Audio thread unmuted, clearing buffers.") _LOGGER.debug("Audio thread unmuted, clearing buffers.")
micro_features.reset() micro_features.reset()
if oww_features is not None: if oww_features is not None:
oww_features.reset() oww_features.reset()
last_active = time.monotonic() # Start refractory period last_active = time.monotonic()
# Re-open microphone to flush OS buffer is_muted_flag = False
_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("Flushing stale audio buffer...")
with mic.recorder(samplerate=16000, channels=1, blocksize=block_size) as mic_in: for _ in range(8):
# --- This is now the main recording loop --- mic_in.record(block_size)
while not state.mic_muted: _LOGGER.debug("Stale audio buffer cleared.")
if state.shutdown: continue
_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 = (
(np.clip(audio_chunk_array, -1.0, 1.0) * 32767.0) (np.clip(audio_chunk_array, -1.0, 1.0) * 32767.0)
.astype("<i2") .astype("<i2")
.tobytes() .tobytes()
) )
if state.satellite is None: if state.satellite is None:
time.sleep(0.01) time.sleep(0.01)
continue continue
if (not wake_words) or (state.wake_words_changed): if (not wake_words) or (state.wake_words_changed):
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()
if ww.id in state.active_wake_words if ww.id in state.active_wake_words
] ]
has_oww = any(isinstance(ww, OpenWakeWord) for ww in wake_words) has_oww = any(isinstance(ww, OpenWakeWord) for ww in wake_words)
if has_oww and (oww_features is None): if has_oww and (oww_features is None):
_LOGGER.debug("Initializing OpenWakeWord features...") _LOGGER.debug("Initializing OpenWakeWord features...")
oww_features = OpenWakeWordFeatures.from_builtin() oww_features = OpenWakeWordFeatures.from_builtin()
try: try:
micro_inputs.clear(); micro_inputs.extend(micro_features.process_streaming(audio_chunk)) micro_inputs.clear(); micro_inputs.extend(micro_features.process_streaming(audio_chunk))
if has_oww: if has_oww:
assert oww_features is not None assert oww_features is not None
oww_inputs.clear(); oww_inputs.extend(oww_features.process_streaming(audio_chunk)) oww_inputs.clear(); oww_inputs.extend(oww_features.process_streaming(audio_chunk))
for wake_word in wake_words: for wake_word in wake_words:
activated = False activated = False
if isinstance(wake_word, MicroWakeWord): if isinstance(wake_word, MicroWakeWord):
if any(wake_word.process_streaming(mi) for mi in micro_inputs): activated = True if any(wake_word.process_streaming(mi) for mi in micro_inputs): activated = True
elif isinstance(wake_word, OpenWakeWord): elif isinstance(wake_word, OpenWakeWord):
if any(p > 0.5 for oi in oww_inputs for p in wake_word.process_streaming(oi)): activated = True if any(p > 0.5 for oi in oww_inputs for p in wake_word.process_streaming(oi)): activated = True
if activated: if activated:
now = time.monotonic() now = time.monotonic()
if (last_active is None) or ((now - last_active) > state.refractory_seconds): if (last_active is None) or ((now - last_active) > state.refractory_seconds):
state.loop.call_soon_threadsafe(state.satellite.wakeup, wake_word) state.loop.call_soon_threadsafe(state.satellite.wakeup, wake_word)
last_active = now last_active = now
stopped = False stopped = False
for micro_input in micro_inputs: for micro_input in micro_inputs:
if state.stop_word.process_streaming(micro_input): if state.stop_word.process_streaming(micro_input):
stopped = True stopped = True
if stopped and (state.stop_word.id in state.active_wake_words): if stopped and (state.stop_word.id in state.active_wake_words):
state.loop.call_soon_threadsafe(state.satellite.stop) state.loop.call_soon_threadsafe(state.satellite.stop)
state.loop.call_soon_threadsafe(state.satellite.handle_audio, audio_chunk) state.loop.call_soon_threadsafe(state.satellite.handle_audio, audio_chunk)
except Exception: except Exception:
_LOGGER.exception("Unexpected error handling audio") _LOGGER.exception("Unexpected error handling audio")
except Exception as e: except Exception as e:
_LOGGER.critical("A soundcard error occurred: %s", e) _LOGGER.critical("A soundcard error occurred: %s", e)