Tkinter timer while recording - python

Same as in topic, i want to create timer while the recording function would run. I have tried a lot of ideas but all of them resulted as an error or just broke up program, maybe you have some ideas?
class rec(object):
def __init__(self):
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
CHUNK = 1024
WAVE_OUTPUT_FILENAME = str(e2.get() + '.wav')
try:
RECORD_SECONDS = int(e1.get())
except ValueError:
tkMessageBox.showinfo("Error", "Please Enter number of seconds")
i = 0
while os.path.exists(WAVE_OUTPUT_FILENAME):
WAVE_OUTPUT_FILENAME = str(e2.get() + '%d.wav'%i)
i += 1
audio = pyaudio.PyAudio()
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True,
frames_per_buffer=CHUNK)
frames = []
print "recording...\n\n"
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
sys.stdout.write('\r%i' % i)
data = stream.read(CHUNK)
frames.append(data)
print "\nfinished recording\n"
# stop Recording
stream.stop_stream()
stream.close()
audio.terminate()
waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(audio.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
waveFile.writeframes(b''.join(frames))
# waveFile.Wave_read.getnframes()
waveFile.close()
tkMessageBox.showinfo("Recorded", "Track:%s"%WAVE_OUTPUT_FILENAME)
I tried to make other function with timer and initiate that function, when i press button, but if i pressed button firstly program ran rec function, and after gone timer function, also i tried to initiate those function by pipe but it does the same, do i have to make that with threads?

Related

pyAudio - stop recording at will from command line

I'm not really that good with Python. Recently I've been toying around with pyAudio and using a simple script managed to record system sound. Thing is, the script I'm using is ran using a fixed timer. Instead, I want to end the recording whenever I want, from command line.
Does anyone know how to achieve this, if possible at all?
import pyaudio
import wave
import sys
DURATION = int(sys.argv[1])
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
CHUNK = 1024
RECORD_SECONDS = DURATION
WAVE_OUTPUT_FILENAME = "file.wav"
print("hello")
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK)
print("Recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("Finished recording")
stream.stop_stream()
stream.close()
p.terminate()
waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(p.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
waveFile.writeframes(b''.join(frames))
waveFile.close()

How to record 2 audio feeds simultaneously?

I want to record a audio track and save it 2 diffrent .wav files. The audio tracks should be saved with a delay of ca. 6 seconds and each .wav should be 12 seconds long.
I tried to do it with multiprocessing and pyaudio, but i cant manage to get it working
Please note that i am a beginner in python and that this is my first post on stackoverflow!
def func1():
#Record and save a 12 seconds long .wav
def func2():
#Record and save a 12 seconds long .wav
if __name__ == '__main__':
p1 = Process(target=func1)
p1.start()
p2 = Process(target=func2)
p2.start()
p1.join()
p2.join()
#start func2 6 seconds after func1
I would expect a data structure like this:
|---1.wav---|---1.wav---|---1.wav---|
|---2.wav---|---2.wav---|---2.wav---|
6sec 12sec 18sec 24sec 30sec 36sec 42sec
EDIT:
I came up with a bit of code that seems to work kind of well. It has a delay of .144 seconds. I am happy about improvement od this code. This code uses threading instead of multiprocessing.
import pyaudio
import wave
from threading import Thread
import time
from datetime import datetime
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
CHUNK = 1024
CHUNK1 = 1024
RECORD_SECONDS = 12
WAVE_OUTPUT_FILENAME1 = name = "outputs/output_1"+datetime.now().strftime("%m:%d:%Y-")
WAVE_OUTPUT_FILENAME2 = name = "outputs/output_2"+datetime.now().strftime("%m:%d:%Y-")
def func1():
while 1==1:
global FORMAT
global CHANNELS
global RATE
global CHUNK
global RECORD_SECONDS
global WAVE_OUTPUT_FILENAME1
WAVE_OUTPUT_FILENAME1 = name = "outputs/output1_"#+datetime.now().strftime("%m:%d:%Y-")
audio = pyaudio.PyAudio()
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True,
frames_per_buffer=CHUNK)
print("recording...")
frames = []
WAVE_OUTPUT_FILENAME1 = WAVE_OUTPUT_FILENAME1+datetime.now().strftime("%H;%M;%S.%f--")
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
WAVE_OUTPUT_FILENAME1 = WAVE_OUTPUT_FILENAME1 + datetime.now().strftime("%H;%M;%S.%f")+".wav"
print("finished recording")
# stop Recording
stream.stop_stream()
stream.close()
audio.terminate()
waveFile = wave.open(WAVE_OUTPUT_FILENAME1, 'wb')
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(audio.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
waveFile.writeframes(b''.join(frames))
waveFile.close()
def func2():
time.sleep(6)
while 1==1:
global FORMAT
global CHANNELS
global RATE
global CHUNK1
global RECORD_SECONDS
global WAVE_OUTPUT_FILENAME2
WAVE_OUTPUT_FILENAME2 = name = "outputs/output2_"#+datetime.now().strftime("%m:%d:%Y-")
audio = pyaudio.PyAudio()
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True,
frames_per_buffer=CHUNK1)
print("recording...")
frames = []
WAVE_OUTPUT_FILENAME2 = WAVE_OUTPUT_FILENAME2+datetime.now().strftime("%H;%M;%S.%f--")
for i in range(0, int(RATE / CHUNK1 * RECORD_SECONDS)):
data = stream.read(CHUNK1)
frames.append(data)
WAVE_OUTPUT_FILENAME2 = WAVE_OUTPUT_FILENAME2 + datetime.now().strftime("%H;%M;%S.%f")+".wav"
print("finished recording")
# stop Recording
stream.stop_stream()
stream.close()
audio.terminate()
waveFile = wave.open(WAVE_OUTPUT_FILENAME2, 'wb')
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(audio.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
waveFile.writeframes(b''.join(frames))
waveFile.close()
if __name__ == '__main__':
Thread(target = func1).start()
Thread(target = func2).start()
why do you think you need multiprocessing? I think it just complicates things
how about just recording in 6 second (or smaller) chunks/frames and write the correct frames to each file.
I've got a bit carried away, and written a nice class to do this:
import pyaudio
import wave
import time
class OverlappedRecorder:
def __init__(
self, secs_per_file, secs_between_file, *,
num_channels=2, sample_rate=48000,
sample_format=pyaudio.paInt16,
):
# various constants needed later
self.num_channels = num_channels
self.sample_width = pyaudio.get_sample_size(sample_format)
self.sample_rate = sample_rate
self.frames_between_start = int(secs_between_file * sample_rate)
self.frames_per_file = int(secs_per_file * sample_rate)
# mutable state needed to keep everything going
self.files = []
self.frames_till_next_file = 0
self.pa = pyaudio.PyAudio()
self.stream = self.pa.open(
format=sample_format, channels=num_channels,
rate=sample_rate, frames_per_buffer=1024,
input=True, start=False,
stream_callback=self._callback,
)
def sleep_while_active(self):
while self.stream.is_active():
time.sleep(0.2)
def begin_wave_file(self):
"internal function to start a new WAV file"
path = time.strftime(
'recording-%Y-%m-%d-%H.%M.%S.wav',
time.localtime()
)
file = wave.open(path, 'wb')
file.setnchannels(self.num_channels)
file.setsampwidth(self.sample_width)
file.setframerate(self.sample_rate)
self.files.append(file)
# context manager stuff, recording starts when entered using "with"
def __enter__(self):
self.stream.start_stream()
return self
# exiting shuts everything down
def __exit__(self, exc_type, exc_val, exc_tb):
self.stream.stop_stream()
self.stream.close()
self.pa.terminate()
for file in self.files:
file.close()
# called by pyaudio when a new set of frames are ready
def _callback(self, data, frame_count, time_info, status):
self.frames_till_next_file -= frame_count
# see if we need to start a new file
if self.frames_till_next_file < 0:
self.frames_till_next_file += self.frames_between_start
self.begin_wave_file()
# can't remove from lists while iterating
# keep a list of files to close and remove later
done = []
for file in self.files:
remain = self.frames_per_file - file.getnframes()
# add appropriate amount of data to all open files
if frame_count < remain:
file.writeframesraw(data)
else:
remain *= self.sample_width * self.num_channels
file.writeframesraw(data[:remain])
done.append(file)
# close anything that finished
for file in done:
file.close()
self.files.remove(file)
# tell pyaudio to keep going
return (None, pyaudio.paContinue)
basic usage is: create an object, enter it using with and it'll start recording, and when you exit it'll stop and clean up.
rec = OverlappedRecorder(12, 6)
with rec:
time.sleep(30)
will let it run for 30 seconds, or you could do:
with OverlappedRecorder(12, 6) as rec:
rec.sleep_while_active()
to let it run until you hit Ctrl+C to kill the program, or you could put a call to input() in there to make it stop when you press enter, or whatever else you like.
a few comments on the code you posted:
you only need to declare global variables if you're going to modify them
why do you have seperate functions? why not just have a single function, and just delay start()ing the second Thread
why are you setting WAVE_OUTPUT_FILENAME1 so many times? just save the start_time and end_time, then format the string in one go
you don't have to read() in chunks, if you know it's going to fit in memory just read everything all in one go
you shouldn't need to keep starting and stopping recording, just open it once in each thread and if you're lucky samples will accumulate in the buffer while you're writing the wav file to disk
something like:
import pyaudio
import wave
import time
from datetime import datetime
from threading import Thread
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 12
def recorder(prefix):
audio = pyaudio.PyAudio()
stream = audio.open(
format=FORMAT, channels=CHANNELS,
rate=RATE, input=True,
)
try:
while True:
start_time = datetime.now()
print("recording started", start_time)
data = stream.read(RATE * RECORD_SECONDS, False)
end_time = datetime.now()
print("finished", end_time)
name = f'{prefix}{start_time:%Y-%m-%d-%H-%M-%S.%f}-{end_time:%H-%M-%S.%f}.wav'
print("writing", name)
with wave.open(name, 'wb') as waveFile:
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(audio.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
waveFile.writeframes(data)
finally:
stream.stop_stream()
stream.close()
audio.terminate()
if __name__ == '__main__':
Thread(target=recorder, args=('outputs/output_1-',)).start()
time.sleep(6)
Thread(target=recorder, args=('outputs/output_2-',)).start()
a few differences:
the version using threading is much less code!
my version allows an arbitrary number of files without using up multiple OS threads for each file (there's the Python thread and pyaudio has an internal thread looking after audio buffers)
my version saves partial files
hope all the helps / makes sense!

PyAudio gives no output in the recording file despite using the appropriate input device

I am trying to use pyaudio to record audio but with the program I have it does not have any output
I use input_device_index = 0 which is my computers microphone. I have tried connecting to bluetooth headphones but this gives an error since the CHUNK variable needs to be changed. This is my code currently:
def record(outputFile):
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 2
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT, input_device_index = 0,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(outputFile, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
I try to record a test file with a lot of sound but I just get a file with no sound at all. Does anyone know the issue?

Add multiple Layers to audio recording with PyAudio

Im been experimenting with audio recording and playback using pyaudio.
I'm able to record a file but I need to be able to add layers on top of it. What I'm trying to do is record a 10 second file then start playing.
While its playing I want to continue to record additional 10 sec layers and add them over top of the prior recording.
Is there a way to do this with Python?
import pyaudio
import wave
CHUNK = 2
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 3
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print(int(RATE / CHUNK * RECORD_SECONDS))
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
I found a module called "PyDub" which does this easily.
http://pydub.com/
from pydub import AudioSegment
track1 = AudioSegment.from_file(track1wav)
track2 = AudioSegment.from_file(track2wav)
combined = track1.overlay(track2)
print ("overlaying recording")
combined.export(track1wav, format='wav')

voice recording using pyaudio

i am trying to record voice using python.
i tried to use the pyaudio module it saved a wav file on my computer but recorded a static voice.
any suggestions?
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "voice.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
First, make sure your microphone is actually connected, on and not muted.
You are not providing a device index when opening the stream. This means that you will get the device that PyAudio considers the default. Which might not be your microphone.
Use the get_device_count and get_device_info_by_index methods of the PyAudio object in an interactive Python session. Print the dictionaries that get_device_info_by_index returns to determine which device index represents your microphone, and provide that index number as the input_device_index parameter when opening the stream.
below code will list indexes of the available recording devices,then user can give a specific index as the input,code will start recording via given recording device index.
import pyaudio
import wave
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
CHUNK = 512
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "recordedFile.wav"
device_index = 2
audio = pyaudio.PyAudio()
print("----------------------record device list---------------------")
info = audio.get_host_api_info_by_index(0)
numdevices = info.get('deviceCount')
for i in range(0, numdevices):
if (audio.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0:
print("Input Device id ", i, " - ", audio.get_device_info_by_host_api_device_index(0, i).get('name'))
print("-------------------------------------------------------------")
index = int(input())
print("recording via index "+str(index))
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True,input_device_index = index,
frames_per_buffer=CHUNK)
print ("recording started")
Recordframes = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
Recordframes.append(data)
print ("recording stopped")
stream.stop_stream()
stream.close()
audio.terminate()
waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(audio.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
waveFile.writeframes(b''.join(Recordframes))
waveFile.close()
Your code works in my environment: Win7 and Python3.4 - I get my voice recorded using my Laptops's microphone.
Maybe your microphone's recording level is set too low. Or is it muted or disabled?
Make sure your Microphone is connected to the computer. It can be identified using below code.
import speech_recognition as sr
for index, name in enumerate(sr.Microphone.list_microphone_names()):
print("Microphone with name \"{1}\" found for microphone(device_index{0})".format(index, name))

Categories

Resources