Qt5中如何同时实现倒计时与sounddevice音频录制?
解决QTimer与sounddevice录制同时运行的问题
你的问题出在record方法里的sd.wait()和文件保存操作会阻塞主线程,Qt的事件循环(包括QTimer的定时更新)必须在主线程空闲时才能处理,所以倒计时被卡住了。下面是具体的解决方案:
核心思路
将音频录制和文件保存的逻辑移到QThread子线程中执行,让主线程专注处理UI更新和QTimer的定时任务,避免阻塞。
修改后的完整代码
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel from PyQt5.QtCore import QTimer, QThread, pyqtSignal import sounddevice as sd from scipy.io.wavfile import write class RecordThread(QThread): # 定义信号,用于通知主线程录制完成 record_finished = pyqtSignal(str) def __init__(self, index, name): super().__init__() self.index = index self.name = name def run(self): # 录制逻辑移到子线程的run方法中 fs = 44100 seconds = 5 myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=1, device=self.index) sd.wait() print(f"STOPPED RECORDING {self.name}") # 保存文件 filename = f"{self.name}.wav" write(filename, fs, myrecording) # 发送信号通知主线程 self.record_finished.emit(filename) class CountDown(QWidget): def __init__(self, name, index): super().__init__() self.initUI(name, index) def initUI(self, name, index): self.setWindowTitle(f"Timer for {name}") layout = QVBoxLayout() self.setLayout(layout) self.time_label = QLabel(self) layout.addWidget(self.time_label) self.setFixedWidth(500) self.setFixedHeight(500) # 初始化QTimer self.timer = QTimer(self) self.current_time = 11 self.timer.timeout.connect(self.update_time) self.timer.start(1000) print(f"START RECORDING {name}") # 创建并启动录制线程 self.record_thread = RecordThread(index, name) self.record_thread.record_finished.connect(self.on_record_finished) self.record_thread.start() self.show() def update_time(self): self.current_time -= 1 print(self.current_time) self.time_label.setText(f"Current Time: {self.current_time}") if self.current_time == 0: self.timer.stop() self.close() def on_record_finished(self, filename): # 录制完成后的回调,可以在这里做后续处理 print(f"录制文件已保存:{filename}") # 如果需要在录制完成后停止计时,也可以在这里操作 # self.timer.stop() # self.close()
关键改动说明
- 新增
RecordThread类继承自QThread,把原本阻塞的录制和保存逻辑放到run方法中,子线程执行这些操作不会影响主线程事件循环。 - 通过
pyqtSignal信号在录制完成后通知主线程,实现线程间通信。 - 主线程中不再直接调用
record方法,而是创建并启动子线程,QTimer可以正常触发update_time更新UI。
内容的提问来源于stack exchange,提问作者jukebox41188
相关产品推荐
相关产品推荐

