阿里云语音合成(汉语英语)带UI界面的小程序(python)

一,项目说明

  将汉文转汉语、英文转英语,同时又有逗号<###English###>,<,,,>和句号<...>标志符用于文件处理。其中英文包含在### 英文 ###中。

  程序A:三个逗号<,,,>和三个句号<...>前面的句段独立成块小分段,同时三个句号<...>前面的句段划分成为另一种较大的分段。其中程序中有控制<,,,>和<...>重复次数的数值

 

程序A输入样例1:

1 ###bring###拿来,带来,,,
2 ###Bronze###青铜色的...
3 ###brush###刷;檫,,,
4 ###build###建筑;造,,,
5 ###building###建筑物;房屋;大楼...

程序A输出样例1:(下文为音频发音的内容)

 1 bring拿来,带来bring拿来,带来
 2 Bronze青铜色的Bronze青铜色的
 3 
 4 bring拿来,带来Bronze青铜色的
 5 
 6 brush刷;檫brush刷;檫
 7 build建筑;造build建筑;造
 8 building建筑物;房屋;大楼building建筑物;房屋;大楼
 9 
10 brush刷;檫build建筑;造building建筑物;房屋;大楼
11 
12 bring拿来,带来Bronze青铜色的brush刷;檫build建筑;造building建筑物;房屋;大楼

 

程序B输入样例1:

###bring###拿来,带来,,,
###Bronze###青铜色的...
###brush###刷;檫,,,
###build###建筑;造,,,
###building###建筑物;房屋;大楼...

程序B输出样例1:(下文为音频发音的内容)

 1 bring拿来,带来bring拿来,带来bring拿来,带来
 2 
 3 Bronze青铜色的
 4 
 5 brush刷;檫brush刷;檫brush刷;檫
 6 build建筑;造build建筑;造造build建筑;造
 7 
 8 building建筑物;房屋;大楼
 9 
10 bring拿来,带来Bronze青铜色的brush刷;檫build建筑;造building建筑物;房屋;大楼

 备注:上文中的程序A、程序B都是使用的默认配置

 

二,界面解析

 

图1 主界面

 

图2 文本导入界面(支持txt和docx文件格式)

 

图3 参数设置界面

 

 

图4 近期调用统计图(更新2019-06-16,尾款到手不再更新)

 

 

三,源码开放

 

