阿里云语音合成(汉语英语)带UI界面的小程序(python)
一,项目说明
将汉文转汉语、英文转英语,同时又有逗号<###English###>,<,,,>和句号<...>标志符用于文件处理。其中英文包含在### 英文 ###中。
程序A:三个逗号<,,,>和三个句号<...>前面的句段独立成块小分段,同时三个句号<...>前面的句段划分成为另一种较大的分段。其中程序中有控制<,,,>和<...>重复次数的数值
程序A输入样例1:
###bring###拿来,带来,,,
###Bronze###青铜色的...
###brush###刷;檫,,,
###build###建筑;造,,,
###building###建筑物;房屋;大楼...
程序A输出样例1:(下文为音频发音的内容)
bring拿来,带来bring拿来,带来
Bronze青铜色的Bronze青铜色的 bring拿来,带来Bronze青铜色的 brush刷;檫brush刷;檫
build建筑;造build建筑;造
building建筑物;房屋;大楼building建筑物;房屋;大楼 brush刷;檫build建筑;造building建筑物;房屋;大楼 bring拿来,带来Bronze青铜色的brush刷;檫build建筑;造building建筑物;房屋;大楼
程序B输入样例1:
###bring###拿来,带来,,,
###Bronze###青铜色的...
###brush###刷;檫,,,
###build###建筑;造,,,
###building###建筑物;房屋;大楼...
程序B输出样例1:(下文为音频发音的内容)
bring拿来,带来bring拿来,带来bring拿来,带来 Bronze青铜色的 brush刷;檫brush刷;檫brush刷;檫
build建筑;造build建筑;造造build建筑;造 building建筑物;房屋;大楼 bring拿来,带来Bronze青铜色的brush刷;檫build建筑;造building建筑物;房屋;大楼
备注:上文中的程序A、程序B都是使用的默认配置
二,界面解析
图1 主界面
图2 文本导入界面(支持txt和docx文件格式)
图3 参数设置界面
图4 近期调用统计图(更新2019-06-16,尾款到手不再更新)
三,源码开放
界面显示(主函数) ui2show.pyw
import tkinter as tk
import netWork
import split2summary
import tkinter.filedialog
import os
import shutil
import docx
from configobj import ConfigObj
from tkinter import ttk
from tkinter import messagebox
import struct class ui2show(tk.Tk):
def __init__(self):
super().__init__() rootPath = os.path.split(os.path.realpath(__file__))[0]
os.chdir(rootPath)
self.dictSpace = {0: 'chinese', 1: 'english'} # *** 系统初始化检测网络 *** #
self.netWork = netWork.netWork()
self.netState, self.textShow = self.netWork.isConnected() # *** 提前加载功能库 *** #
self.split2summary = split2summary.split2summary()
self.config = ConfigObj("config.ini", encoding='UTF8')
#print(self.config) self.vartext = tk.StringVar()
self.vartext.set(self.textShow)
self.geometry('597x100')
self.resizable(0, 0)
self.title('文字处理&音频合成')
self.fileFeedback = [] self.homePage() def homePage(self): # 默认主页
self.top1 = tk.Frame()
self.top1.pack(fill="x") tk.Button(self.top1, text='文本导入', width=27, command=self.file4manage).grid(row=0, column=0)
tk.Button(self.top1, text='参数设置', width=27, command=self.config4set).grid(row=0, column=1)
tk.Button(self.top1, text='音频合成', width=27, command=self.txt2run).grid(row=0, column=2)
tk.Label(self.top1, height=3, textvariable=self.vartext, bg='white', font=('黑体', 10), anchor='w').grid(row=1,
column=0,
columnspan=3) def file4manage(self): # 文件初始化 成功√
path = tkinter.filedialog.askopenfilename(initialdir='C:\\Users\\Administrator\\Desktop', filetypes=(
("txt or docx files", "*.txt;*.docx"), ("All files", "*.*")))
if path == "":
self.fileState, self.textShow, self.fileFeedback = False, '未导入任何文件', []
else: # 已导入文件
p, f = os.path.split(path)
path_directory = os.path.dirname(os.path.realpath(__file__)) + '\\data\\' + str(os.path.splitext(f)[0])
isExists = os.path.exists(path_directory)
if not isExists: # 如果不存在这个目录
os.makedirs(path_directory) # 创建一个新的路径
shutil.copyfile(path, path_directory + '\\' + f) if str(os.path.splitext(f)[1]) == '.txt':
file_object = open(path, 'r')
file_context = file_object.read()
file_object.close() elif str(os.path.splitext(f)[1]) == '.docx':
document = docx.Document(path)
file_context = ''
for paragraph in document.paragraphs:
file_context += paragraph.text
self.fileState, self.textShow, self.fileFeedback = True, '已导入文本数据', [path_directory, file_context]
self.vartext.set(self.textShow) def config4set(self): # 参数配置界面
self.top2 = tk.Toplevel()
self.top2.title('参数配置') self.txtShow = [] # 直接全部设置成int型文件
for i in range(16):
if i == 11 or 15:
self.txtShow.append(tk.StringVar())
else:
self.txtShow.append(tk.IntVar()) txtShow = []
#print(self.config['txtA'])
txtA = self.config['txtA']
for i in enumerate(txtA['name']):
txtShow.append(int(txtA[i[1]]))
txtB = self.config['txtB']
for i in enumerate(txtB['name']):
txtShow.append(int(txtB[i[1]]))
txtC = self.config['chinese']
for i in enumerate(txtC['name']):
txtShow.append(int(txtC[i[1]]))
txtD = self.config['english']
for i in enumerate(txtD['name']):
txtShow.append(int(txtD[i[1]])) # print(txtShow)
for keyi, valuei in enumerate(txtShow):
self.txtShow[keyi].set(valuei) tk.Label(self.top2, text='程序A', width=30).grid(row=0, column=0, columnspan=2)
tk.Label(self.top2, text='逗号次数', width=10).grid(row=1, column=0, columnspan=1)
tk.Label(self.top2, text='句号次数', width=10).grid(row=2, column=0, columnspan=1)
tk.Label(self.top2, text='全部文本次数', width=10).grid(row=3, column=0, columnspan=1)
tk.Label(self.top2, text='是否生成音频', width=10).grid(row=4, column=0, columnspan=1)
tk.Entry(self.top2, textvariable=self.txtShow[0], width=10).grid(row=1, column=1)
tk.Entry(self.top2, textvariable=self.txtShow[1], width=10).grid(row=2, column=1)
tk.Entry(self.top2, textvariable=self.txtShow[2], width=10).grid(row=3, column=1)
checkA = tk.Checkbutton(self.top2, text="是", variable=self.txtShow[3], width=10)
checkA.select()
checkA.grid(column=1, row=4, sticky=tk.W) tk.Label(self.top2, text='程序B', width=30).grid(row=0, column=2, columnspan=2)
tk.Label(self.top2, text='逗号次数', width=10).grid(row=1, column=2, columnspan=1)
tk.Label(self.top2, text='句号次数', width=10).grid(row=2, column=2, columnspan=1)
tk.Label(self.top2, text='全部文本次数', width=10).grid(row=3, column=2, columnspan=1)
tk.Label(self.top2, text='是否生成音频', width=10).grid(row=4, column=2, columnspan=1)
tk.Entry(self.top2, textvariable=self.txtShow[4], width=10).grid(row=1, column=3)
tk.Entry(self.top2, textvariable=self.txtShow[5], width=10).grid(row=2, column=3)
tk.Entry(self.top2, textvariable=self.txtShow[6], width=10).grid(row=3, column=3)
checkB = tk.Checkbutton(self.top2, text="是", variable=self.txtShow[7], width=10)
checkB.select()
checkB.grid(column=3, row=4, sticky=tk.W) tk.Label(self.top2, text='汉语', width=10).grid(row=0, column=4, columnspan=2)
tk.Label(self.top2, text='音量', width=10).grid(row=1, column=4, columnspan=1)
tk.Label(self.top2, text='语速', width=10).grid(row=2, column=4, columnspan=1)
tk.Label(self.top2, text='语调', width=10).grid(row=3, column=4, columnspan=1)
tk.Label(self.top2, text='发言人', width=10).grid(row=4, column=4, columnspan=1)
tk.Entry(self.top2, textvariable=self.txtShow[8], width=13).grid(row=1, column=5)
tk.Entry(self.top2, textvariable=self.txtShow[9], width=13).grid(row=2, column=5)
tk.Entry(self.top2, textvariable=self.txtShow[10], width=13).grid(row=3, column=5)
chosenC = ttk.Combobox(self.top2, textvariable=self.txtShow[11], width=10)
chosenC['values'] = (
'Xiaoyun', 'Xiaogang', 'Ruoxi', 'Xiaomeng', 'Xiaowei', 'Amei', 'Xiaoxue', 'Siqi', 'Sijia', 'Sicheng',
'Siyue',
'Xiaomei', 'Sitong', 'Ninger', 'Xiaobei', 'Yina', 'Sijing', 'Shanshan')
chosenC.current(txtShow[11])
chosenC.grid(row=4, column=5) tk.Label(self.top2, text='英语', width=10).grid(row=0, column=6, columnspan=2)
tk.Label(self.top2, text='音量', width=10).grid(row=1, column=6, columnspan=1)
tk.Label(self.top2, text='语速', width=10).grid(row=2, column=6, columnspan=1)
tk.Label(self.top2, text='语调', width=10).grid(row=3, column=6, columnspan=1)
tk.Label(self.top2, text='发言人', width=10).grid(row=4, column=6, columnspan=1)
tk.Entry(self.top2, textvariable=self.txtShow[12], width=13).grid(row=1, column=7)
tk.Entry(self.top2, textvariable=self.txtShow[13], width=13).grid(row=2, column=7)
tk.Entry(self.top2, textvariable=self.txtShow[14], width=13).grid(row=3, column=7)
chosenD = ttk.Combobox(self.top2, textvariable=self.txtShow[15], width=10)
chosenD['values'] = ('Wendy', 'William', 'Halen', 'Harry')
chosenD.current(txtShow[15])
chosenD.grid(row=4, column=7) tk.Button(self.top2, text='确定', command=self.config2ok, width=27).grid(row=5, column=0, columnspan=2)
tk.Button(self.top2, text='重置', command=self.config2reset, width=27).grid(row=5, column=2, columnspan=2)
tk.Button(self.top2, text='帮助', command=self.config2help, width=27).grid(row=5, column=4, columnspan=2) # for keyi,valuei in enumerate(txtShow):
self.txtShow[3].set(txtShow[3])
self.txtShow[7].set(txtShow[7]) def config2ok(self): # 参数设置-成功√
txtShow = []
for i in self.txtShow:
txtShow.append(i.get()) txtShow[11] = self.config['chinese']['voice_parameter'].index(txtShow[11])
txtShow[15] = self.config['english']['voice_parameter'].index(txtShow[15])
# print('txtShow:',txtShow[3],txtShow[7]) for i in enumerate(txtShow[:4]):
self.config['txtA'][self.config['txtA']['name'][i[0]]] = i[1]
for i in enumerate(txtShow[4:8]):
self.config['txtB'][self.config['txtB']['name'][i[0]]] = i[1]
for i in enumerate(txtShow[8:12]):
self.config['chinese'][self.config['chinese']['name'][i[0]]] = i[1]
for i in enumerate(txtShow[12:16]):
self.config['english'][self.config['english']['name'][i[0]]] = i[1]
self.config.write() def config2reset(self): # 恢复出厂设置 成功√
for i in ['txtA', 'txtB', 'chinese', 'english']:
for j in self.config[i]['name']:
self.config[i][j] = self.config[i]['default_' + j][1]
self.config.write() txtShow = [] # 获取最新的参数配置并更新界面数据
txtA = self.config['txtA']
for i in enumerate(txtA['name']):
txtShow.append(int(txtA[i[1]]))
txtB = self.config['txtB']
for i in enumerate(txtB['name']):
txtShow.append(int(txtB[i[1]]))
txtC = self.config['chinese']
for i in enumerate(txtC['name']):
txtShow.append(int(txtC[i[1]]))
txtD = self.config['english']
for i in enumerate(txtD['name']):
txtShow.append(int(txtD[i[1]])) for keyi, valuei in enumerate(txtShow):
self.txtShow[keyi].set(valuei)
self.txtShow[11].set(self.config['chinese']['voice_parameter'][txtShow[11]])
self.txtShow[15].set(self.config['english']['voice_parameter'][txtShow[15]]) def config2help(self):
tk.messagebox.showinfo("参数设置帮助", "语音合成参数设置范围:\n1,音量范围0~100;\n2,语速范围-500~500;\n3,语调范围-500~500;") def txt2run(self):
if len(self.fileFeedback) == 0:
self.textShow = '没有导入文本文件\n请先进行{文本导入}'
self.vartext.set(self.textShow)
else: # 已正常导入【路径,文本】
# self.dictSpace
dataASet = []
for i in self.config['txtA']['name']:
dataASet.append(int(self.config['txtA'][i]))
dataBSet = []
for i in self.config['txtB']['name']:
dataBSet.append(int(self.config['txtB'][i]))
if dataASet[-1]+dataBSet[-1]==0:
self.textShow='设置中未勾选{是否生成音频}\n请先勾选相关选项再做操作'
self.vartext.set(self.textShow)
return None
txt_value, txt_state = self.split2summary.txt2split(self.fileFeedback[1])
self.textShow = '正在将文字转化为音频...'
self.vartext.set(self.textShow)
for keyi, valuei in enumerate(txt_value):
for keyj, valuej in enumerate(valuei):
for keyk, valuek in enumerate(valuej):
txt_value[keyi][keyj][keyk] = self.netWork.txt2audio(txt_value[keyi][keyj][keyk],
self.dictSpace[
txt_state[keyi][keyj][keyk]]) # *** 合成音频完整性测试 *** # 测试成功√
# audioTest=[]
# for keyi, valuei in enumerate(txt_value): # 句号
# for keyj, valuej in enumerate(valuei):
# for keyk, valuek in enumerate(valuej):
# pathTest = self.fileFeedback[0] + '\\' + self.fileFeedback[0].split('\\')[-1] + str(keyi)+str(keyj)+str(keyk) +'Test.wav'
# with open(pathTest, mode='wb') as f:
# f.write(txt_value[keyi][keyj][keyk]) # *** 音频文件合并成逗号分段 *** #
wav_format = txt_value[0][0][0][:44] # wav音频文件的帧头信息,后续保存文件需要进行二次修改
for keyi, valuei in enumerate(txt_value): # 句号
for keyj, valuej in enumerate(valuei):
# str_comma = []
for keyk, valuek in enumerate(valuej):
if keyk == 0:
str_comma = txt_value[keyi][keyj][keyk]
else:
str_comma += txt_value[keyi][keyj][keyk][44:]
txt_value[keyi][keyj] = str_comma # *** 合成音频英汉合并完整性测试 *** # 测试成功√
# audioTest=[]
# for keyi, valuei in enumerate(txt_value): # 句号
# for keyj, valuej in enumerate(valuei):
# pathTest = self.fileFeedback[0] + '\\' + self.fileFeedback[0].split('\\')[-1] + 'comma'+str(keyi)+str(keyj)+'Test.wav'
# with open(pathTest, mode='wb') as f:
# f.write(txt_value[keyi][keyj]) # *** 程序A *** #
if dataASet[-1]:
self.textShow = '正在生成音频A'
self.vartext.set(self.textShow)
# print('runA',dataASet)
pathA = self.fileFeedback[0] + '\\' + self.fileFeedback[0].split('\\')[-1] + 'A.wav'
audioA = self.split2summary.programA(txt_value, dataASet) audioA_len = len(audioA)
wav_format = wav_format[:4] + struct.pack('<L', audioA_len + 44) + wav_format[8:]
wav_format = wav_format[:40] + struct.pack('<L', audioA_len) + wav_format[44:]
with open(pathA, mode='wb') as f:
f.write(wav_format + audioA)
self.textShow = '已生成音频A'
self.vartext.set(self.textShow) # *** 程序B *** #
if dataBSet[-1]:
self.textShow += '正在成音频B'
self.vartext.set(self.textShow) pathB = self.fileFeedback[0] + '\\' + self.fileFeedback[0].split('\\')[-1] + 'B.wav'
audioB = self.split2summary.programB(txt_value, dataBSet) audioB_len = len(audioB)
wav_format = wav_format[:4] + struct.pack('<L', audioB_len + 44) + wav_format[8:]
wav_format = wav_format[:40] + struct.pack('<L', audioB_len) + wav_format[44:]
with open(pathB, mode='wb') as f:
f.write(wav_format + audioB) if dataASet[-1] and dataBSet[-1]:
self.textShow='已合成音频A、B'
elif dataBSet[-1]:
self.textShow = '已合成音频B'
elif dataASet[-1]:
self.textShow = '已合成音频A' self.vartext.set(self.textShow) if __name__ == '__main__':
# *** 测试ui界面显示 *** #
ui2show = ui2show()
ui2show.mainloop()
网络相关支持函数 netWork.pyw
#-*- coding:utf-8 -*-
from configobj import ConfigObj # config.ini参数操作函数
import urllib.parse
import requests # 网络操作函数
import http.client
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
import json
import datetime # *** 网络连接函数 *** #
class netWork:
# def __init__(self):
# pass def isConnected(self): # 检测网络是否已正常连接
try:
html = requests.get("https://www.baidu.com/", timeout=2)
except:
return False, '无法连接网络,请检查网络是否正常连接'
return True, '网络连接正常' def getToken(self): # 获取token值,后续需要在version3.0解决
config = ConfigObj("config.ini", encoding='UTF8')
client = AcsClient(config['user']['AccessKeyID'], config['user']['AccessKeySecret'], "cn-shanghai")
request = CommonRequest()
request.set_method('POST')
request.set_domain('nls-meta.cn-shanghai.aliyuncs.com')
request.set_version('2019-02-28')
request.set_action_name('CreateToken')
response = client.do_action_with_exception(request)
response = json.loads(str(response, 'utf-8'))
return response['Token']['Id'] def txt2audio(self, text, type): # 小段文本转音频的程序,输入text、
config = ConfigObj("config.ini", encoding='UTF8')
if config['user']['nowTime']!=str(datetime.datetime.now())[:10]: # 按天进行token值更新
config['user']['nowTime'] = str(datetime.datetime.now())[:10]
config['user']['&token'] = self.getToken()
config.write() conn = http.client.HTTPSConnection(config['user']['host'])
du = config['user']
dc = config[type] # 这里分汉文、英文 url = ''
url = 'https://' + du['host'] + '/stream/v1/tts'
url = url + '?appkey=' + du['?appkey']
url = url + '&token=' + du['&token']
url = url + '&format=' + du['&format']
url = url + '&sample_rate=' + du['&sample_rate']
url = url + '&voice=' + dc['voice_parameter'][int(dc['&voice'])]
url = url + '&volume=' + dc['&volume']
url = url + '&speech_rate=' + dc['&speech_rate']
url = url + '&pitch_rate=' + dc['&pitch_rate'] if type == 'chinese':
if len(text) < 300: # 满足文本长度要求
list_text = [text]
else: # 不满足文本长度要求
list_text = text.split('.') # 很少有文本能够一段超过300字
elif type == 'english':
num = len(text.split()) # 英文和汉文不同使用空格区分单词
if num < 300:
list_text = [text]
else:
list_text = text.split('.')
list_audio = []
for i in list_text:
textUrlencode = urllib.parse.quote_plus(i)
textUrlencode = textUrlencode.replace("+", "%20")
textUrlencode = textUrlencode.replace("*", "%2A")
textUrlencode = textUrlencode.replace("%7E", "~")
conn.request(method='GET', url=url + '&text=' + textUrlencode)
response = conn.getresponse()
body = response.read()
list_audio.append(body)
conn.close() audio_all = list_audio[0]
if len(list_text) > 1:
for i in list_audio[1:]:
audio_all += i
return audio_all if __name__ == '__main__':
net = netWork()
# *** 测试网络连接是否正常 *** # 成功√
netState, feedbackWord=net.isConnected()
print(netState, feedbackWord) # *** 测试自动获取token值 *** # 成功√
# Token=net.getToken()
# print(Token) # *** 测试语音合成是否正常 *** # 成功√
# text = '你好,万雨。测试成功'
# type = 'chinese'
# fileName = 'testAudio1.wav'
# audio = net.txt2audio(text, type)
# with open(fileName, mode='wb') as f:
# f.write(audio)
文本处理相关函数 split2summary.pyw
#-*- coding:utf-8 -*-
"""
函数说明:
①将原始文本进行拆分-合并
②将获得音频进行按要求重复合并 """ class split2summary:
def findCE(self, text): # 区分汉文英文
index = []
for i in range(len(text) - 2):
if text[i:i + 3] == '###':
index.append(i)
# elif text[i:i + 3] == '>>>':
# index.append(i)
# print(index)
if len(index) == 0:
return [text], [0]
text_list = []
text_state = []
index_history = [0, 0]
for key, value in enumerate(index):
# print(key,value)
if key % 2 == 0: # 汉文
if index[key] == 0:
continue
index_history = [index_history[1], index[key]]
if key == 0:
text_list.append(text[index_history[0]:index_history[1]])
else:
text_list.append(text[index_history[0] + 3:index_history[1]])
text_state.append(0)
else: # 英文
index_history = [index_history[1], index[key]]
text_list.append(text[index_history[0] + 3:index_history[1]])
text_state.append(1)
# 解决句尾的问题
if index[-1] + 3 != len(text):
text_list.append(text[index[-1] + 3:len(text)])
text_state.append(0)
return text_list, text_state def txt2split(self, text):
txt_mid = text.split('...')
for i in range(len(txt_mid)):
txt_mid[i] = txt_mid[i].split(',,,')
txt_value = []
txt_state = []
for i in txt_mid[:-1]:
txt_state_mid = []
txt_value_mid = []
for j in i:
text_list, text_state = self.findCE(j)
txt_value_mid.append(text_list)
txt_state_mid.append(text_state)
txt_value.append(txt_value_mid)
txt_state.append(txt_state_mid)
return txt_value, txt_state # *** 将最小分段合并一级到逗号分段 *** #
def value2comma(self, value):
for keyi, valuei in enumerate(value): # 句号
for keyj, valuej in enumerate(valuei):
for keyk, valuek in enumerate(valuej):
if keyk == 0:
str_comma = value[keyi][keyj][keyk]
else:
str_comma += value[keyi][keyj][keyk]
value[keyi][keyj] = str_comma
return value # *** 处理分段函数A 成功√ *** #
def programA(self, value, dataASet):
valueA = []
for keyi, valuei in enumerate(value): # 句号
value_end = []
for keyj, valuej in enumerate(valuei):
if keyj == 0 and (dataASet[0] != 0 or dataASet[1] != 0):
value_end = value[keyi][keyj]
if dataASet[0] != 0:
for times in range(dataASet[0] - 1):
value_end += value[keyi][keyj]
elif dataASet[0] != 0:
for times in range(dataASet[0]):
value_end += value[keyi][keyj]
elif dataASet[1] != 0:
value_end += value[keyi][keyj] if keyi == 0 and dataASet[0] != 0:
valueA = value_end
elif dataASet[0] != 0:
valueA += value_end # *** 专门针对句号分段 *** #
# for keyi, valuei in enumerate(value):
for times in range(dataASet[1]):
for keyj, valuej in enumerate(valuei):
if (keyi == 0 and keyj == 0) and (dataASet[0] == 0 and valueA == []):
valueA = value[keyi][keyj]
else:
valueA += value[keyi][keyj] # *** 专门针对整个篇幅的分段 *** #
for times in range(dataASet[2]):
for keyi, valuei in enumerate(value): # 句号
for keyj, valuej in enumerate(valuei):
# print(keyi, keyj)
if (keyi, keyj) == (0, 0) and valueA == []: valueA = value[keyi][keyj]
else:
valueA += value[keyi][keyj] # print(valueA)
return valueA def programB(self, value, dataBSet):
valueB=[]
# *** 逗号分段处理 *** #
for keyi, valuei in enumerate(value): # 句号
value_end = []
for keyj, valuej in enumerate(valuei[:-1]):
if keyj == 0 and (dataBSet[0] != 0 or dataBSet[1] != 0):
value_end = value[keyi][keyj]
if dataBSet[0] != 0:
for times in range(dataBSet[0] - 1):
value_end += value[keyi][keyj]
elif dataBSet[0] != 0:
for times in range(dataBSet[0]):
value_end += value[keyi][keyj]
elif dataBSet[1] != 0:
value_end += value[keyi][keyj] if keyi == 0 and dataBSet[0] != 0:
valueB = value_end
elif dataBSet[0] != 0:
valueB += value_end # *** 专门针对句号分段 *** #
for times in range(dataBSet[1]):
if (keyi == 0) and (valueB == []):
valueB = value[keyi][-1]
else:
valueB += value[keyi][-1] # *** 专门针对整个篇幅的分段 *** #
for times in range(dataBSet[2]):
for keyi, valuei in enumerate(value): # 句号
for keyj, valuej in enumerate(valuei):
if (keyi, keyj) == (0, 0) and valueB == []:
# print('run')
valueB = value[keyi][keyj]
else:
valueB += value[keyi][keyj] # print(valueB)
return valueB if __name__=="__main__":
split2summary = split2summary()
text = '1你好<<<2don\'t do that>>>,,,<<<3I have a dream>>>4万雨...5什么<<<6hello>>>,,,<<<7Game of thrones>>>8烂尾了...'
dataASet=[0,0,1,1]
dataBSet=[2,0,0,1]
txt_value, txt_state = split2summary.txt2split(text)
print(txt_value)
print(txt_state) value = split2summary.value2comma(txt_value)
print(value)
split2summary.programA(value,dataASet)
# split2summary.programB(value,dataBSet)
参数配置文件 config.ini
# 标准汉语英语-语音处理合成程序-配置文件setting.ini
# 参数说明:
# ①txtA:程序A的处理参数
# name其他参数的名称,comma逗号重复次数,end句号重复次数,full全文重复次数,run是否运行,default默认参数
# ②txtB:程序B的处理参数
# ③chinese:标准汉语语音合成参数设置
# volume音量大小,tones音调,speed语速,spokesman发言人
# ④english:标准英语语音合成参数设置
# ⑤user:token需要自己更新数据,这是一个有期限的数据 [user]
name = url, ?appkey, &token, &format, &sample_rate
nowTime = 2019-05-17
&token = 07ee4200162547a39aebcd4325679219
AccessKeyID = 【这里需要自己的阿里云-参数】
AccessKeySecret = oPSg3IswMi8kNOpkRaAhkZBTtOPgkr
host = nls-gateway.cn-shanghai.aliyuncs.com
url = https://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/tts
?appkey = 【这里需要自己的阿里云-语音服务-参数】
&format = wav
&sample_rate = 16000
wav_format = "b'RIFF\xac\xdc9\x00WAVEfmt\x10\x00\x00\x00\x01\x00\x01\x00\x80>\x00\x00\x00}\x00\x00\x02\x00\x10\x00data\x80\xdc9\x00'" [txtA]
name = comma, end, full, run
comma = 2
end = 2
full = 1
run = 0
default_comma = 1, 2, 5
default_end = 1, 2, 5
default_full = 0, 1, 3
default_run = 0, 1 [txtB]
name = comma, end, full, run
comma = 3
end = 1
full = 1
run = 0
default_comma = 1, 3, 5
default_end = 1, 1, 5
default_full = 0, 1, 3
default_run = 0, 1 [chinese]
# voice发言人、volume音量、speech_rate语速、pitch_rate语调
name = &volume, &speech_rate, &pitch_rate, &voice
&volume = 50
&speech_rate = 0
&pitch_rate = 0
&voice = 9 default_&volume = 0, 50, 100
default_&speech_rate = -500, 0, 500
default_&pitch_rate = -500, 0, 500
default_&voice = 0, 9, 18
voice_parameter = Xiaoyun, Xiaogang, Ruoxi, Xiaomeng, Xiaowei, Amei, Xiaoxue, Siqi, Sijia, Sicheng, Siyue, Xiaomei, Sitong, Ninger, Xiaobei, Yina, Sijing, Shanshan [english]
# voice发言人、volume音量、speech_rate语速、pitch_rate语调
name = &volume, &speech_rate, &pitch_rate, &voice
&volume = 50
&speech_rate = 0
&pitch_rate = 0
&voice = 1 default_&volume = 0, 50, 100
default_&speech_rate = -500, 0, 500
default_&pitch_rate = -500, 0, 500
default_&voice = 0, 1, 3
voice_parameter = Wendy, William, Halen, Harry [help] [about]
四,总结
使用tkinter构建UI界面,ini文件充当参数配置文件,其中WAV音频文件合并过程中遇到一些问题,但是后续通过学习WAV音频格式文件的数据帧信息也顺利的解决了相关问题
五,参考链接
源码链接:https://pan.baidu.com/s/1yRzK4EFAeXg4tHIgZMsHjA 提取码:e24q 注意:AccessKeyID和AccessKeySecret需要填写自己的阿里云ID和密钥【这个很重要】
阿里云自动获取token值(python) https://www.cnblogs.com/Mufasa/p/10880698.html
WAV格式文件无损合并&帧头数据体解析(python)(原创) https://www.cnblogs.com/Mufasa/p/10878777.html
python读写增删修改ini配置文件 https://www.cnblogs.com/Mufasa/p/10845535.html
阿里云语音合成(汉语英语)带UI界面的小程序(python)的更多相关文章
- jira插件带ui界面和几种方式
http://localhost:2990/jira/plugins/servlet/issuecrud jira插件带ui界面和几种方式 https://developer.atlassian.co ...
- Solr4.10.2集成Nutch1.9与自带UI界面使用
Solr4.10.2集成Nutch1.9与自带UI界面使用 一.Solr4.10.2与Nutch1.9集成 环境:Solr4.10.2已经配置在Tomcat上 Solr的Tomcat配置详见Solr4 ...
- 不需内测账号,带你体验微信小程序完整开发过程
不需内测账号,带你体验微信小程序完整开发过程 2016年09月24日 - 作者: SwiftCafe 微信小程序还没正式发布就已经迅速成为大家讨论的焦点,那么大家可能觉得只有收到内测邀请才能体验小程序 ...
- windows下运行的linux服务器批量管理工具(带UI界面)
产生背景: 由于做服务器运维方面的工作,需要一人对近千台LINUX服务器进行统一集中的管理,如同时批量对LINUX服务器执行相关的指令.同时批量对LINUX服务器upload程序包.同时批量对LINU ...
- 阿里云出手SaaS生态,中国SaaS市场小而不强有望破解
企业服务SaaS市场还有很大的增长空间.SaaS的鼻祖Salesforces今年5月迈上了千亿美元市值的门槛,再一次为ToB市场注入了兴奋剂.单单一个SaaS CRM,目前全球的市场规模就超过400亿 ...
- 剖析简易计算器带你入门微信小程序开发
写在前面,但是重点在后面 这是教程,也不是教程. 可以先看Demo的操作动图,看看是个什么玩意儿,GitHub地址(https://github.com/dunizb/wxapp-sCalc) 自从微 ...
- 阿里云Ubuntu 18.04安装图形界面
#!/bin/bash #更新软件库 apt-get update #升级软件 apt-get upgrade #安装ubuntu桌面系统 apt-get install ubuntu-desktop
- 带坑使用微信小程序框架WePY组件化开发项目,附带第三方插件使用坑
纯粹用来记录wepy及相关联内容,以防再犯~ 1. 接手的wepy项目版本是 1.7.2 ,so我没有初始化的过程.... 2. 安装wepy命令工具,npm install wepy-cli -g ...
- C#/.NET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案
本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...
随机推荐
- git push and git pull
原文链接 git push 通常对于一个本地的新建分支,例如git checkout -b develop, 在develop分支commit了代码之后,如果直接执行git push命令,develo ...
- ARP 之 发送请求arp_solicit
概述 arp_solicit用来发送ARP请求,首先会根据ARP_ANNOUNCE参数来选取源地址,然后判断是否达到内核发送次数上限,未达到则调用内核arp_send_dst函数发送,如果达到上限,则 ...
- 【MyBatis】实现in操作符在WHERE 子句中规定多个值
Mapper.xml中写: <select id="selectIdsByDate" resultType="java.lang.Long"> se ...
- [java]取当前平台默认字符集,取字符串长度
public class TimestampLength { public static void main(String[] args) { System.out.println(java.nio. ...
- 前端知识点回顾之重点篇——ES6的async函数和module
async函数 ES2017 标准引入了 async 函数,使得异步操作变得更加方便. async 函数是 Generator 函数的语法糖 什么是语法糖? 意指那些没有给计算机语言添加新功能,而只是 ...
- C++ STL——string和vector
目录 一 STL基本概念 二 string容器 三 vector容器 3.1 vector动态增长原理 3.2 vector构造函数 3.3 vector常用赋值操作 3.4 vector大小操作 3 ...
- 升级到Android Studio3.x遇到的问题及解决方案
升级到Android Studio3.x遇到的问题及解决方案 转 https://www.2cto.com/kf/201711/695736.html 升级到Android Studio3.0遇到的问 ...
- handler方法
post(Runnable) postAtTime(Runnable,long) postDelayed(Runnable long) post类方法允许你排列一个Runnable对象到主线程队列中 ...
- 小D课堂 - 新版本微服务springcloud+Docker教程_5-01分布式核心知识之熔断、降级
笔记: 第五章 互联网架构服务降级熔断 Hystrix 实战 1.分布式核心知识之熔断.降级讲解 简介:系统负载过高,突发流量或者网络等各种异常情况介绍,常用的解决方案 1.熔断: ...
- Linux日常用的命令
查看一个文件夹是的挂载路径,比如查看opt文件夹挂载在哪:df /opt root@iZ2zedo02x7n4nuc3lb4ueZ:~# df /opt Filesystem 1K-blocks Us ...