pyqt5多线程实现录音

14 篇文章 0 订阅
该博客介绍了一个使用PyQt5和相关库实现的录音和播放功能的应用。应用中包含一个UI对话框,当点击特定按钮时,会启动录音线程,并在完成时切换到播放状态。录音线程利用sounddevice和soundfile库进行音频输入和输出,通过Qt线程保证了界面的响应性。
摘要由CSDN通过智能技术生成

请添加图片描述

# -*- coding: utf-8 -*-

import io
import sys
import threading
import time
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import numpy as np
import cv2
from ui import Ui_Dialog
import sounddevice as sd
import soundfile as sf
import queue


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(100, 100)
        self.label_5 = QtWidgets.QLabel(Dialog)
        self.label_5.setGeometry(QtCore.QRect(0, 0, 100, 100))
        self.label_5.setText("")
        self.label_5.setPixmap(QtGui.QPixmap("pic/record.gif"))
        self.label_5.setScaledContents(True)
        self.label_5.setObjectName("label_5")

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "发音检测"))

# qt线程 录音
class Worker(QThread):
    # 定义信号
    _signal = pyqtSignal(str)
    def __init__(self, parent=None):
        super(Worker, self).__init__(parent)
        self.isStart = False
    
    # 播放
    def play(self):
        event = threading.Event()
        data, fs = sf.read("test.wav", always_2d=True)
        current_frame = 0

        def callback(outdata, frames, time, status):
            global current_frame
            if status:
                print(status)
            chunksize = min(len(data) - current_frame, frames)
            outdata[:chunksize] = data[current_frame:current_frame + chunksize]
            if chunksize < frames:
                outdata[chunksize:] = 0
                raise sd.CallbackStop()
            current_frame += chunksize

        stream = sd.OutputStream(
            samplerate=fs, device=None, channels=data.shape[1],
            callback=callback, finished_callback=event.set)
        with stream:
            event.wait()  # Wait until playback is finished

    def stop(self):
        print("停止录音")
        self.isStart = False

    def run(self):
        # 开始录音
        self.isStart = True
        q = queue.Queue()


        def callback(indata, frames, time, status):
            """This is called (from a separate thread) for each audio block."""
            if status:
                print(status, file=sys.stderr)
            q.put(indata.copy())


        # soundfile expects an int, sounddevice provides a float:
        samplerate = 16000
        channels = 1
        # Make sure the file is opened before recording anything:
        with sf.SoundFile("test.wav", mode='w', samplerate=samplerate,channels=channels) as file:
            with sd.InputStream(samplerate=samplerate, device=None,channels=channels, callback=callback):
                self._signal.emit("开始录音")
                while self.isStart:
                    file.write(q.get())

        # 停止录音
        self._signal.emit("录音线程结束")

class mwindow(QWidget, Ui_Dialog):
    def __init__(self):
        super(mwindow, self).__init__()
        self.setupUi(self)
        self.flag = 0
        # 创建线程对象
        self.thread_obj = Worker()
        # 将信号与槽连接
        self.thread_obj._signal.connect(self.set_btn)

    # 信号带参回传
    def set_btn(self,a):
        print(a)
        # 设置可点击
        self.label_5.setEnabled(True)

    # 鼠标松开事件
    def mouseReleaseEvent(self, event):
        # 获取鼠标松开的坐标
        x = event.x()
        y = event.y()
        # 鼠标松开的对象
        label = self.childAt(x, y)
        # 判断鼠标松开的对象是否为label
        if isinstance(label, QLabel):
            # 获取label的名字
            name = label.objectName()
            if name=="label_5":
                # 设置不可点击
                self.label_5.setEnabled(False)
                # 判断是否为第一次按下
                if self.flag==0:
                    # 更换图片
                    label.setPixmap(QPixmap("pic/stop.gif"))
                    # 开启线程
                    self.thread_obj.start()
                    # 设置标志位为1
                    self.flag = 1
                else:
                    # 更换图片
                    label.setPixmap(QPixmap("pic/record.gif"))
                    self.thread_obj.stop()
                    self.flag=0

if __name__ == '__main__':
    app=QApplication(sys.argv)
    #初始化窗口
    m=mwindow()
    m.show()
    sys.exit(app.exec_())


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图像处理大大大大大牛啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值