界面显示(主函数)  ui2show.pyw

  1 import tkinter as tk
  2 import netWork
  3 import split2summary
  4 import tkinter.filedialog
  5 import os
  6 import shutil
  7 import docx
  8 from configobj import ConfigObj
  9 from tkinter import ttk
 10 from tkinter import messagebox
 11 import struct
 12 
 13 
 14 class ui2show(tk.Tk):
 15     def __init__(self):
 16         super().__init__()
 17         
 18         rootPath = os.path.split(os.path.realpath(__file__))[0]
 19         os.chdir(rootPath)
 20         self.dictSpace = {0: 'chinese', 1: 'english'}
 21         
 22         # *** 系统初始化检测网络 *** #
 23         self.netWork = netWork.netWork()
 24         self.netState, self.textShow = self.netWork.isConnected()
 25 
 26         # *** 提前加载功能库 *** #
 27         self.split2summary = split2summary.split2summary()
 28         self.config = ConfigObj("config.ini", encoding='UTF8')
 29         #print(self.config)
 30         
 31         self.vartext = tk.StringVar()
 32         self.vartext.set(self.textShow)
 33         self.geometry('597x100')
 34         self.resizable(0, 0)
 35         self.title('文字处理&音频合成')
 36         self.fileFeedback = []
 37 
 38         self.homePage()
 39 
 40     def homePage(self):  # 默认主页
 41         self.top1 = tk.Frame()
 42         self.top1.pack(fill="x")
 43 
 44         tk.Button(self.top1, text='文本导入', width=27, command=self.file4manage).grid(row=0, column=0)
 45         tk.Button(self.top1, text='参数设置', width=27, command=self.config4set).grid(row=0, column=1)
 46         tk.Button(self.top1, text='音频合成', width=27, command=self.txt2run).grid(row=0, column=2)
 47         tk.Label(self.top1, height=3, textvariable=self.vartext, bg='white', font=('黑体', 10), anchor='w').grid(row=1,
 48                                                                                                                column=0,
 49                                                                                                                columnspan=3)
 50 
 51     def file4manage(self):  # 文件初始化 成功√
 52         path = tkinter.filedialog.askopenfilename(initialdir='C:\\Users\\Administrator\\Desktop', filetypes=(
 53             ("txt or docx files", "*.txt;*.docx"), ("All files", "*.*")))
 54         if path == "":
 55             self.fileState, self.textShow, self.fileFeedback = False, '未导入任何文件', []
 56         else:  # 已导入文件
 57             p, f = os.path.split(path)
 58             path_directory = os.path.dirname(os.path.realpath(__file__)) + '\\data\\' + str(os.path.splitext(f)[0])
 59             isExists = os.path.exists(path_directory)
 60             if not isExists:  # 如果不存在这个目录
 61                 os.makedirs(path_directory)  # 创建一个新的路径
 62                 shutil.copyfile(path, path_directory + '\\' + f)
 63 
 64             if str(os.path.splitext(f)[1]) == '.txt':
 65                 file_object = open(path, 'r')
 66                 file_context = file_object.read()
 67                 file_object.close()
 68 
 69             elif str(os.path.splitext(f)[1]) == '.docx':
 70                 document = docx.Document(path)
 71                 file_context = ''
 72                 for paragraph in document.paragraphs:
 73                     file_context += paragraph.text
 74             self.fileState, self.textShow, self.fileFeedback = True, '已导入文本数据', [path_directory, file_context]
 75         self.vartext.set(self.textShow)
 76 
 77     def config4set(self):  # 参数配置界面
 78         self.top2 = tk.Toplevel()
 79         self.top2.title('参数配置')
 80 
 81         self.txtShow = []  # 直接全部设置成int型文件
 82         for i in range(16):
 83             if i == 11 or 15:
 84                 self.txtShow.append(tk.StringVar())
 85             else:
 86                 self.txtShow.append(tk.IntVar())
 87 
 88         txtShow = []
 89         #print(self.config['txtA'])
 90         txtA = self.config['txtA']
 91         for i in enumerate(txtA['name']):
 92             txtShow.append(int(txtA[i[1]]))
 93         txtB = self.config['txtB']
 94         for i in enumerate(txtB['name']):
 95             txtShow.append(int(txtB[i[1]]))
 96         txtC = self.config['chinese']
 97         for i in enumerate(txtC['name']):
 98             txtShow.append(int(txtC[i[1]]))
 99         txtD = self.config['english']
