在录制音频Python3的同时更新Tkinter中的进度条

时间:2017-11-10 08:06:31

标签: multithreading python-3.x user-interface tkinter pyaudio

这个简单程序的目标是能够显示麦克风录制的进度条(范围从0到30秒)。我正在使用Tkinter库,Python 3.6和PyAudio来记录。

我写完了各个部分的代码(录制+更新进度条)但我不知道如何更改代码以便它们同时发生(而不是一个接一个)。此外,我已经意识到,当我正在录制时,GUI会冻结(我无法点击或调整按钮大小),我也想知道如何解决这个问题。在做了一些更多的研究后,我感觉答案在于多线程或root.update(),但我不确定。

我正在寻找录制音频的代码示例我同时更新进度条。

以下是一个例子:

from tkinter import *
from tkinter import ttk
import tkinter as tk
import pyaudio
import numpy as np
np.random.seed(123)  # for reproducibility
import matplotlib
matplotlib.use('Agg')  # No pictures displayed


class Test_GUI(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        root = self

        label_title = Label(root, text="Progress Bar Recording Sample")
        label_title.pack(fil="x")

        topFrame = Frame(root)
        topFrame.pack(side=TOP)

        self.recordButton = Button(topFrame, text="Record", command=self.start)
        self.recordButton.pack(side=LEFT)

        self.progress = ttk.Progressbar(topFrame, orient="horizontal",
                                        length=200, mode="determinate")
        self.min = 0
        self.maxMin = 0
        self.progress.pack(side=RIGHT)

        # recording attributes.
        self.CHUNK = 1024
        self.FORMAT = pyaudio.paInt16
        self.CHANNELS = 2
        self.RATE = 44100
        self.RECORD_SECONDS = 15
        self.WAVE_OUTPUT_FILENAME = "/Users/Sree/Desktop/PythonPrograms/audio_output_test.wav"

    def start(self):
        print("here")

        self.progress["value"] = 0
        self.maxMin = 30
        self.progress["maximum"] = 30


        '''
        I need the following 2 lines to happen at the same time
        the progress bar needs to update from 1-30 seconds(which is the time I am recording)
        '''
        self.record()
        self.update_progress() #The progress bar is from 0 sec to 30 sec indicating what percentage of the time the mic has been recording for. 

    def update_progress(self):
        self.min += 0.1
        self.progress["value"] = self.min
        if self.min < self.maxMin:
            # update after 100 ms
            self.after(100, self.update_progress)

    def record(self):
        p = pyaudio.PyAudio()
        stream = p.open(format=self.FORMAT,
                             channels=self.CHANNELS,
                             rate=self.RATE,
                             input=True,
                             frames_per_buffer=self.CHUNK)

        print("* recording")

        frames = []

        for i in range(0, int(self.RATE / self.CHUNK * self.RECORD_SECONDS)):
            data = stream.read(self.CHUNK)
            frames.append(data)

        print("* done recording")

        stream.stop_stream()
        stream.close()
        p.terminate()

        wf = wave.open(self.WAVE_OUTPUT_FILENAME, 'wb')
        wf.setnchannels(self.CHANNELS)
        wf.setsampwidth(p.get_sample_size(self.FORMAT))
        wf.setframerate(self.RATE)
        wf.writeframes(b''.join(frames))
        wf.close()


app = Test_GUI()
app.mainloop()

1 个答案:

答案 0 :(得分:2)

要防止GUI在录制时冻结,您需要在单独的线程中启动录制。为此,您可以使用threading模块,并将self.record()方法中的start替换为:

record_thread = threading.Thread(target=self.record, daemon=True)
record_thread.start()