You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 21:26:16