100         for i in enumerate(txtD['name']):
101             txtShow.append(int(txtD[i[1]]))
102 
103         # print(txtShow)
104         for keyi, valuei in enumerate(txtShow):
105             self.txtShow[keyi].set(valuei)
106 
107         tk.Label(self.top2, text='程序A', width=30).grid(row=0, column=0, columnspan=2)
108         tk.Label(self.top2, text='逗号次数', width=10).grid(row=1, column=0, columnspan=1)
109         tk.Label(self.top2, text='句号次数', width=10).grid(row=2, column=0, columnspan=1)
110         tk.Label(self.top2, text='全部文本次数', width=10).grid(row=3, column=0, columnspan=1)
111         tk.Label(self.top2, text='是否生成音频', width=10).grid(row=4, column=0, columnspan=1)
112         tk.Entry(self.top2, textvariable=self.txtShow[0], width=10).grid(row=1, column=1)
113         tk.Entry(self.top2, textvariable=self.txtShow[1], width=10).grid(row=2, column=1)
114         tk.Entry(self.top2, textvariable=self.txtShow[2], width=10).grid(row=3, column=1)
115         checkA = tk.Checkbutton(self.top2, text="", variable=self.txtShow[3], width=10)
116         checkA.select()
117         checkA.grid(column=1, row=4, sticky=tk.W)
118 
119         tk.Label(self.top2, text='程序B', width=30).grid(row=0, column=2, columnspan=2)
120         tk.Label(self.top2, text='逗号次数', width=10).grid(row=1, column=2, columnspan=1)
121         tk.Label(self.top2, text='句号次数', width=10).grid(row=2, column=2, columnspan=1)
122         tk.Label(self.top2, text='全部文本次数', width=10).grid(row=3, column=2, columnspan=1)
123         tk.Label(self.top2, text='是否生成音频', width=10).grid(row=4, column=2, columnspan=1)
124         tk.Entry(self.top2, textvariable=self.txtShow[4], width=10).grid(row=1, column=3)
125         tk.Entry(self.top2, textvariable=self.txtShow[5], width=10).grid(row=2, column=3)
126         tk.Entry(self.top2, textvariable=self.txtShow[6], width=10).grid(row=3, column=3)
127         checkB = tk.Checkbutton(self.top2, text="", variable=self.txtShow[7], width=10)
128         checkB.select()
129         checkB.grid(column=3, row=4, sticky=tk.W)
130 
131         tk.Label(self.top2, text='汉语', width=10).grid(row=0, column=4, columnspan=2)
132         tk.Label(self.top2, text='音量', width=10).grid(row=1, column=4, columnspan=1)
133         tk.Label(self.top2, text='语速', width=10).grid(row=2, column=4, columnspan=1)
134         tk.Label(self.top2, text='语调', width=10).grid(row=3, column=4, columnspan=1)
135         tk.Label(self.top2, text='发言人', width=10).grid(row=4, column=4, columnspan=1)
136         tk.Entry(self.top2, textvariable=self.txtShow[8], width=13).grid(row=1, column=5)
137         tk.Entry(self.top2, textvariable=self.txtShow[9], width=13).grid(row=2, column=5)
138         tk.Entry(self.top2, textvariable=self.txtShow[10], width=13).grid(row=3, column=5)
139         chosenC = ttk.Combobox(self.top2, textvariable=self.txtShow[11], width=10)
140         chosenC['values'] = (
141             'Xiaoyun', 'Xiaogang', 'Ruoxi', 'Xiaomeng', 'Xiaowei', 'Amei', 'Xiaoxue', 'Siqi', 'Sijia', 'Sicheng',
142             'Siyue',
143             'Xiaomei', 'Sitong', 'Ninger', 'Xiaobei', 'Yina', 'Sijing', 'Shanshan')
144         chosenC.current(txtShow[11])
145         chosenC.grid(row=4, column=5)
146 
147         tk.Label(self.top2, text='英语', width=10).grid(row=0, column=6, columnspan=2)
148         tk.Label(self.top2, text='音量', width=10).grid(row=1, column=6, columnspan=1)
149         tk.Label(self.top2, text='语速', width=10).grid(row=2, column=6, columnspan=1)
150         tk.Label(self.top2, text='语调', width=10).grid(row=3, column=6, columnspan=1)
151         tk.Label(self.top2, text='发言人', width=10).grid(row=4, column=6, columnspan=1)
152         tk.Entry(self.top2, textvariable=self.txtShow[12], width=13).grid(row=1, column=7)
153         tk.Entry(self.top2, textvariable=self.txtShow[13], width=13).grid(row=2, column=7)
154         tk.Entry(self.top2, textvariable=self.txtShow[14], width=13).grid(row=3, column=7)
155         chosenD = ttk.Combobox(self.top2, textvariable=self.txtShow[15], width=10)
156         chosenD['values'] = ('Wendy', 'William', 'Halen', 'Harry')
157         chosenD.current(txtShow[15])
158         chosenD.grid(row=4, column=7)
159 
160         tk.Button(self.top2, text='确定', command=self.config2ok, width=27).grid(row=5, column=0, columnspan=2)
161         tk.Button(self.top2, text='重置', command=self.config2reset, width=27).grid(row=5, column=2, columnspan=2)
162         tk.Button(self.top2, text='帮助', command=self.config2help, width=27).grid(row=5, column=4, columnspan=2)
163 
164         # for keyi,valuei in enumerate(txtShow):
165         self.txtShow[3].set(txtShow[3])
166         self.txtShow[7].set(txtShow[7])
167 
168     def config2ok(self):  # 参数设置-成功√
169         txtShow = []
170         for i in self.txtShow:
171             txtShow.append(i.get())
172 
173         txtShow[11] = self.config['chinese']['voice_parameter'].index(txtShow[11])
174         txtShow[15] = self.config['english']['voice_parameter'].index(txtShow[15])
175         # print('txtShow:',txtShow[3],txtShow[7])
176 
177         for i in enumerate(txtShow[:4]):
178             self.config['txtA'][self.config['txtA']['name'][i[0]]] = i[1]
179         for i in enumerate(txtShow[4:8]):
180             self.config['txtB'][self.config['txtB']['name'][i[0]]] = i[1]
181         for i in enumerate(txtShow[8:12]):
182             self.config['chinese'][self.config['chinese']['name'][i[0]]] = i[1]
183         for i in enumerate(txtShow[12:16]):
184             self.config['english'][self.config['english']['name'][i[0]]] = i[1]
185         self.config.write()
186 
187     def config2reset(self):  # 恢复出厂设置 成功√
188         for i in ['txtA', 'txtB', 'chinese', 'english']:
189             for j in self.config[i]['name']:
190                 self.config[i][j] = self.config[i]['default_' + j][1]
191         self.config.write()
192 
193         txtShow = []    # 获取最新的参数配置并更新界面数据
194         txtA = self.config['txtA']
195         for i in enumerate(txtA['name']):
196             txtShow.append(int(txtA[i[1]]))
197         txtB = self.config['txtB']
198         for i in enumerate(txtB['name']):
199             txtShow.append(int(txtB[i[1]]))
200         txtC = self.config['chinese']
201         for i in enumerate(txtC['name']):
202             txtShow.append(int(txtC[i[1]]))
203         txtD = self.config['english']
204         for i in enumerate(txtD['name']):
205             txtShow.append(int(txtD[i[1]]))
206 
207         for keyi, valuei in enumerate(txtShow):
208             self.txtShow[keyi].set(valuei)
209         self.txtShow[11].set(self.config['chinese']['voice_parameter'][txtShow[11]])
210         self.txtShow[15].set(self.config['english']['voice_parameter'][txtShow[15]])
211 
212     def config2help(self):
213         tk.messagebox.showinfo("参数设置帮助", "语音合成参数设置范围:\n1,音量范围0~100;\n2,语速范围-500~500;\n3,语调范围-500~500;")
214 
215     def txt2run(self):
216         if len(self.fileFeedback) == 0:
217             self.textShow = '没有导入文本文件\n请先进行{文本导入}'
218             self.vartext.set(self.textShow)
219         else:  # 已正常导入【路径,文本】
220             # self.dictSpace
221             dataASet = []
222             for i in self.config['txtA']['name']:
223                 dataASet.append(int(self.config['txtA'][i]))
224             dataBSet = []
225             for i in self.config['txtB']['name']:
226                 dataBSet.append(int(self.config['txtB'][i]))
227             if dataASet[-1]+dataBSet[-1]==0:
228                 self.textShow='设置中未勾选{是否生成音频}\n请先勾选相关选项再做操作'
229                 self.vartext.set(self.textShow)
230                 return None
231             txt_value, txt_state = self.split2summary.txt2split(self.fileFeedback[1])
232             self.textShow = '正在将文字转化为音频...'
233             self.vartext.set(self.textShow)
234             for keyi, valuei in enumerate(txt_value):
235                 for keyj, valuej in enumerate(valuei):
236                     for keyk, valuek in enumerate(valuej):
237                         txt_value[keyi][keyj][keyk] = self.netWork.txt2audio(txt_value[keyi][keyj][keyk],
238                                                                              self.dictSpace[
239                                                                                  txt_state[keyi][keyj][keyk]])
240 
241             # *** 合成音频完整性测试 *** #   测试成功√
242             # audioTest=[]
243             # for keyi, valuei in enumerate(txt_value):  # 句号
244             #     for keyj, valuej in enumerate(valuei):
245             #         for keyk, valuek in enumerate(valuej):
246             #             pathTest = self.fileFeedback[0] + '\\' + self.fileFeedback[0].split('\\')[-1] + str(keyi)+str(keyj)+str(keyk) +'Test.wav'
247             #             with open(pathTest, mode='wb') as f:
248             #                 f.write(txt_value[keyi][keyj][keyk])
249 
250             # *** 音频文件合并成逗号分段 *** #
251             wav_format = txt_value[0][0][0][:44]  # wav音频文件的帧头信息,后续保存文件需要进行二次修改
252             for keyi, valuei in enumerate(txt_value):  # 句号
253                 for keyj, valuej in enumerate(valuei):
254                     # str_comma = []
255                     for keyk, valuek in enumerate(valuej):
256                         if keyk == 0:
257                             str_comma = txt_value[keyi][keyj][keyk]
258                         else:
259                             str_comma += txt_value[keyi][keyj][keyk][44:]
260                     txt_value[keyi][keyj] = str_comma
261 
262             # *** 合成音频英汉合并完整性测试 *** #   测试成功√
263             # audioTest=[]
264             # for keyi, valuei in enumerate(txt_value):  # 句号
265             #     for keyj, valuej in enumerate(valuei):
266             #         pathTest = self.fileFeedback[0] + '\\' + self.fileFeedback[0].split('\\')[-1] + 'comma'+str(keyi)+str(keyj)+'Test.wav'
267             #         with open(pathTest, mode='wb') as f:
268             #             f.write(txt_value[keyi][keyj])
269 
270             # *** 程序A *** #
271             if dataASet[-1]:
272                 self.textShow = '正在生成音频A'
273                 self.vartext.set(self.textShow)
274                 # print('runA',dataASet)
275                 pathA = self.fileFeedback[0] + '\\' + self.fileFeedback[0].split('\\')[-1] + 'A.wav'
276                 audioA = self.split2summary.programA(txt_value, dataASet)
277 
278                 audioA_len = len(audioA)
279                 wav_format = wav_format[:4] + struct.pack('<L', audioA_len + 44) + wav_format[8:]
280                 wav_format = wav_format[:40] + struct.pack('<L', audioA_len) + wav_format[44:]
281                 with open(pathA, mode='wb') as f:
282                     f.write(wav_format + audioA)
283                 self.textShow = '已生成音频A'
284                 self.vartext.set(self.textShow)
285 
286             # *** 程序B *** #
287             if dataBSet[-1]:
288                 self.textShow += '正在成音频B'
289                 self.vartext.set(self.textShow)
290 
291                 pathB = self.fileFeedback[0] + '\\' + self.fileFeedback[0].split('\\')[-1] + 'B.wav'
292                 audioB = self.split2summary.programB(txt_value, dataBSet)
293 
294                 audioB_len = len(audioB)
295                 wav_format = wav_format[:4] + struct.pack('<L', audioB_len + 44) + wav_format[8:]
296                 wav_format = wav_format[:40] + struct.pack('<L', audioB_len) + wav_format[44:]
297                 with open(pathB, mode='wb') as f:
298                     f.write(wav_format + audioB)
299 
300             if dataASet[-1] and dataBSet[-1]:
301                 self.textShow='已合成音频A、B'
302             elif dataBSet[-1]:
303                 self.textShow = '已合成音频B'
304             elif dataASet[-1]:
305                 self.textShow = '已合成音频A'
306 
307             self.vartext.set(self.textShow)
308 
309 if __name__ == '__main__':
310     # *** 测试ui界面显示 *** #
311     ui2show = ui2show()
312     ui2show.mainloop()

 

