Python实现可以语音聊天的桌面宠物程序

目录

简介

程序

源代码

GUI

        DesktopWife.py

        MusicPlayer.py

        WeatherGui.py

语音


简介

        普通的桌面宠物程序只能动一动,于是我给程序添加了语言,既可以聊天,也可以实现一些自动功能,不如搜索,打开程序什么的。


程序

Python实现可以语音聊天的桌面宠物程序_第1张图片


源代码

        gui界面都是使用PyQt5开发的,语音唤醒功能也是使用的第三方库和api   

GUI

        DesktopWife.py

import sys
import os

from PyQt5.QtGui import QCursor
from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QPainterPath
from PyQt5.QtGui import QRegion
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QRectF
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QDesktopWidget
from PyQt5.QtWidgets import QMenu
from PyQt5.QtWidgets import QAction
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtWidgets import QMessageBox

import requests

import WeatherGui
import MusicPlayer
import Tray
import VoiceToText

VoiceToText.run()

"""主界面"""
class DesktopWife(QWidget):
    def __init__(self):
        super(DesktopWife, self).__init__()
        self.UI()

    def UI(self):
        self.Image = QPixmap(".\image\\bg.png")
        self.WindowSize = QDesktopWidget().screenGeometry()

        self.setWindowTitle("DesktopWife")
        self.resize(int(self.Image.width()), int(self.Image.height()))
        self.move(int((self.WindowSize.width() - self.Image.width()) / 2), int((self.WindowSize.height() - self.Image.height()) / 2))
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SubWindow)
        # setAutoFillBackground(True)表示的是自动填充背景,False为透明背景
        self.setAutoFillBackground(False)
        # 窗口透明,窗体空间不透明
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        self.PlayLabel = QLabel(self)
        self.PlayLabel.setPixmap(self.Image)

        self.WindowMessage = QLabel("我好困", self)
        self.WindowMessage.setGeometry(int((self.Image.width() - 80) / 2) + 10, 10, 200, 40)
        self.WindowMessage.setStyleSheet("color: white;")

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self._WindowMenu)

        self.Timer = QTimer()
        self.Timer.start(5000)
        self.Timer.timeout.connect(self.RandomWindowMessage)

    """右键菜单"""
    def _WindowMenu(self):
        self.Menu = QMenu(self)
        self.Menu.setStyleSheet("background-color: black; color: white;")

        self.WeatherForecastQAction = QAction(QIcon(".\image\Button.png"), u"查看天气", self)
        self.Menu.addAction(self.WeatherForecastQAction)

        self.PlayMusicQAction = QAction(QIcon(".\image\Button.png"), u"播放音乐", self)
        self.Menu.addAction(self.PlayMusicQAction)

        self.StartTray = QAction(QIcon(".\image\\bg.png"), u"退置托盘", self)
        self.Menu.addAction(self.StartTray)

        self.CloseWindowAction = QAction(QIcon(".\image\Quit.png"), u"退出程序", self)
        self.Menu.addAction(self.CloseWindowAction)

        self.WeatherForecastQAction.triggered.connect(self.WeatherForecast)
        self.PlayMusicQAction.triggered.connect(self.MusicPaly)
        self.StartTray.triggered.connect(self.SetTray)
        self.CloseWindowAction.triggered.connect(self.ColseWindowActionEvent)

        self.Menu.popup(QCursor.pos())

        # 圆角
        rect = QRectF(0, 0, self.Menu.width(), self.Menu.height())
        path = QPainterPath()
        path.addRoundedRect(rect, 10, 10)
        polygon = path.toFillPolygon().toPolygon()
        region = QRegion(polygon)
        self.Menu.setMask(region)

    def ColseWindowActionEvent(self):
        VoiceToText._conent = False
        self.close()
        sys.exit()

    """系统托盘"""
    def SetTray(self):
        self._Tray = Tray.TrayIcon(self)
        self._Tray.show()
        self.hide()

    """随机一诗"""
    # 因为csdn的智障检测,这里无法查看

    """音乐播放"""
    def MusicPaly(self):
        self.file, _Type = QFileDialog.getOpenFileName(self, u"选择音乐文件", f"{os.path.split(__file__)[0]}\\music")
        if os.path.isfile(self.file):
            self._MusicPlayGui = MusicPlayer.MusicGui(self.file)
            self._MusicPlayGui.show()
        else:
            QMessageBox.information(self, "提示", f"文件:{self.file} 无法识别")

    """天气预报"""
    def WeatherForecast(self):
        self.WeatherForecastGUI = WeatherGui.WeatherGUI()
        self.WeatherForecastGUI.show()

    """重写移动事假,更改鼠标图标"""
    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_flag = True
            self.m_Position = event.globalPos() - self.pos()  # 获取鼠标相对窗口的位置
            event.accept()
            self.setCursor(QCursor(Qt.OpenHandCursor))  # 更改鼠标图标

    def mouseMoveEvent(self, QMouseEvent):
        if Qt.LeftButton and self.m_flag:
            self.move(QMouseEvent.globalPos() - self.m_Position)  # 更改窗口位置
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        self.m_flag = False
        self.setCursor(QCursor(Qt.ArrowCursor))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    Window = DesktopWife()
    Window.show()
    app.exec_()

        MusicPlayer.py

