Desmond-Dong commited on
Commit
feebc51
·
1 Parent(s): 23c59a7

修复: 语音助手唤醒时暂停Sendspin和音乐播放

Browse files

- 添加pause_sendspin()/resume_sendspin()方法
- duck()时暂停Sendspin音频流,unduck()时恢复
- 改进pause()方法,真正停止音频输出
- 防止语音助手交互时的音频冲突

reachy_mini_ha_voice/audio_player.py CHANGED
@@ -102,6 +102,7 @@ class AudioPlayer:
102
  # Audio buffer for Sendspin playback
103
  self._sendspin_audio_format: Optional["PCMFormat"] = None
104
  self._sendspin_playback_started = False
 
105
 
106
  def set_reachy_mini(self, reachy_mini) -> None:
107
  """Set the Reachy Mini instance."""
@@ -124,6 +125,28 @@ class AudioPlayer:
124
  """Get current Sendspin server URL."""
125
  return self._sendspin_url
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  async def start_sendspin_discovery(self) -> None:
128
  """Start mDNS discovery for Sendspin servers.
129
 
@@ -269,10 +292,16 @@ class AudioPlayer:
269
 
270
  Plays the audio through Reachy Mini's speaker using push_audio_sample().
271
  Resamples audio if needed (Reachy Mini uses 16kHz).
 
 
272
  """
273
  if self.reachy_mini is None:
274
  return
275
 
 
 
 
 
276
  try:
277
  # Store format for potential use
278
  self._sendspin_audio_format = fmt
@@ -515,11 +544,21 @@ class AudioPlayer:
515
  _LOGGER.exception("Unexpected error running done callback")
516
 
517
  def pause(self) -> None:
518
- """Pause playback."""
 
 
 
 
 
 
 
 
 
519
  self.is_playing = False
520
 
521
  def resume(self) -> None:
522
- """Resume playback."""
 
523
  if self._playlist:
524
  self._play_next()
525
 
 
102
  # Audio buffer for Sendspin playback
103
  self._sendspin_audio_format: Optional["PCMFormat"] = None
104
  self._sendspin_playback_started = False
105
+ self._sendspin_paused = False # Pause Sendspin when voice assistant is active
106
 
107
  def set_reachy_mini(self, reachy_mini) -> None:
108
  """Set the Reachy Mini instance."""
 
125
  """Get current Sendspin server URL."""
126
  return self._sendspin_url
127
 
128
+ def pause_sendspin(self) -> None:
129
+ """Pause Sendspin audio playback.
130
+
131
+ Called when voice assistant is activated to prevent audio conflicts.
132
+ Incoming Sendspin audio chunks will be dropped until resumed.
133
+ """
134
+ if self._sendspin_paused:
135
+ return
136
+ self._sendspin_paused = True
137
+ _LOGGER.debug("Sendspin audio paused (voice assistant active)")
138
+
139
+ def resume_sendspin(self) -> None:
140
+ """Resume Sendspin audio playback.
141
+
142
+ Called when voice assistant returns to idle state.
143
+ """
144
+ if not self._sendspin_paused:
145
+ return
146
+ self._sendspin_paused = False
147
+ self._logged_resample = False # Reset resample log flag for new stream
148
+ _LOGGER.debug("Sendspin audio resumed")
149
+
150
  async def start_sendspin_discovery(self) -> None:
151
  """Start mDNS discovery for Sendspin servers.
152
 
 
292
 
293
  Plays the audio through Reachy Mini's speaker using push_audio_sample().
294
  Resamples audio if needed (Reachy Mini uses 16kHz).
295
+
296
+ Note: Audio is dropped when Sendspin is paused (e.g., during voice assistant interaction).
297
  """
298
  if self.reachy_mini is None:
299
  return
300
 
301
+ # Drop audio when paused (voice assistant is active)
302
+ if self._sendspin_paused:
303
+ return
304
+
305
  try:
306
  # Store format for potential use
307
  self._sendspin_audio_format = fmt
 
544
  _LOGGER.exception("Unexpected error running done callback")
545
 
546
  def pause(self) -> None:
547
+ """Pause playback.
548
+
549
+ Stops current audio output but preserves playlist for resume.
550
+ """
551
+ self._stop_flag.set()
552
+ if self.reachy_mini is not None:
553
+ try:
554
+ self.reachy_mini.media.stop_playing()
555
+ except Exception:
556
+ pass
557
  self.is_playing = False
558
 
559
  def resume(self) -> None:
560
+ """Resume playback from where it was paused."""
561
+ self._stop_flag.clear()
562
  if self._playlist:
563
  self._play_next()
564
 
reachy_mini_ha_voice/satellite.py CHANGED
@@ -398,10 +398,14 @@ class VoiceSatelliteProtocol(APIServer):
398
  def duck(self) -> None:
399
  _LOGGER.debug("Ducking music")
400
  self.state.music_player.duck()
 
 
401
 
402
  def unduck(self) -> None:
403
  _LOGGER.debug("Unducking music")
404
  self.state.music_player.unduck()
 
 
405
 
406
  def _tts_finished(self) -> None:
407
  self.state.active_wake_words.discard(self.state.stop_word.id)
 
398
  def duck(self) -> None:
399
  _LOGGER.debug("Ducking music")
400
  self.state.music_player.duck()
401
+ # Pause Sendspin to prevent audio conflicts during voice interaction
402
+ self.state.tts_player.pause_sendspin()
403
 
404
  def unduck(self) -> None:
405
  _LOGGER.debug("Unducking music")
406
  self.state.music_player.unduck()
407
+ # Resume Sendspin audio
408
+ self.state.tts_player.resume_sendspin()
409
 
410
  def _tts_finished(self) -> None:
411
  self.state.active_wake_words.discard(self.state.stop_word.id)