如何用python做一个小工具:文字转语音

思路:文字换语言的功能实现需要使用第三方的工具,在百度AI开放平台查找到语音技术的相关文档。


这是官方指导的示例代码:

# coding=utf-8

import sys
import json

# 保证兼容python2以及python3
IS_PY3 = sys.version_info.major == 3
if IS_PY3:
    from urllib.request import urlopen
    from urllib.request import Request
    from urllib.error import URLError
    from urllib.parse import urlencode
    from urllib.parse import quote_plus
else:
    import urllib2
    from urllib import quote_plus
    from urllib2 import urlopen
    from urllib2 import Request
    from urllib2 import URLError
    from urllib import urlencode

# 替换你的 API_KEY
API_KEY = 'nu9r2plGFi3s1ugayDPSM6Mk'

# 替换你的 SECRET_KEY
SECRET_KEY = 'G62YGnq84eKTqu0mBgvdpmC6gNBzHdai'

# 大姚的订单信息内容文本
TEXT = "三分钟前,由北京市顺义区二经路与二纬路交汇处北侧,北京首都国际机场T3航站楼 去往 东城区北三环东路36号喜来登大酒店(北京金隅店)"

TTS_URL = 'http://tsn.baidu.com/text2audio'

"""  TOKEN start """

TOKEN_URL = 'http://openapi.baidu.com/oauth/2.0/token'

"""
    获取token
"""
def fetch_token():
    params = {'grant_type': 'client_credentials',
              'client_id': API_KEY,
              'client_secret': SECRET_KEY}
    post_data = urlencode(params)
    if (IS_PY3):
        post_data = post_data.encode('utf-8')
    req = Request(TOKEN_URL, post_data)
    try:
        f = urlopen(req, timeout=5)
        result_str = f.read()
    except URLError as err:
        print('token http response http code : ' + str(err.code))
        result_str = err.read()
    if (IS_PY3):
        result_str = result_str.decode()

    result = json.loads(result_str)

    if ('access_token' in result.keys() and 'scope' in result.keys()):
        if not 'audio_tts_post' in result['scope'].split(' '):
            print ('please ensure has check the tts ability')
            exit()
        return result['access_token']
    else:
        print ('please overwrite the correct API_KEY and SECRET_KEY')
        exit()

"""  TOKEN end """

if __name__ == '__main__':

    token = fetch_token()

    tex = quote_plus(TEXT)  # 此处TEXT需要两次urlencode

    params = {'tok': token, 'tex': tex, 'cuid': "quickstart",
              'lan': 'zh', 'ctp': 1}  # lan ctp 固定参数

    data = urlencode(params)

    req = Request(TTS_URL, data.encode('utf-8'))
    has_error = False
    try:
        f = urlopen(req)
        result_str = f.read()

        headers = dict((name.lower(), value) for name, value in f.headers.items())

        has_error = ('content-type' not in headers.keys() or headers['content-type'].find('audio/') < 0)
    except  URLError as err:
        print('http response http code : ' + str(err.code))
        result_str = err.read()
        has_error = True

    save_file = "error.txt" if has_error else u'大姚的订单信息.mp3'

    with open(save_file, 'wb') as of:
        of.write(result_str)

    if has_error:
        if (IS_PY3):
            result_str = str(result_str, 'utf-8')
        print("tts api  error:" + result_str)

    print("file saved as : " + save_file)

代码运行效果如下:

英文mp3转文字python_封装


直接运行保存了文件,没有输入的功能,也没有选择保存的功能。在此基础上,将它进行一个修改:

# 大姚的订单信息内容文本
TEXT = "三分钟前,由北京市顺义区二经路与二纬路交汇处北侧,北京首都国际机场T3航站楼 去往 东城区北三环东路36号喜来登大酒店(北京金隅店)"

修改后:

TEXT = input('请输入转换的文本:')

这样就实现了文本输入的功能:

英文mp3转文字python_python_02

再修改一下保存的选择:

save_file = "error.txt" if has_error else u'大姚的订单信息.mp3'

修改一下:

name = input('保存为mp3:')
save_name = name + '.mp3'
save_file = "error.txt" if has_error else save_name

运行一下 :

英文mp3转文字python_API_03

试听一下:

python/hello.mp3

内容输入和保存名字的功能已经实现,还需要加一个保存的路径,默认保存的路径是py文件的文件夹里面。我们可以输入一个:文件夹路径,以桌面为例。

# 添加一个路径
path = 'C:\Users\airmo\Desktop'

# 在打开将路径加入到打开文件里面
with open(path+'\\'+save_file,'wb') as of:
    of.write(result_str)

运行效果如下:

英文mp3转文字python_python_04

在桌面也能找到这个文件:

英文mp3转文字python_英文mp3转文字python_05

然而,我们想把这个工具给别人(不会python)用的时候,需要打包成 .exe 文件,在这之前还需要做一个UI界面,便于操作。

Python GUI之tkinter窗口视窗教程大集合(看这篇就够了)

这是用Tkinter做界面的详细介绍。

首先需要一个界面,要有两个输入框,和一个确认按钮:

import tkinter as tk # 导入Tkinter模块

window = tk.Tk() # 创建一个窗口
window.title('文字转语音v1.0') # 窗口的标题
window.geometry('400x150') # 窗口的初始大小

e1 = tk.Entry(window,show = None,font=('微软雅黑', 16)) # 创建一个文本框,收集输入的内容
e1.pack() # 封装在window上
e2 = tk.Entry(window,show = None,font=('微软雅黑', 16)) # 文件名
e2.pack() # 封装在window上
b1 = tk.Button(window,text='确定',font=('微软雅黑', 16),command=main) # 创建一个按钮,执行main函数
b1.pack()