import os

from PyQt5 import QtMultimedia
from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QRegion
from PyQt5.QtGui import QCursor
from PyQt5.QtGui import QPainterPath
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QUrl
from PyQt5.QtCore import QSize
from PyQt5.QtCore import QRectF
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QSlider
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QPushButton

from mutagen import File

"""音乐播放界面"""
class MusicGui(QWidget):
    def __init__(self, _file):
        super(MusicGui, self).__init__()
        self.file = _file
        self.GetMusicIcon()
        self.UI()
        self.Music = QUrl.fromLocalFile(_file)
        self.Content = QtMultimedia.QMediaContent(self.Music)
        self.player = QtMultimedia.QMediaPlayer()
        self.player.setVolume(100)
        self.player.setMedia(self.Content)

    def UI(self):
        self.setWindowTitle("DesktopWife-MusicPlayGui")
        self.resize(240, 135)

        self.QuitButton = QPushButton(self)
        self.QuitButton.setIcon(QIcon(".\image\MusicQuit.png"))
        self.QuitButton.setIconSize(QSize(200, 200))
        self.QuitButton.setGeometry(208, 10, 20, 20)
        QuitButtonRect = QRectF(0, 0, self.QuitButton.width(), self.QuitButton.height())
        QuitButtonPath = QPainterPath()
        QuitButtonPath.addRoundedRect(QuitButtonRect, 10, 10)
        QuitButtonPolgon = QuitButtonPath.toFillPolygon().toPolygon()
        QuitButtonRegion = QRegion(QuitButtonPolgon)
        self.QuitButton.setMask(QuitButtonRegion)
        self.QuitButton.clicked.connect(self.QuitButtonEvent)

        self.WindowMinimizedButton = QPushButton(self)
        self.WindowMinimizedButton.setIcon(QIcon(".\image\WindowMinimized.png"))
        self.WindowMinimizedButton.setIconSize(QSize(20, 20))
        self.WindowMinimizedButton.setGeometry(180, 10, 20, 20)
        WindowMinimizedButtonRect = QRectF(0, 0,  self.WindowMinimizedButton.width(), self.WindowMinimizedButton.height())
        WindowMinimizedButtonPath = QPainterPath()
        WindowMinimizedButtonPath.addRoundedRect(WindowMinimizedButtonRect, 10, 10)
        WindowMinimizedButtonPolgon = QuitButtonPath.toFillPolygon().toPolygon()
        WindowMinimizedButtonRegion = QRegion(WindowMinimizedButtonPolgon)
        self.WindowMinimizedButton.setMask(WindowMinimizedButtonRegion)
        self.WindowMinimizedButton.clicked.connect(self.SetWindowMin)

        self.MusicIconLabel = QPushButton(self)
        self.MusicIconLabel.setGeometry(20, 20, 30, 30)
        self.MusicIconLabel.setStyleSheet("color: blue;")
        if os.path.isfile(".\music\MusicIcon\MusicIcon.jpg"):
            self.MusicIconLabel.setIcon(QIcon(".\music\MusicIcon\MusicIcon.jpg"))
            self.MusicIconLabel.setIconSize(QSize(30, 30))
        else:
            self.MusicIconLabel.setText("无法提取音频图片")
            self.MusicIconLabel.setGeometry(20, 20, 120, 30)

        self.MusicNameLabel = QLabel(self)
        self.MusicNameLabel.setGeometry(20, int((self.height() - 30) / 2), 250, 30)
        self.MusicNameLabel.setStyleSheet("font-size:10px;")
        self.MusicNameLabel.setText(os.path.split(self.file)[-1])

        self.volume = QSlider(Qt.Horizontal, self)
        self.volume.setMinimum(0)
        self.volume.setMaximum(100)
        self.volume.setValue(50)
        self.volume.setTickInterval(5)
        self.volume.setTickPosition(QSlider.TicksBelow)
        self.volume.setGeometry(10, 100, 150, 30)
        self.volume.valueChanged.connect(self.VolumeNumber)

        self.VolumeNumberLabel = QLabel(f"{self.volume.value()}", self)
        self.VolumeNumberLabel.setGeometry(175, 100, 20, 20)

        self.PlayButton = QPushButton(self)
        self.PlayButton.setIcon(QIcon(".\image\stop.png"))
        self.PlayButton.setIconSize(QSize(200, 200))
        self.PlayButton.setGeometry(200, 100, 30, 30)
        self.IS_PlayMusic = False
        self.PlayButton.clicked.connect(self.PlayButtonEvent)

        # 圆角
        rect = QRectF(0, 0, self.width(), self.height())
        path = QPainterPath()
        path.addRoundedRect(rect, 10, 10)
        polygon = path.toFillPolygon().toPolygon()
        region = QRegion(polygon)
        self.setMask(region)

    def SetWindowMin(self):
        self.setWindowState(Qt.WindowMinimized)

    def QuitButtonEvent(self):
        self.hide()
        if os.path.isfile(".\music\MusicIcon\MusicIcon.jpg"):
            os.remove(".\music\MusicIcon\MusicIcon.jpg")
        self.player.stop()

    def PlayButtonEvent(self):
        if self.IS_PlayMusic:
            self.PauseMusic()
        else:
            self.PlayMusic()

    def VolumeNumber(self):
        self.VolumeNumberLabel.setText(f"{self.volume.value()}")
        self.player.setVolume(self.volume.value())

    def GetMusicIcon(self):
        self.MusicMutagnFile = File(self.file)
        try:
            self.MusicIconData = self.MusicMutagnFile.tags['APIC:test'].data
            with open(".\music\MusicIcon\MusicIcon.jpg", "wb") as wfp:
                wfp.write(self.MusicIconData)
        except KeyError:
            pass

    def PlayMusic(self):
        self.player.play()
        self.PlayButton.setIcon(QIcon(".\image\play.png"))
        self.PlayButton.setIconSize(QSize(200, 200))
        self.IS_PlayMusic = True

    def PauseMusic(self):
        self.player.pause()
        self.PlayButton.setIcon(QIcon(".\image\stop.png"))
        self.PlayButton.setIconSize(QSize(200, 200))
        self.IS_PlayMusic = False

    """重写移动事假,更改鼠标图标"""
    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_flag = True
            self.m_Position = event.globalPos() - self.pos()  # 获取鼠标相对窗口的位置
            event.accept()
            self.setCursor(QCursor(Qt.OpenHandCursor))  # 更改鼠标图标

    def mouseMoveEvent(self, QMouseEvent):
        if Qt.LeftButton and self.m_flag:
            self.move(QMouseEvent.globalPos() - self.m_Position)  # 更改窗口位置
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        self.m_flag = False
        self.setCursor(QCursor(Qt.ArrowCursor))

        WeatherGui.py

