一,项目说明
将汉文转汉语、英文转英语,同时又有逗号<###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音频格式文件的数据帧信息也顺利的解决了相关问题