window.mainloop() # 窗口刷新

效果就是这样:

英文mp3转文字python_封装_06

然后将e1的值赋予给TEXT,e2的值赋予给name:

TEXT = str(e1.get())
name = str(e2.get())

英文mp3转文字python_python_07

英文mp3转文字python_python_08

我们在桌面也能找到转换好的文件:

英文mp3转文字python_python_09

试听一下:

python/hello1.mp3

这样还是不完美,我们想实现选择文件保存的路径,可以用filedialog.askdirectory():

from tkinter import filedialog
path = filedialog.askdirectory()

点击运行:

英文mp3转文字python_API_10

点击”确定“:

英文mp3转文字python_封装_11


英文mp3转文字python_英文mp3转文字python_12

然后去选择保存的文件夹查看:

英文mp3转文字python_API_13

我们想快捷到达保存的文件夹,需要用到os模块,前面的路径已经在赋予了path:

import os

save_path = path
os.startfile(save_path)

运行后就直接打开保存的文件夹了。

我们想在转换结束后增加一个tip,提示转换完成,就需要用到tk的messagebox:

from tkinter import messagebox
tip = messagebox.askyesno(title='提示',message='转换完成!是否查看文件')
if tip:
    save_path = path
    os.startfile(save_path)

运行一下 :

英文mp3转文字python_python_14


英文mp3转文字python_封装_15

附上完整代码:

# coding=utf-8

import sys
import os
import json
from tkinter import filedialog,messagebox

# 保证兼容python2以及python3
IS_PY3 = sys.version_info.major == 3
if IS_PY3:
    from urllib.request import urlopen
    from urllib.request import Request
    from urllib.error import URLError
    from urllib.parse import urlencode
    from urllib.parse import quote_plus
else:
    import urllib2
    from urllib import quote_plus
    from urllib2 import urlopen
    from urllib2 import Request
    from urllib2 import URLError
    from urllib import urlencode

import tkinter as tk # 导入Tkinter模块

window = tk.Tk() # 创建一个窗口
window.title('文字转语音v1.0') # 窗口的标题
window.geometry('400x150') # 窗口的初始大小

e1 = tk.Entry(window,show = None,font=('微软雅黑', 16)) # 创建一个文本框,收集输入的内容
e1.pack() # 封装在window上
e2 = tk.Entry(window,show = None,font=('微软雅黑', 16)) # 文件名
e2.pack() # 封装在window上

# 替换你的 API_KEY
API_KEY = 'nu9r2plGFi3s1ugayDPSM6Mk'

# 替换你的 SECRET_KEY
SECRET_KEY = 'G62YGnq84eKTqu0mBgvdpmC6gNBzHdai'

TTS_URL = 'http://tsn.baidu.com/text2audio'

"""  TOKEN start """

TOKEN_URL = 'http://openapi.baidu.com/oauth/2.0/token'

"""
    获取token
"""
def fetch_token():
    params = {'grant_type': 'client_credentials',
              'client_id': API_KEY,
              'client_secret': SECRET_KEY}
    post_data = urlencode(params)
    if (IS_PY3):
        post_data = post_data.encode('utf-8')
    req = Request(TOKEN_URL, post_data)
    try:
        f = urlopen(req, timeout=5)
        result_str = f.read()
    except URLError as err:
        print('token http response http code : ' + str(err.code))
        result_str = err.read()
    if (IS_PY3):
        result_str = result_str.decode()

    result = json.loads(result_str)

    if ('access_token' in result.keys() and 'scope' in result.keys()):
        if not 'audio_tts_post' in result['scope'].split(' '):
            print ('please ensure has check the tts ability')
            exit()
        return result['access_token']
    else:
        print ('please overwrite the correct API_KEY and SECRET_KEY')
        exit()

"""  TOKEN end """

def main():

    TEXT = str(e1.get())

    token = fetch_token()

    tex = quote_plus(TEXT)  # 此处TEXT需要两次urlencode

    params = {'tok': token, 'tex': tex, 'cuid': "quickstart",
              'lan': 'zh', 'ctp': 1}  # lan ctp 固定参数

    data = urlencode(params)

    req = Request(TTS_URL, data.encode('utf-8'))
    has_error = False
    try:
        f = urlopen(req)
        result_str = f.read()

        headers = dict((name.lower(), value) for name, value in f.headers.items())

        has_error = ('content-type' not in headers.keys() or headers['content-type'].find('audio/') < 0)
    except  URLError as err:
        print('http response http code : ' + str(err.code))
        result_str = err.read()
        has_error = True

    name = str(e2.get())
    save_name = name + '.mp3'
    save_file = "error.txt" if has_error else save_name

    # 添加一个路径
    path = filedialog.askdirectory()

    # 在打开将路径加入到打开文件里面
    with open(path+'\\'+save_file,'wb') as of:
        of.write(result_str)

    if has_error:
        if (IS_PY3):
            result_str = str(result_str, 'utf-8')
        print("tts api  error:" + result_str)

    tip = messagebox.askyesno(title='提示',message='转换完成!是否查看文件')
    if tip:
        save_path = path
        os.startfile(save_path)

b1 = tk.Button(window,text='确定',font=('微软雅黑', 16),command = main) # 创建一个按钮,执行main函数
b1.pack()

window.mainloop() # 窗口刷新

代码和UI都做好了,然后就是封装成**.exe**文件了

python文件封装成*.exe文件(单文件和多文件)