from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QCursor
from PyQt5.QtGui import QRegion
from PyQt5.QtGui import QPainterPath
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QSize
from PyQt5.QtCore import QRectF
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QPushButton

import requests

"""天气查询界面"""
class WeatherGUI(QWidget):
    def __init__(self):
        super(WeatherGUI, self).__init__()
        self.setWindowTitle("DesktopWife-WeatherGui")
        self.resize(470, 270)
        # 圆角
        rect = QRectF(0, 0, self.width(), self.height())
        path = QPainterPath()
        path.addRoundedRect(rect, 10, 10)
        polygon = path.toFillPolygon().toPolygon()
        region = QRegion(polygon)
        self.setMask(region)

        self.QuitButton = QPushButton(self)
        self.QuitButton.setIcon(QIcon(".\image\Quit.png"))
        self.QuitButton.setIconSize(QSize(40, 40))
        self.QuitButton.setGeometry(400, 10, 40, 40)
        QuitButtonRect = QRectF(0, 0, self.QuitButton.width(), self.QuitButton.height())
        QuitButtonPath = QPainterPath()
        QuitButtonPath.addRoundedRect(QuitButtonRect, 50, 50)
        QuitButtonPolygon = QuitButtonPath.toFillPolygon().toPolygon()
        QuitButtonRegin  = QRegion(QuitButtonPolygon)
        self.QuitButton.setMask(QuitButtonRegin)
        self.QuitButton.clicked.connect(self.hide)

        self.WeatherText = QLabel(self)
        self.WeatherText.setGeometry(int((470 - 300) / 2), int((270 - 200) / 2), 300, 200)
        self.GetWeather()

    def GetWeather(self):
        GET = requests.get("# 因为csdn的智障检测,这里无法查看")
        if GET.status_code == 200:
            JSON = GET.json()
            INFO = JSON['info']
            Data = f"城市:{JSON['city']}\n时间:{INFO['date']}" \
                   + f"\n星期:{INFO['week']}\n天气:{INFO['type']}" \
                   + f"\n{INFO['high']}\n{INFO['low']}\n风向:{INFO['fengxiang']}" \
                   + f"\n风级:{INFO['fengli']}\n主人您要:{INFO['tip']}"
            self.WeatherText.setText(Data)
        else:
            return False

    """重写移动事假,更改鼠标图标"""

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_flag = True
            self.m_Position = event.globalPos() - self.pos()  # 获取鼠标相对窗口的位置
            event.accept()
            self.setCursor(QCursor(Qt.OpenHandCursor))  # 更改鼠标图标

    def mouseMoveEvent(self, QMouseEvent):
        if Qt.LeftButton and self.m_flag:
            self.move(QMouseEvent.globalPos() - self.m_Position)  # 更改窗口位置
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        self.m_flag = False
        self.setCursor(QCursor(Qt.ArrowCursor))

