Spaces:
Running
Running
Update recorder.py
Browse files- recorder.py +64 -30
recorder.py
CHANGED
|
@@ -10,7 +10,7 @@ import queue
|
|
| 10 |
class AudioRecorder:
|
| 11 |
def __init__(self, sample_rate: int = 44100, channels: int = 1, device_index: int = None):
|
| 12 |
"""
|
| 13 |
-
Initialize the audio recorder.
|
| 14 |
|
| 15 |
Args:
|
| 16 |
sample_rate (int): Sample rate in Hz (default: 44100)
|
|
@@ -26,6 +26,21 @@ class AudioRecorder:
|
|
| 26 |
self.recording_data = []
|
| 27 |
self.stream = None
|
| 28 |
self.final_audio_data = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
def start_recording(self):
|
| 31 |
"""Start recording audio from the selected input device."""
|
|
@@ -33,6 +48,12 @@ class AudioRecorder:
|
|
| 33 |
return False
|
| 34 |
|
| 35 |
print("Starting recording...")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
self.recording = True
|
| 37 |
self.recording_data = []
|
| 38 |
self.audio_queue = queue.Queue()
|
|
@@ -80,6 +101,12 @@ class AudioRecorder:
|
|
| 80 |
print("Stopping recording...")
|
| 81 |
self.recording = False
|
| 82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
# First, get any remaining data from the queue
|
| 84 |
queue_data = []
|
| 85 |
max_attempts = 10 # Prevent infinite loops
|
|
@@ -266,44 +293,51 @@ class AudioRecorder:
|
|
| 266 |
|
| 267 |
def list_audio_devices() -> list:
|
| 268 |
"""
|
| 269 |
-
List all available audio input devices.
|
| 270 |
|
| 271 |
Returns:
|
| 272 |
list: A list of dictionaries containing device information
|
| 273 |
"""
|
| 274 |
try:
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
try:
|
| 280 |
-
if device['max_input_channels'] > 0:
|
| 281 |
-
input_devices.append({
|
| 282 |
-
'id': i,
|
| 283 |
-
'name': device.get('name', f'Device {i}'),
|
| 284 |
-
'input_channels': device.get('max_input_channels', 1),
|
| 285 |
-
'default_samplerate': device.get('default_samplerate', 44100)
|
| 286 |
-
})
|
| 287 |
-
except (KeyError, TypeError):
|
| 288 |
-
continue
|
| 289 |
-
|
| 290 |
-
if not input_devices:
|
| 291 |
-
print("No input devices found. Using default device.")
|
| 292 |
-
return [{
|
| 293 |
-
'id': sd.default.device[0],
|
| 294 |
-
'name': 'Default Device',
|
| 295 |
-
'input_channels': 1,
|
| 296 |
-
'default_samplerate': 44100
|
| 297 |
-
}]
|
| 298 |
|
| 299 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 300 |
|
| 301 |
-
|
| 302 |
-
print(
|
| 303 |
-
# Return a default device as fallback
|
| 304 |
return [{
|
| 305 |
-
'id': sd.default.device[0] if hasattr(sd.default, 'device') else 0,
|
| 306 |
'name': 'Default Device',
|
| 307 |
'input_channels': 1,
|
| 308 |
'default_samplerate': 44100
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 309 |
}]
|
|
|
|
| 10 |
class AudioRecorder:
|
| 11 |
def __init__(self, sample_rate: int = 44100, channels: int = 1, device_index: int = None):
|
| 12 |
"""
|
| 13 |
+
Initialize the audio recorder with fallback for environments without audio devices.
|
| 14 |
|
| 15 |
Args:
|
| 16 |
sample_rate (int): Sample rate in Hz (default: 44100)
|
|
|
|
| 26 |
self.recording_data = []
|
| 27 |
self.stream = None
|
| 28 |
self.final_audio_data = None
|
| 29 |
+
self.has_audio_device = True # Assume we have audio device by default
|
| 30 |
+
|
| 31 |
+
# Test if we can actually use the audio device
|
| 32 |
+
try:
|
| 33 |
+
# Try to query devices to see if we have audio support
|
| 34 |
+
devices = sd.query_devices()
|
| 35 |
+
if not devices:
|
| 36 |
+
print("Warning: No audio devices found")
|
| 37 |
+
self.has_audio_device = False
|
| 38 |
+
elif self.device_index is not None and self.device_index >= len(devices):
|
| 39 |
+
print(f"Warning: Device index {self.device_index} is out of range")
|
| 40 |
+
self.has_audio_device = False
|
| 41 |
+
except Exception as e:
|
| 42 |
+
print(f"Warning: Could not query audio devices: {e}")
|
| 43 |
+
self.has_audio_device = False
|
| 44 |
|
| 45 |
def start_recording(self):
|
| 46 |
"""Start recording audio from the selected input device."""
|
|
|
|
| 48 |
return False
|
| 49 |
|
| 50 |
print("Starting recording...")
|
| 51 |
+
|
| 52 |
+
if not self.has_audio_device:
|
| 53 |
+
print("Warning: No audio device available, recording will not capture any audio")
|
| 54 |
+
self.recording = True
|
| 55 |
+
return True
|
| 56 |
+
|
| 57 |
self.recording = True
|
| 58 |
self.recording_data = []
|
| 59 |
self.audio_queue = queue.Queue()
|
|
|
|
| 101 |
print("Stopping recording...")
|
| 102 |
self.recording = False
|
| 103 |
|
| 104 |
+
if not self.has_audio_device:
|
| 105 |
+
print("No audio device was available during recording")
|
| 106 |
+
# Return a small silent audio buffer
|
| 107 |
+
self.final_audio_data = np.zeros((44100, self.channels), dtype=np.float32)
|
| 108 |
+
return self.final_audio_data
|
| 109 |
+
|
| 110 |
# First, get any remaining data from the queue
|
| 111 |
queue_data = []
|
| 112 |
max_attempts = 10 # Prevent infinite loops
|
|
|
|
| 293 |
|
| 294 |
def list_audio_devices() -> list:
|
| 295 |
"""
|
| 296 |
+
List all available audio input devices with fallback for environments without audio devices.
|
| 297 |
|
| 298 |
Returns:
|
| 299 |
list: A list of dictionaries containing device information
|
| 300 |
"""
|
| 301 |
try:
|
| 302 |
+
# First, check if we can even query devices
|
| 303 |
+
try:
|
| 304 |
+
devices = sd.query_devices()
|
| 305 |
+
input_devices = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 306 |
|
| 307 |
+
for i, device in enumerate(devices):
|
| 308 |
+
try:
|
| 309 |
+
if device.get('max_input_channels', 0) > 0:
|
| 310 |
+
input_devices.append({
|
| 311 |
+
'id': i,
|
| 312 |
+
'name': str(device.get('name', f'Device {i}')), # Ensure name is string
|
| 313 |
+
'input_channels': int(device.get('max_input_channels', 1)),
|
| 314 |
+
'default_samplerate': int(device.get('default_samplerate', 44100))
|
| 315 |
+
})
|
| 316 |
+
except (KeyError, TypeError, ValueError) as e:
|
| 317 |
+
print(f"Warning: Error processing device {i}: {e}")
|
| 318 |
+
continue
|
| 319 |
+
|
| 320 |
+
if input_devices:
|
| 321 |
+
return input_devices
|
| 322 |
+
|
| 323 |
+
except Exception as e:
|
| 324 |
+
print(f"Warning: Could not query audio devices: {e}")
|
| 325 |
|
| 326 |
+
# If we get here, either no input devices found or there was an error
|
| 327 |
+
print("No valid input devices found, using default configuration")
|
|
|
|
| 328 |
return [{
|
| 329 |
+
'id': sd.default.device[0] if hasattr(sd, 'default') and hasattr(sd.default, 'device') else 0,
|
| 330 |
'name': 'Default Device',
|
| 331 |
'input_channels': 1,
|
| 332 |
'default_samplerate': 44100
|
| 333 |
+
}]
|
| 334 |
+
|
| 335 |
+
except Exception as e:
|
| 336 |
+
print(f"Error in list_audio_devices: {e}")
|
| 337 |
+
# Final fallback in case anything else goes wrong
|
| 338 |
+
return [{
|
| 339 |
+
'id': 0,
|
| 340 |
+
'name': 'Fallback Device',
|
| 341 |
+
'input_channels': 1,
|
| 342 |
+
'default_samplerate': 44100
|
| 343 |
}]
|