网络相关支持函数  netWork.pyw

  1 #-*- coding:utf-8 -*- 
  2 from configobj import ConfigObj  # config.ini参数操作函数
  3 import urllib.parse
  4 import requests  # 网络操作函数
  5 import http.client
  6 from aliyunsdkcore.client import AcsClient
  7 from aliyunsdkcore.request import CommonRequest
  8 import json
  9 import datetime
 10 
 11 # *** 网络连接函数 *** #
 12 class netWork:
 13     # def __init__(self):
 14     #     pass
 15 
 16     def isConnected(self):  # 检测网络是否已正常连接
 17         try:
 18             html = requests.get("https://www.baidu.com/", timeout=2)
 19         except:
 20             return False, '无法连接网络,请检查网络是否正常连接'
 21         return True, '网络连接正常'
 22 
 23     def getToken(self):  # 获取token值,后续需要在version3.0解决
 24         config = ConfigObj("config.ini", encoding='UTF8')
 25         client = AcsClient(config['user']['AccessKeyID'], config['user']['AccessKeySecret'], "cn-shanghai")
 26         request = CommonRequest()
 27         request.set_method('POST')
 28         request.set_domain('nls-meta.cn-shanghai.aliyuncs.com')
 29         request.set_version('2019-02-28')
 30         request.set_action_name('CreateToken')
 31         response = client.do_action_with_exception(request)
 32         response = json.loads(str(response, 'utf-8'))
 33         return response['Token']['Id']
 34 
 35     def txt2audio(self, text, type):  # 小段文本转音频的程序,输入text、
 36         config = ConfigObj("config.ini", encoding='UTF8')
 37         if config['user']['nowTime']!=str(datetime.datetime.now())[:10]:    # 按天进行token值更新
 38             config['user']['nowTime'] = str(datetime.datetime.now())[:10]
 39             config['user']['&token'] = self.getToken()
 40             config.write()
 41 
 42         conn = http.client.HTTPSConnection(config['user']['host'])
 43         du = config['user']
 44         dc = config[type]  # 这里分汉文、英文
 45 
 46         url = ''
 47         url = 'https://' + du['host'] + '/stream/v1/tts'
 48         url = url + '?appkey=' + du['?appkey']
 49         url = url + '&token=' + du['&token']
 50         url = url + '&format=' + du['&format']
 51         url = url + '&sample_rate=' + du['&sample_rate']
 52         url = url + '&voice=' + dc['voice_parameter'][int(dc['&voice'])]
 53         url = url + '&volume=' + dc['&volume']
 54         url = url + '&speech_rate=' + dc['&speech_rate']
 55         url = url + '&pitch_rate=' + dc['&pitch_rate']
 56 
 57         if type == 'chinese':
 58             if len(text) < 300:  # 满足文本长度要求
 59                 list_text = [text]
 60             else:  # 不满足文本长度要求
 61                 list_text = text.split('.')  # 很少有文本能够一段超过300字
 62         elif type == 'english':
 63             num = len(text.split())  # 英文和汉文不同使用空格区分单词
 64             if num < 300:
 65                 list_text = [text]
 66             else:
 67                 list_text = text.split('.')
 68         list_audio = []
 69         for i in list_text:
 70             textUrlencode = urllib.parse.quote_plus(i)
 71             textUrlencode = textUrlencode.replace("+", "%20")
 72             textUrlencode = textUrlencode.replace("*", "%2A")
 73             textUrlencode = textUrlencode.replace("%7E", "~")
 74             conn.request(method='GET', url=url + '&text=' + textUrlencode)
 75             response = conn.getresponse()
 76             body = response.read()
 77             list_audio.append(body)
 78         conn.close()
 79 
 80         audio_all = list_audio[0]
 81         if len(list_text) > 1:
 82             for i in list_audio[1:]:
 83                 audio_all += i
 84         return audio_all
 85 
 86 
 87 if __name__ == '__main__':
 88     net = netWork()
 89     # *** 测试网络连接是否正常 *** #      成功√
 90     netState, feedbackWord=net.isConnected()
 91     print(netState, feedbackWord)
 92 
 93     # *** 测试自动获取token值 *** #    成功√
 94     # Token=net.getToken()
 95     # print(Token)
 96 
 97     # *** 测试语音合成是否正常 *** #  成功√
 98     # text = '你好,万雨。测试成功'
 99     # type = 'chinese'
