7

python应用(2):写个python程序给自己用

 3 years ago
source link: https://segmentfault.com/a/1190000038293405
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

用python写一个程序,然后在命令行上执行,看不到界面(UI),这种程序很常见了,叫命令行程序。然而很多人,特别是不懂程序的人,更需要看到的是一个有界面的,能通过鼠标操作的程序,毕竟已经迈进“窗口”的时代,虽然Dos还存在。所以,怎么用python弄出有界面的程序呢?

界面也是一个工具,所以,有没有界面工具库呢?必须得有,而且有很多个,你搜索“python界面库”就可以看到很多这方面的介绍,而我要介绍的,是python最早就有的 tkinter ,通过它来实现界面程序。

tkinter内置在python中,所以不用再安装,直接import进来使用就是了。沿用上一节介绍的文本转语音的程序,我现在要写一个界面程序,上面有两个按钮,一个用来选择文本文件,一个是“转换成语音”,来看看怎么实现吧。

(1)TTS的GUI程序

from tkinter import *
import tkinter.messagebox as msgbox
import tkinter.filedialog as filedlg
import os
import pyttsx3
from pydub import AudioSegment
import threading

txtfile = ""
window = Tk()
pathlabel = Label(window, text="...")

def fileFunc():
    default_dir = "文件路径"
    global txtfile
    global pathlabel
    txtfile = filedlg.askopenfilename(title="选择文件", initialdir=(os.path.expanduser(default_dir)))
    (path, fname) = os.path.split(txtfile)
    pathlabel["text"] = fname

def converThreadFunc(content):
    outfile = "out.aiff"
    tts = pyttsx3.init()
    tts.save_to_file(content, outfile)
    tts.runAndWait()

def convertFunc():
    if len(txtfile) == 0:
        msgbox.showinfo("提示", "请先选择文本文件")
        return
    content = open(txtfile, "r", encoding="utf-8").read()
    if len(content)==0:
        msgbox.showinfo("提示", "文本文件没有内容,转换终止,不输出语音文件")
        return
    t1 = threading.Thread(target=converThreadFunc, args=(content,))
    t1.start()
    t1.join()
    outfile = "out.aiff"
    AudioSegment.from_file(outfile).export("out.mp3", format="mp3")
    msgbox.showinfo("提示", "转换成功,程序目录下的out.mp3就是最终的语音文件:%s" % os.getcwd())
    os.system("open '%s'" % os.getcwd())
    
def main():
    window.title("TTS-文本转换语音")
    window.geometry("320x320+100+100")
    filebtn = Button(window, text="选择文本文件", command=fileFunc)
    convertbtn = Button(window, text="转换成语音", command=convertFunc)
    filebtn.place(x=10, y=10)
    pathlabel.place(x=10, y=40)
    convertbtn.place(x=10, y=80)
    window.mainloop()

if __name__=="__main__":
    main()

抓重点来看。

1、使用了tkinter的控件,messagebox是提示框,filedialog是文件选择控件,再比如Button跟Label,这些都是常用的控件,它们的创建跟属性设置,也有不少详情,你可以搜索来了解。

2、这里用place方法来设置控件的位置,类似的方法还有pack、grid等。

3、业务逻辑上,重点是处理两个按钮的点击事件,也就是那两个def出来的xxFunc函数了。

4、文本转语音的处理,使用了上节介绍的代码,也没有什么神秘的。

5、pyttsx3.engine的函数runAndWait在执行完后会结束当前线程,所以,不能在主线程即UI线程来执行这个函数,而要启动一个thread来执行它,否则runAndWait执行后主界面就会消失,这不是预期的事情。

运行起来后的一个截图是这样的:

1460000038293410

程序弄好了,先不管它丑不丑吧,至少功能可以用了。如果是自己使用的话,那怎么样才能快速地启用这个程序呢?

(2)结合alfred来调用程序

之前介绍过怎么在mac系统上快速地切换或启动一个程序,使用的工具就是alfred,这是一个超级好用的工具。那现在再次使用alfred来启用刚才写的程序。

关于alfred的安装或使用,网上很多介绍,我之前介绍“mac环境与工具”时也有介绍,但是,这里有一个地方要注意: 手动用终端执行上面的python程序是可以正常运作的,但一旦通过alfred执行python程序,那在AudioSegment.form_file时就会异常,最终export不出语音文件,就算直接在python代码中执行ffmpeg命令也一样会失败,判断是,alfred执行python脚本的情况下,AudioSegment(包括它使用的ffmpeg)没有权限访问文件。 考虑到这种情况,就要变通一下了:让alfred打开一个新的终端,并且让这个终端执行python程序--按这个思路来制作工具。

1、在alfred上新建一个“Script Filter”:

1460000038293409

2、新的terminal会执行cmd.sh脚本,这个脚本是这样的:

cd '/Users/freejet/Library/Application Support/Alfred 3/Alfred.alfredpreferences/workflows/user.workflow.4D91A493-39F3-433C-9D33-65917236A6F5'
source ~/Desktop/pyenv/bin/activate
python3 demo_gui.py

先是cd到这个alfred脚本即workflow所在的目录,这个目录路径你可以通过右键workflow找到,然后激活python3的环境(第一节介绍到的内容),最后执行python程序也就是上面介绍的“TTS的GUI程序”。

把这个cmd.sh放到当前workflow的目录中,这样alfred才能找到它。

3、执行一下,效果是这样的:

1460000038293408

最后的那个out.mp3就是最终想要的文件,你可以听一下(如果你是在公众号内看到这篇文章的话):

(out.mp3试听)

对应的文本是这样的:

瑶草一何碧,春入武陵溪。溪上桃花无数,花上有黄鹂,我欲穿花寻路,直入白云深处,浩气展虹霓。只恐花深里,红露湿人衣。坐玉石,欹玉枕,拂金徽。谪仙何处,天人伴我白螺杯。我为灵芝仙草,不为朱唇丹脸,长啸亦何为!醉舞下山去,明月逐人归。——宋.黄庭坚《水调歌头.游览》

你已经开始吐槽了吧:这语音效果怎么这么差!

传统的TTS就这样子了,有得听就不错了,如果想要“有感情”的效果那一般要使用成熟的语音合成接口,或者自己训练一个出来。但不管语音效果怎么样,本文的目的已经达到了: 怎么用python写一个程序,然后给自己快速地调用到。so,see you。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK