diff options
Diffstat (limited to 'solo-tool-project/src/solo_tool/recorder.py')
| -rw-r--r-- | solo-tool-project/src/solo_tool/recorder.py | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/solo-tool-project/src/solo_tool/recorder.py b/solo-tool-project/src/solo_tool/recorder.py new file mode 100644 index 0000000..71c8ac8 --- /dev/null +++ b/solo-tool-project/src/solo_tool/recorder.py @@ -0,0 +1,72 @@ +from pathlib import Path + +import pyaudio as pa +from pydub import AudioSegment, effects + +class Recording: + def __init__(self, frames: list, channels: int, samplingRate: int, sampleFormat: int): + self._segment = AudioSegment( + data=b''.join(frames), + sample_width=sampleFormat, + frame_rate=samplingRate, + channels=channels + ) + self._postProcess() + + def _postProcess(self) -> None: + self._segment = effects.normalize(self._segment) + + def writeWav(self, file: Path) -> None: + self._segment.export(str(file), format="wav") + + def writeMp3(self, file: Path) -> None: + self._segment.export(str(file), format="mp3", bitrate="320k") + +class Recorder: + def __init__(self, bufferSize: int, samplingRate: int): + self._bufferSize = bufferSize + self._samplingRate = samplingRate + self._sampleFormat = pa.paInt16 + self._channels = 2 + self._pa = pa.PyAudio() + self._stream = None + self._frames = [] + + def __del__(self): + if self.recording: + self._stream.stop_stream() + self._stream.close() + + def _callback(self, inData, frameCount, timeInfo, statusFlags): + if statusFlags != pa.paNoError and statusFlags != pa.paInputOverflowed: + print(f"Recorder callback got status {hex(statusFlags)}, aborting") + # TODO figure out what status code is being received and if it's a problem or not + #return (None, pa.paAbort) + + self._frames.append(inData) + return (None, pa.paContinue) + + def startRecording(self) -> None: + if self.recording: + return + + self._frames.clear() + self._stream = self._pa.open(format=self._sampleFormat, + channels=self._channels, + rate=self._samplingRate, + frames_per_buffer=self._bufferSize, + input=True, + stream_callback=self._callback) + + def stopRecording(self) -> Recording: + if not self.recording: + return None + self._stream.stop_stream() + self._stream.close() + self._stream = None + return Recording(self._frames, self._channels, self._samplingRate, self._pa.get_sample_size(self._sampleFormat)) + + @property + def recording(self) -> bool: + return self._stream is not None + |
