From 2fbca72f63a7621cdd6a51e4bc86a185de4e7c67 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 15 Sep 2024 01:30:48 -0400 Subject: [PATCH] Initi pdab recorder --- src/discordAudioBot/pdab-recorder.py | 92 ++++++++++++++++++++++++++++ src/discordAudioBot/pdabHandler.mjs | 3 + 2 files changed, 95 insertions(+) create mode 100644 src/discordAudioBot/pdab-recorder.py diff --git a/src/discordAudioBot/pdab-recorder.py b/src/discordAudioBot/pdab-recorder.py new file mode 100644 index 0000000..5fc9acb --- /dev/null +++ b/src/discordAudioBot/pdab-recorder.py @@ -0,0 +1,92 @@ +import pyaudio +import wave +import argparse +import os +import datetime +from pydub import AudioSegment +from pydub.silence import detect_nonsilent + +# Parameters for the audio stream +FORMAT = pyaudio.paInt16 +CHANNELS = 2 +RATE = 48000 +CHUNK = 1024 +SILENCE_THRESHOLD = -50 # Silence threshold (adjust for noise level) +SILENCE_DURATION = 1250 # n miliseconds of silence to stop recording + +audio = pyaudio.PyAudio() + +# Create the recordings directory if it doesn't exist +RECORDINGS_DIR = './recordings' +if not os.path.exists(RECORDINGS_DIR): + os.makedirs(RECORDINGS_DIR) + +def get_filename(): + """Generate a filename with the current date and time, stored in the recordings directory.""" + return os.path.join(RECORDINGS_DIR, datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + ".wav") + + +def save_wave_file(filename, audio_segment): + """Save the given audio segment to a WAV file in the recordings directory.""" + audio_segment.export(filename, format="wav") + print(f"Saved recording: {filename}") + + +def detect_nonsilent_chunk(sound, silence_thresh=SILENCE_THRESHOLD, silence_len=SILENCE_DURATION): + """Detect if there's a nonsilent chunk in the sound.""" + return detect_nonsilent(sound, min_silence_len=silence_len, silence_thresh=silence_thresh) + + +def record_transmissions(device_id: int): + stream = audio.open(format=FORMAT, channels=CHANNELS, + rate=RATE, input=True, + frames_per_buffer=CHUNK, input_device_index=device_id ) + + frames = [] + recording = False + + print("Listening for transmissions...") + + while True: + data = stream.read(CHUNK) + frames.append(data) + + # Convert current audio buffer to AudioSegment for processing + sound = AudioSegment(b''.join(frames), sample_width=audio.get_sample_size(FORMAT), frame_rate=RATE, channels=CHANNELS) + + # Detect if there's sound (nonsilent chunk) + nonsilent_chunks = detect_nonsilent_chunk(sound) + + if nonsilent_chunks and not recording: + print("Transmission detected, starting recording...") + recording = True + frames = [] # Reset frames to start fresh for this transmission + + elif recording and not nonsilent_chunks: + # Transmission has ended (silence detected for the required duration) + if len(frames) > 0: + # Save recording without leading/trailing silence + trimmed_audio = sound[nonsilent_chunks[0][0]:nonsilent_chunks[-1][1]] + filename = get_filename() + save_wave_file(filename, trimmed_audio) + + recording = False + frames.clear() # Clear frames to prepare for the next transmission + print("Recording stopped, waiting for the next transmission...") + + +def parse_arguments(): + parser = argparse.ArgumentParser() + parser.add_argument("device_id", type=int, help="The ID of the audio device to use") + return parser.parse_args() + + +if __name__ == "__main__": + try: + args = parse_arguments() + logger.info("Arguments: %s", args) + record_transmissions(device=args['device_id']) + except KeyboardInterrupt: + print("Stopping...") + finally: + audio.terminate() diff --git a/src/discordAudioBot/pdabHandler.mjs b/src/discordAudioBot/pdabHandler.mjs index a5d5452..65968ba 100644 --- a/src/discordAudioBot/pdabHandler.mjs +++ b/src/discordAudioBot/pdabHandler.mjs @@ -27,6 +27,9 @@ export const initDiscordBotClient = (clientId, callback, runPDAB = true) => { if (runPDAB) launchProcess("python", [join(__dirname, "../../pdab/main.py"), process.env.AUDIO_DEVICE_ID, clientId, port], false, false, join(__dirname, "../../pdab")); pdabProcess = true; // TODO - Make this more dynamic + + // Start the PDAB Recorder + if (runPDAB) launchProcess("python", [join(__dirname, "./pdab-recorder.py"), process.env.AUDIO_DEVICE_ID], false, false, __dirname); } export const startPdabSocketServer = () => {