Reputation: 9
I was wondering if there is a way to stop recording and export that recording in the finally: statement in python. Example: let’s say I’m recording then all of a sudden my script crashes while I’m recording, would there be a way to stop recording and exporting that were to happen?
I’ve tried making a separate function that exports and stops recording and have that run on finally:, but that didn’t work, it just made a new file. Any help would be appreciated. My code is below:
import pyaudio
import wave
import time
import signal
from datetime import datetime
# Configuration
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 10
# Initialize PyAudio
audio = pyaudio.PyAudio()
def record_audio(filename):
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True, frames_per_buffer=CHUNK)
print("Recording started")
frames = []
data = stream.read(CHUNK)
frames.append(data)
print("Recording stopped")
stream.stop_stream()
stream.close()
# Save to WAV file
wf = wave.open(filename, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(audio.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
def main():
try:
while True:
timestamp = datetime.now().strftime("%m-%d-%Y_%H-%M-%S")
wav_filename = f"/home/henrikkoehler/Desktop/Audio_Files/{timestamp}.wav"
record_audio(wav_filename)
print(f"Audio saved to {wav_filename}")
# Wait a bit to avoid multiple recordings from a single press
time.sleep(1)
except KeyboardInterrupt:
print("Exiting...")
except:
time.sleep(1)
t_end = time.time() + 15 * 1
while time.time() < t_end:
print("Error! Restart!")
finally:
audio.terminate()
if __name__ == "__main__":
main()
Upvotes: 0
Views: 80
Reputation: 443
To do this, you should separate the file writing and stream closing code into separate functions. This way, you can access the code anywhere without copy pasting it.
def close_stream(stream):
try:
stream.stop_stream()
stream.close()
print("Recording stopped")
except: pass
def write_file(filename, frames):
try:
# Save to WAV file
wf = wave.open(filename, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(audio.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
print(f"Audio saved to {wav_filename}")
except: pass
Then make your stream recording, filename, and recorded frames from your function record_audio()
global so you can access them outside of your function. This way you won't get an undefined
error.
global stream, frames
global wav_filename
Make sure to move your messages of confirmation for writing files and closing the recording after the corresponding code to make sure the entire process finishes in case code breaks. Additionally, use a for loop to record in duration instead of one chunk per recording.
Your final code should look something like this:
import pyaudio
import wave
import time
import signal
from datetime import datetime
# Configuration
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 10
# Initialize PyAudio
audio = pyaudio.PyAudio()
def record_audio(filename):
global stream, frames
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True, frames_per_buffer=CHUNK)
print("Recording started")
frames = []
#data = stream.read(CHUNK)
#frames.append(data)
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
close_recording(stream)
write_file(filename, frames)
def close_recording(recording):
try:
recording.stop_stream()
recording.close()
print("Recording stopped")
except: pass
def write_file(filename, frames):
try:
# Save to WAV file
wf = wave.open(filename, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(audio.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
print(f"Audio saved to {wav_filename}")
except: pass
def main():
global wav_filename
try:
timestamp = datetime.now().strftime("%m-%d-%Y_%H-%M-%S")
wav_filename = f"./{timestamp}.wav"
record_audio(wav_filename)
# Wait a bit to avoid multiple recordings from a single press
time.sleep(1)
except KeyboardInterrupt:
close_recording(stream)
write_file(wav_filename, frames)
print("Exiting...")
except:
close_recording(stream)
write_file(wav_filename, frames)
time.sleep(1)
t_end = time.time() + 15 * 1
while time.time() < t_end:
print("Error! Restart!")
finally:
audio.terminate()
if __name__ == "__main__":
main()
Additionally, if you want to record indefinitely instead of only for 10 seconds, use a while True:
instead of a for
loop in record_audio()
.
def record_audio(filename):
global stream, frames
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True, frames_per_buffer=CHUNK)
print("Recording started")
frames = []
#data = stream.read(CHUNK)
#frames.append(data)
#for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
while True: #Use while True to keep adding to recording until you interrupt with exit
data = stream.read(CHUNK)
frames.append(data)
close_recording(stream)
write_file(filename, frames)
Upvotes: 0