100     # fileName = 'testAudio1.wav'
101     # audio = net.txt2audio(text, type)
102     # with open(fileName, mode='wb') as f:
103     #     f.write(audio)

 

文本处理相关函数  split2summary.pyw

  1 #-*- coding:utf-8 -*- 
  2 """
  3 函数说明:
  4 ①将原始文本进行拆分-合并
  5 ②将获得音频进行按要求重复合并
  6 
  7 """
  8 
  9 
 10 class split2summary:
 11     def findCE(self, text):  # 区分汉文英文
 12         index = []
 13         for i in range(len(text) - 2):
 14             if text[i:i + 3] == '###':
 15                 index.append(i)
 16             # elif text[i:i + 3] == '>>>':
 17             #     index.append(i)
 18         # print(index)
 19         if len(index) == 0:
 20             return [text], [0]
 21         text_list = []
 22         text_state = []
 23         index_history = [0, 0]
 24         for key, value in enumerate(index):
 25             # print(key,value)
 26             if key % 2 == 0:  # 汉文
 27                 if index[key] == 0:
 28                     continue
 29                 index_history = [index_history[1], index[key]]
 30                 if key == 0:
 31                     text_list.append(text[index_history[0]:index_history[1]])
 32                 else:
 33                     text_list.append(text[index_history[0] + 3:index_history[1]])
 34                 text_state.append(0)
 35             else:  # 英文
 36                 index_history = [index_history[1], index[key]]
 37                 text_list.append(text[index_history[0] + 3:index_history[1]])
 38                 text_state.append(1)
 39         # 解决句尾的问题
 40         if index[-1] + 3 != len(text):
 41             text_list.append(text[index[-1] + 3:len(text)])
 42             text_state.append(0)
 43         return text_list, text_state
 44 
 45     def txt2split(self, text):
 46         txt_mid = text.split('...')
 47         for i in range(len(txt_mid)):
 48             txt_mid[i] = txt_mid[i].split(',,,')
 49         txt_value = []
 50         txt_state = []
 51         for i in txt_mid[:-1]:
 52             txt_state_mid = []
 53             txt_value_mid = []
 54             for j in i:
 55                 text_list, text_state = self.findCE(j)
 56                 txt_value_mid.append(text_list)
 57                 txt_state_mid.append(text_state)
 58             txt_value.append(txt_value_mid)
 59             txt_state.append(txt_state_mid)
 60         return txt_value, txt_state
 61 
 62     # *** 将最小分段合并一级到逗号分段 *** #
 63     def value2comma(self, value):
 64         for keyi, valuei in enumerate(value):  # 句号
 65             for keyj, valuej in enumerate(valuei):
 66                 for keyk, valuek in enumerate(valuej):
 67                     if keyk == 0:
 68                         str_comma = value[keyi][keyj][keyk]
 69                     else:
 70                         str_comma += value[keyi][keyj][keyk]
 71                 value[keyi][keyj] = str_comma
 72         return value
 73 
 74     # *** 处理分段函数A 成功√ *** #
 75     def programA(self, value, dataASet):
 76         valueA = []
 77         for keyi, valuei in enumerate(value):  # 句号
 78             value_end = []
 79             for keyj, valuej in enumerate(valuei):
 80                 if keyj == 0 and (dataASet[0] != 0 or dataASet[1] != 0):
 81                     value_end = value[keyi][keyj]
 82                     if dataASet[0] != 0:
 83                         for times in range(dataASet[0] - 1):
 84                             value_end += value[keyi][keyj]
 85                 elif dataASet[0] != 0:
 86                     for times in range(dataASet[0]):
 87                         value_end += value[keyi][keyj]
 88                 elif dataASet[1] != 0:
 89                     value_end += value[keyi][keyj]
 90 
 91             if keyi == 0 and dataASet[0] != 0:
 92                 valueA = value_end
 93             elif dataASet[0] != 0:
 94                 valueA += value_end
 95 
 96         # *** 专门针对句号分段 *** #
 97         # for keyi, valuei in enumerate(value):
 98             for times in range(dataASet[1]):
 99                 for keyj, valuej in enumerate(valuei):
