I’m trying to build a really simple UI using Tkinter with a start/stop button to record sound. When user clicks start, it starts to record sound from microphone (follow the basic pyaudio example) and will stop when user click stop.
But it is not working properly and acting really weird, somehow if I use my phone to play a video, the output can sometimes record some sound (quality not good), but when I speak, it records nothing… But the sample code for recording from pyaudio works and can record my sound… It will be great if anyone can explain what is going on here… Thanks!
from tkinter import *
import wave
import sys
import pyaudio
import time
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
class DataCollectionUI(Tk):
def triggerOnClick(self):
if self.trigger['text'] == 'start':
print('===========================start recording')
self.p = pyaudio.PyAudio()
self.stream = self.p.open(format=FORMAT, channels=CHANNELS, rate=RATE, frames_per_buffer=CHUNK, input=True)
self.trigger['text'] = 'stop'
self.startTime = time.time()
else:
frames = []
for _ in range(0, RATE // CHUNK * int(round(time.time() - self.startTime, 0))):
audiolet = self.stream.read(CHUNK)
frames.append(audiolet)
print("=================== recording finished")
self.stream.close()
self.p.terminate()
self.wf = wave.open('output'+ str(self.count) +'.wav', 'wb')
self.wf.setnchannels(CHANNELS)
self.wf.setsampwidth(self.p.get_sample_size(FORMAT))
self.wf.setframerate(RATE)
self.wf.writeframes(b''.join(frames))
self.wf.close()
self.count += 1
self.trigger['text'] = 'start'
def __init__(self):
super().__init__()
self.title("data collection")
self.geometry("350x200")
self.trigger = Button(self, text="start", command=self.triggerOnClick)
self.trigger.grid(column=0, row=0, sticky='w')
self.count = 1
ui = DataCollectionUI()
ui.mainloop()
You aren’t even trying to read the incoming audio until the “stop” button is clicked – I suspect you need to read it periodically during recording, to keep internal buffers from filling up. When you’re using Tkinter, you can’t use the standard solution of reading in a loop, as that would simply lock up the GUI. Your options are to use Tkinter’s
.after()
method to periodically call the reading function, or use Pyaudio’s streaming option to do the reading in a separate thread.Thanks for your explanation! I saw some other’s working code which uses a separate thread. And my code above only starts to record after I click stop which explains why it records the sound from my cell phone but not my speech since I usually stop talking after the click… Could you paste your comment in an answer so I can pick it as answer?