fix: allow virtual ALSA PCM names (dsnoop etc.); log arecord stderr
AudioSystem.find_device() now falls back to treating an unmatched spec as a direct ALSA PCM name when the ALSA backend is available. Virtual devices defined in asound.conf (dsnoop, plug, etc.) never appear in 'arecord -l' so they were always rejected as 'not found', even when valid. ALSAStream now captures arecord stderr via a reader thread instead of discarding it, so errors like 'Device or resource busy' are logged as warnings and visible in docker compose logs.
This commit is contained in:
@@ -186,13 +186,15 @@ class ALSAStream:
|
||||
self._process = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL,
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
except FileNotFoundError:
|
||||
raise RuntimeError("arecord not found - install alsa-utils: sudo apt install alsa-utils")
|
||||
|
||||
self._thread = threading.Thread(target=self._read_loop, daemon=True)
|
||||
self._stderr_thread = threading.Thread(target=self._log_stderr, daemon=True)
|
||||
self._thread.start()
|
||||
self._stderr_thread.start()
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
@@ -206,6 +208,12 @@ class ALSAStream:
|
||||
if self._thread:
|
||||
self._thread.join(timeout=1)
|
||||
|
||||
def _log_stderr(self):
|
||||
for line in self._process.stderr:
|
||||
line = line.decode('utf-8', errors='replace').rstrip()
|
||||
if line:
|
||||
self.logger.warning(f"arecord: {line}")
|
||||
|
||||
def _read_loop(self):
|
||||
chunk_size = self.sample_rate * self.channels * 2 // 10 # 100 ms chunks
|
||||
while self._running and self._process.poll() is None:
|
||||
@@ -306,6 +314,14 @@ class AudioSystem:
|
||||
if spec_lower in dev.name.lower():
|
||||
return dev
|
||||
|
||||
# No hardware device matched. Treat spec as a direct ALSA PCM name so
|
||||
# virtual devices defined in asound.conf (dsnoop, plug, etc.) work without
|
||||
# appearing in `arecord -l`.
|
||||
if 'alsa' in self._backends:
|
||||
return AudioDevice(
|
||||
id=spec, name=spec, channels=2, sample_rate=44100, backend='alsa'
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user