100                     if (keyi == 0 and keyj == 0) and (dataASet[0] == 0 and valueA == []):
101                         valueA = value[keyi][keyj]
102                     else:
103                         valueA += value[keyi][keyj]
104 
105         # *** 专门针对整个篇幅的分段 *** #
106         for times in range(dataASet[2]):
107             for keyi, valuei in enumerate(value):  # 句号
108                 for keyj, valuej in enumerate(valuei):
109                     # print(keyi, keyj)
110                     if (keyi, keyj) == (0, 0) and valueA == []:
111 
112                         valueA = value[keyi][keyj]
113                     else:
114                         valueA += value[keyi][keyj]
115 
116         # print(valueA)
117         return valueA
118 
119     def programB(self, value, dataBSet):
120         valueB=[]
121         # *** 逗号分段处理 *** #
122         for keyi, valuei in enumerate(value):  # 句号
123             value_end = []
124             for keyj, valuej in enumerate(valuei[:-1]):
125                 if keyj == 0 and (dataBSet[0] != 0 or dataBSet[1] != 0):
126                     value_end = value[keyi][keyj]
127                     if dataBSet[0] != 0:
128                         for times in range(dataBSet[0] - 1):
129                             value_end += value[keyi][keyj]
130                 elif dataBSet[0] != 0:
131                     for times in range(dataBSet[0]):
132                         value_end += value[keyi][keyj]
133                 elif dataBSet[1] != 0:
134                     value_end += value[keyi][keyj]
135 
136             if keyi == 0 and dataBSet[0] != 0:
137                 valueB = value_end
138             elif dataBSet[0] != 0:
139                 valueB += value_end
140 
141             # *** 专门针对句号分段 *** #
142             for times in range(dataBSet[1]):
143                 if (keyi == 0) and (valueB == []):
144                     valueB = value[keyi][-1]
145                 else:
146                     valueB += value[keyi][-1]
147 
148         # *** 专门针对整个篇幅的分段 *** #
149         for times in range(dataBSet[2]):
150             for keyi, valuei in enumerate(value):  # 句号
151                 for keyj, valuej in enumerate(valuei):
152                     if (keyi, keyj) == (0, 0) and valueB == []:
153                         # print('run')
154                         valueB = value[keyi][keyj]
155                     else:
156                         valueB += value[keyi][keyj]
157 
158         # print(valueB)
159         return valueB
160 
161 
162 if __name__=="__main__":
163     split2summary = split2summary()
164     text = '1你好<<<2don\'t do that>>>,,,<<<3I have a dream>>>4万雨...5什么<<<6hello>>>,,,<<<7Game of thrones>>>8烂尾了...'
165     dataASet=[0,0,1,1]
166     dataBSet=[2,0,0,1]
167     txt_value, txt_state = split2summary.txt2split(text)
168     print(txt_value)
169     print(txt_state)
170 
171     value = split2summary.value2comma(txt_value)
172     print(value)
173     split2summary.programA(value,dataASet)
174     # split2summary.programB(value,dataBSet)

 

