Update audio_capture.py
Browse files- audio_capture.py +23 -21
audio_capture.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
-
# audio_capture.py (
|
2 |
-
import
|
3 |
import numpy as np
|
4 |
import wave
|
5 |
import os
|
@@ -8,41 +8,42 @@ import config
|
|
8 |
|
9 |
class AudioRecorder:
|
10 |
def __init__(self):
|
11 |
-
self.audio = pyaudio.PyAudio()
|
12 |
-
self.stream = None
|
13 |
self.is_recording = False
|
14 |
self.sample_rate = config.SAMPLE_RATE
|
15 |
self.filename = f"meeting_{datetime.now().strftime('%Y%m%d_%H%M%S')}.wav"
|
16 |
self.audio_buffer = []
|
|
|
17 |
|
18 |
def start_recording(self):
|
19 |
self.is_recording = True
|
20 |
self.audio_buffer = []
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
channels=config.CHANNELS,
|
24 |
-
|
25 |
-
|
26 |
-
frames_per_buffer=config.CHUNK_SIZE,
|
27 |
-
input_device_index=config.INPUT_DEVICE_INDEX
|
28 |
)
|
|
|
29 |
return True
|
30 |
|
31 |
def get_audio_chunk(self):
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
return np.frombuffer(data, dtype=np.int16)
|
37 |
-
except OSError as e:
|
38 |
-
print(f"Audio error: {str(e)}")
|
39 |
-
return None
|
40 |
return None
|
41 |
|
42 |
def stop_recording(self):
|
43 |
if self.is_recording:
|
44 |
self.is_recording = False
|
45 |
-
self.stream.
|
46 |
self.stream.close()
|
47 |
self._save_recording()
|
48 |
return os.path.join(config.RECORDINGS_DIR, self.filename)
|
@@ -50,8 +51,9 @@ class AudioRecorder:
|
|
50 |
|
51 |
def _save_recording(self):
|
52 |
os.makedirs(config.RECORDINGS_DIR, exist_ok=True)
|
|
|
53 |
with wave.open(os.path.join(config.RECORDINGS_DIR, self.filename), 'wb') as wf:
|
54 |
wf.setnchannels(config.CHANNELS)
|
55 |
-
wf.setsampwidth(
|
56 |
wf.setframerate(self.sample_rate)
|
57 |
-
wf.writeframes(
|
|
|
1 |
+
# audio_capture.py (Updated with SoundDevice)
|
2 |
+
import sounddevice as sd
|
3 |
import numpy as np
|
4 |
import wave
|
5 |
import os
|
|
|
8 |
|
9 |
class AudioRecorder:
|
10 |
def __init__(self):
|
|
|
|
|
11 |
self.is_recording = False
|
12 |
self.sample_rate = config.SAMPLE_RATE
|
13 |
self.filename = f"meeting_{datetime.now().strftime('%Y%m%d_%H%M%S')}.wav"
|
14 |
self.audio_buffer = []
|
15 |
+
self.stream = None
|
16 |
|
17 |
def start_recording(self):
|
18 |
self.is_recording = True
|
19 |
self.audio_buffer = []
|
20 |
+
|
21 |
+
def callback(indata, frames, time, status):
|
22 |
+
if status:
|
23 |
+
print(f"Audio error: {status}")
|
24 |
+
if self.is_recording:
|
25 |
+
self.audio_buffer.append(indata.copy())
|
26 |
+
|
27 |
+
self.stream = sd.InputStream(
|
28 |
+
samplerate=self.sample_rate,
|
29 |
channels=config.CHANNELS,
|
30 |
+
callback=callback,
|
31 |
+
dtype='int16'
|
|
|
|
|
32 |
)
|
33 |
+
self.stream.start()
|
34 |
return True
|
35 |
|
36 |
def get_audio_chunk(self):
|
37 |
+
# In this implementation, we don't need to return chunks because
|
38 |
+
# we are using a callback. But to keep the interface, we return the last chunk.
|
39 |
+
if self.is_recording and self.audio_buffer:
|
40 |
+
return self.audio_buffer[-1]
|
|
|
|
|
|
|
|
|
41 |
return None
|
42 |
|
43 |
def stop_recording(self):
|
44 |
if self.is_recording:
|
45 |
self.is_recording = False
|
46 |
+
self.stream.stop()
|
47 |
self.stream.close()
|
48 |
self._save_recording()
|
49 |
return os.path.join(config.RECORDINGS_DIR, self.filename)
|
|
|
51 |
|
52 |
def _save_recording(self):
|
53 |
os.makedirs(config.RECORDINGS_DIR, exist_ok=True)
|
54 |
+
audio_data = np.concatenate(self.audio_buffer, axis=0)
|
55 |
with wave.open(os.path.join(config.RECORDINGS_DIR, self.filename), 'wb') as wf:
|
56 |
wf.setnchannels(config.CHANNELS)
|
57 |
+
wf.setsampwidth(2) # 2 bytes for int16
|
58 |
wf.setframerate(self.sample_rate)
|
59 |
+
wf.writeframes(audio_data.tobytes())
|