语音

import os
import wave
import pyaudio
import speech_recognition
import speech_recognition as sr
from threading import Thread
import requests

CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 16000

_conent = True

def record_and_recog(wave_out_path, TIME=3):
    p = pyaudio.PyAudio()
    stream = p.open(format=FORMAT,
                    channels=CHANNELS,
                    rate=RATE,
                    input=True,
                    frames_per_buffer=CHUNK)

    wf = wave.open(wave_out_path, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    for _ in range(0, int(RATE / CHUNK * TIME)):
        data = stream.read(CHUNK)
        wf.writeframes(data)
    stream.stop_stream()
    stream.close()
    p.terminate()
    wf.close()
    return wave_out_path

def TTS(Test: str):
    GET = requests.get(f"https://tts.youdao.com/fanyivoice?word={Test}&le=zh&keyfrom=speaker-target")
    if GET.status_code == 200:
        with open(".\\out.mp3", "wb") as wfp:
            wfp.write(GET.content)
            wfp.close()
        FFplay = os.popen(f"cd {os.path.split(__file__)[0]} && ffplay out.mp3 -noborder -nodisp -autoexit")
        FFplay.readlines()
        return True
    else:
        return False

def Scanning(Path="C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\"):
    _DIRList = []
    _File = []
    for paths, dirs, files in os.walk(Path):
        if dirs:
            for dir in dirs:
                _DIRList.append(paths+"\\"+dir)
        if files:
            for file in files:
                _File.append(paths+"\\"+file)
    return _File

def GoogleTranslate():
    global _conent
    while _conent:
        Rec = sr.Recognizer()
        with sr.AudioFile(record_and_recog(".\\test.wav")) as source:
            audio = Rec.record(source)

        try:
            GoogleTranslateText = Rec.recognize_google(audio, language="zh-CN")
        except speech_recognition.UnknownValueError:
            continue
        print(GoogleTranslateText)
        if "小雨" in GoogleTranslateText or "小宇" in GoogleTranslateText:
            TTS("主人我在听,请您下达命令")
            NewRec = sr.Recognizer()
            with sr.AudioFile(record_and_recog(".\\test.wav")) as Newsource:
                NewAudio = NewRec.record(Newsource)
            try:
                Text = Rec.recognize_google(NewAudio, language="zh-CN")
            except speech_recognition.UnknownValueError:
                continue
            print(Text)
            # 因为csdn智障检测,这里无法查看
            elif "打开命令行" in Text:
                TTS("好的, 主人")
                os.popen(f"start cmd")
                TTS("已为您打开命令行")
            elif "关闭语音功能" in Text or "关闭语音" in Text:
                TTS("好的,主人 下次再见")
                break
            elif "打开" in Text:
                TTS("好的, 主人")
                ISSTART = False
                for _Path in Scanning():
                    if Text.strip("打开") == os.path.split(_Path)[-1].split(".")[0]:
                        os.popen(f'"{_Path}"')
                        print(_Path)
                        TTS(f"已为您打开 {Text.strip('打开')}")
                        ISSTART = True
                        break
                if ISSTART:
                    continue
                else:
                    TTS(f"主人未找到 {Text.strip('打开')}")
            elif "关机" in Text:
                TTS("主人是否确定要关机呢?")
                shotdownRrc = sr.Recognizer()
                with sr.AudioFile(record_and_recog(".\\out.mp3")) as shotdowndata:
                    shotdownAudio = shotdownRrc.record(shotdowndata)
                try:
                    ISSHOTDOWN = Rec.recognize_google(shotdownAudio, language="zh-CN")
                except speech_recognition.UnknownValueError:
                    continue
                if ISSHOTDOWN in ["是", "是的", "没错", "要"]:
                    TTS("好的, 主人好好学习呀!")
                    os.popen("shutdown -s -t 1")
                elif ISSHOTDOWN in ["否", "不", "不要", "不关机"]:
                    TTS("好的, 不进行关机")
                else:
                    TTS("主人,我没听懂")
            else:
# 因为csdn的智障检测,这里无法查看
                if GET.status_code == 200:
                    try:
                        TTS(str(GET.json()['data']['info']['text']).replace("小思", "小雨"))
                    except TypeError:
                        continue

def run():
    Start = Thread(target=GoogleTranslate)
    Start.start()
    # Start.join()

使用 Python 实现一个可以语音交流的桌面宠物

你可能感兴趣的:(python,python,pyqt5,语音识别,tts,人工智能)