参数配置文件  config.ini

 1 #   标准汉语英语-语音处理合成程序-配置文件setting.ini
 2 #   参数说明:
 3 #   ①txtA:程序A的处理参数
 4 #   name其他参数的名称,comma逗号重复次数,end句号重复次数,full全文重复次数,run是否运行,default默认参数
 5 #   ②txtB:程序B的处理参数
 6 #   ③chinese:标准汉语语音合成参数设置
 7 #   volume音量大小,tones音调,speed语速,spokesman发言人
 8 #   ④english:标准英语语音合成参数设置
 9 #   ⑤user:token需要自己更新数据,这是一个有期限的数据
10 
11 [user]
12 name = url, ?appkey, &token, &format, &sample_rate
13 nowTime = 2019-05-17
14 &token = 07ee4200162547a39aebcd4325679219
15 AccessKeyID = 【这里需要自己的阿里云-参数】
16 AccessKeySecret = oPSg3IswMi8kNOpkRaAhkZBTtOPgkr
17 host = nls-gateway.cn-shanghai.aliyuncs.com
18 url = https://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/tts
19 ?appkey = 【这里需要自己的阿里云-语音服务-参数】
20 &format = wav
21 &sample_rate = 16000
22 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'"
23 
24 
25 [txtA]
26 name = comma, end, full, run
27 comma = 2
28 end = 2
29 full = 1
30 run = 0
31 default_comma = 1, 2, 5
32 default_end = 1, 2, 5
33 default_full = 0, 1, 3
34 default_run = 0, 1
35 
36 [txtB]
37 name = comma, end, full, run
38 comma = 3
39 end = 1
40 full = 1
41 run = 0
42 default_comma = 1, 3, 5
43 default_end = 1, 1, 5
44 default_full = 0, 1, 3
45 default_run = 0, 1
46 
47 [chinese]
48 # voice发言人、volume音量、speech_rate语速、pitch_rate语调
49 name = &volume, &speech_rate, &pitch_rate, &voice
50 &volume = 50
51 &speech_rate = 0
52 &pitch_rate = 0
53 &voice = 9
54 
55 default_&volume = 0, 50, 100
56 default_&speech_rate = -500, 0, 500
57 default_&pitch_rate = -500, 0, 500
58 default_&voice = 0, 9, 18
59 voice_parameter = Xiaoyun, Xiaogang, Ruoxi, Xiaomeng, Xiaowei, Amei, Xiaoxue, Siqi, Sijia, Sicheng, Siyue, Xiaomei, Sitong, Ninger, Xiaobei, Yina, Sijing, Shanshan
60 
61 [english]
62 # voice发言人、volume音量、speech_rate语速、pitch_rate语调
63 name = &volume, &speech_rate, &pitch_rate, &voice
64 &volume = 50
65 &speech_rate = 0
66 &pitch_rate = 0
67 &voice = 1
68 
69 default_&volume = 0, 50, 100
70 default_&speech_rate = -500, 0, 500
71 default_&pitch_rate = -500, 0, 500
72 default_&voice = 0, 1, 3
73 voice_parameter = Wendy, William, Halen, Harry
74 
75 [help]
76 
77 [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

 

posted on 2019-05-17 21:27  周健康  阅读(2658)  评论(2编辑  收藏  举报

导航