多线程的音频打标记的python实现(原创)

技术难度:

①需要一个UI界面,并且其中可进行相关参数的自调,最开始使用的是pygame的框架,后来转用tk界面;

②需要可以播放音频文件,MP3、WMA等格式;

③需要在播放音频的同时进行打标签操作,多线程技术;

④对音频进行相关拆分、叠加、重组,使用ffmpeg库进行相关操作;

一,UI界面

二,文件内容

使用 双击启动音频标记程序.bat 文件进行相对位置的文件启动,并且在 lib 中把所需的 ffmpeg 文件都已加载进去

三,程序源码

其中使用 threading 库的多线程功能,并且也使用到tk按钮中传递对象的功能。

  1 #-*- coding:utf-8 -*-
  2 #edited by Mufasa
  3 #文本标记软件
  4 
  5 # import pygame     #已经确定
  6 import time
  7 import threading
  8 import tkinter,time,decimal,math,string,os
  9 import tkinter.filedialog
 10 import shutil
 11 import tkinter as tk
 12 import subprocess
 13 from pydub import AudioSegment     #已经确定
 14 
 15 
 16 def out_comma(data,num_1,num_2):
 17   txt=''
 18   if len(data)==1:
 19     for n in range(num_2):
 20       txt=txt+data[0]+''
 21     txt=txt[:-1]+''
 22   else:
 23     for i in data:
 24       for n in range(num_1):
 25         txt=txt+i+''
 26     if num_1!=0:
 27       txt=txt[:-1]+''
 28     for n in range(num_2):
 29       for i in data:
 30         txt=txt+i+''
 31       txt=txt[:-1]+''
 32   return txt
 33 
 34 
 35 
 36 
 37 class assist():
 38   def write_txt_data(data,path):
 39     ls = os.linesep
 40     #data 为数组类型
 41     fobj = open(path,'w')
 42     fobj.writelines(['%s%s'%(x,ls)for x in data])
 43     fobj.close()
 44   def read_txt_data(path):
 45     fobj = open(path,'r')
 46     string = []
 47     for eachline in fobj:
 48       if eachline[:-1] != '':
 49         string.append(eachline[:-1])
 50     fobj.close()
 51     return string
 52     
 53     
 54 class out_aboutcode(tk.Toplevel):
 55   def __init__(self):
 56     super().__init__()
 57     self.title('关于程序')# 弹窗界面
 58     self.setup_UI()
 59   def setup_UI(self):
 60     row1 = tk.Frame(self)
 61     row1.pack(fill="x")
 62     # tk.Label(row1, text='欢迎使用音频标记软件!软件基于Python36设计

使用说明:
1,先选择需要进行标记的音频文件;
2,点击——标记音频按钮,开始进行标记其中[ , ]符为小段标记点,[ . ]为大段标记点;
3,标记的音频播放完毕后,点击—生成标记按钮,直接转换成标记文件并存储在\data\文件名\目录下;

欢迎使用').pack(side=tk.LEFT)
 63     tk.Label(row1, text='欢迎使用音频标记软件!软件基于Python36设计

使用说明:
1,先点击[ 选择音频 ],选定您要进行标记的音频文件(默认支持MP3和wav格式)
2,点击[ 标记音频 ],在文件的文本输入框中输入 , . 这两种符号分别进行小段和大段标记
3,点击[ 生成标记 ],将音频的标记信息进行存储
4,点击[ 设置音频 ],对音频的播放模式进行个性化设置

祝使用愉快(*^_^*)').pack(side=tk.LEFT)
 64     
 65     row4 = tk.Frame(self)
 66     row4.pack(fill="x")
 67     tk.Button(row4, text="关闭窗口", command=self.cancel).pack(side=tk.RIGHT)
 68   def cancel(self):
 69     self.destroy()
 70 
 71 '''
 72 data_set.txt 
 73 [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
 74 程序A    ["逗号次数","逗号停顿","句号次数","句号停顿" , "大段次数" , "大段停顿" , "全体音频文件播放次数" , "产生此音频"]
 75 [3,0,3,0,1,1,2,1]
 76 A 0 1 2 3
 77 [3,0,3,0,1,1,2,1,3,0,0,0,1,1,0,1]
 78 
 79 ["3","0","3","0","1","1","2","1","3","0","0","0","1","1","0","1"]
 80 
 81 [3,0,0,0,1,1,0,1]
 82 程序B    ["逗号次数","逗号停顿","句号次数","句号停顿" , "大段次数" , "大段停顿" , "全体音频文件播放次数" , "产生此音频"]
 83 '''
 84 
 85 class out_setconfig(tk.Toplevel):
 86   def __init__(self):
 87     super().__init__()
 88     self.title('参数设置')# 弹窗界面
 89     self.data_set_path = os.path.dirname(os.path.realpath(__file__))+"\data_set.txt"
 90     isExists = os.path.exists(self.data_set_path )
 91     if isExists == False:     #bug,之前没有设置
 92       self.setup_eror()
 93     else:
 94       self.setup_UI()
 95 
 96   def setup_eror(self):
 97     row1 = tk.Frame(self)
 98     row1.pack(fill="x")
 99     tk.Label(row1, text='程序第一次运行!

已进行参数初始化操作
').pack(side=tk.LEFT)
100     row4 = tk.Frame(self)
101     row4.pack(fill="x")
102     assist.write_txt_data(["3","0","3","0","1","1","2","1","3","0","1","0","2","0","0","1"],self.data_set_path )
103     tk.Button(row4, text="关闭窗口", command=self.cancel).pack(side=tk.RIGHT)
104   def setup_UI(self):
105     
106     self.A00 = tk.StringVar()
107     self.A01 = tk.StringVar()
108     self.A10 = tk.StringVar()
109     self.A11 = tk.StringVar()
110     self.A20 = tk.StringVar()
111     self.A21 = tk.StringVar()
112     self.A30 = tk.StringVar()
113     # self.chvarEn = tk.IntVar()
114     self.A31 = tk.IntVar()
115     
116     self.B00 = tk.StringVar()
117     self.B01 = tk.StringVar()
118     self.B10 = tk.StringVar()
119     self.B11 = tk.StringVar()
120     self.B20 = tk.StringVar()
121     self.B21 = tk.StringVar()
122     self.B30 = tk.StringVar()
123     self.B31 = tk.IntVar()
124     
125     data = assist.read_txt_data(self.data_set_path)
126     # print(data)
127     self.A00.set(data[0])
128     self.A01.set(data[1])
129     self.A10.set(data[2])
130     self.A11.set(data[3])
131     self.A20.set(data[4])
132     self.A21.set(data[5])
133     self.A30.set(data[6])
134     # d = int(data[7])
135     # self.A31.set(d)
136     
137     self.B00.set(data[8])
138     self.B01.set(data[9])
139     self.B10.set(data[10])
140     self.B11.set(data[11])
141     self.B20.set(data[12])
142     self.B21.set(data[13])
143     self.B30.set(data[14])
144     # d = int(data[15])
145     # self.B31.set(d)
146     # self.B31.set(int(data[15]))
147     
148     row1 = tk.Frame(self)
149     row1.pack(fill="x")
150     
151     tk.Label(row1,text='程序A',width=30 ).grid(row=0,column=0,columnspan=2)
152     tk.Label(row1,text='逗号次数:',width=15).grid(row=1,column=0)
153     tk.Label(row1,text='逗号停顿(秒):',width=15).grid(row=2,column=0)
154     tk.Label(row1,text='句号次数:',width=15).grid(row=3,column=0)
155     tk.Label(row1,text='句号停顿(秒)',width=15).grid(row=4,column=0)
156     tk.Label(row1,text='括号次数',width=15).grid(row=5,column=0)
157     tk.Label(row1,text='括号停顿(秒)',width=15).grid(row=6,column=0)
158     tk.Label(row1,text='全部音频次数',width=15).grid(row=7,column=0)
159     tk.Label(row1,text='是否生成音频',width=15).grid(row=8,column=0)
160     
161     
162     tk.Entry(row1, textvariable=self.A00, width=13).grid(row=1,column=1)
163     tk.Entry(row1, textvariable=self.A01, width=13).grid(row=2,column=1)
164     tk.Entry(row1, textvariable=self.A10, width=13).grid(row=3,column=1)
165     tk.Entry(row1, textvariable=self.A11, width=13).grid(row=4,column=1)
166     tk.Entry(row1, textvariable=self.A20, width=13).grid(row=5,column=1)
167     tk.Entry(row1, textvariable=self.A21, width=13).grid(row=6,column=1)
168     tk.Entry(row1, textvariable=self.A30, width=13).grid(row=7,column=1)
169     checkA = tk.Checkbutton(row1, text="播放", variable=self.A31)
170     checkA.select()
171     checkA.grid(column=1, row=8, sticky=tk.W)
172     
173     
174     tk.Label(row1,text='程序B',width=30 ).grid(row=0,column=2,columnspan=2)
175     tk.Label(row1,text='逗号次数:',width=15).grid(row=1,column=2)
176     tk.Label(row1,text='逗号停顿(秒):',width=15).grid(row=2,column=2)
177     tk.Label(row1,text='句号次数:',width=15).grid(row=3,column=2)
178     tk.Label(row1,text='句号停顿(秒)',width=15).grid(row=4,column=2)
179     tk.Label(row1,text='大段次数',width=15).grid(row=5,column=2)
180     tk.Label(row1,text='大段停顿(秒)',width=15).grid(row=6,column=2)
181     tk.Label(row1,text='全部音频次数',width=15).grid(row=7,column=2)
182     tk.Label(row1,text='是否生成音频',width=15).grid(row=8,column=2)
183     
184     
185     tk.Entry(row1, textvariable=self.B00, width=13).grid(row=1,column=3)
186     tk.Entry(row1, textvariable=self.B01, width=13).grid(row=2,column=3)
187     tk.Entry(row1, textvariable=self.B10, width=13).grid(row=3,column=3)
188     tk.Entry(row1, textvariable=self.B11, width=13).grid(row=4,column=3)
189     tk.Entry(row1, textvariable=self.B20, width=13).grid(row=5,column=3)
190     tk.Entry(row1, textvariable=self.B21, width=13).grid(row=6,column=3)
191     tk.Entry(row1, textvariable=self.B30, width=13).grid(row=7,column=3)
192     checkB = tk.Checkbutton(row1, text="播放", variable=self.B31)
193     checkB.select()
194     checkB.grid(column=3, row=8, sticky=tk.W)
195     self.A31.set(int(data[7]))
196     self.B31.set(int(data[15]))
197     
198     tk.Button(row1, text="取消", command=self.cancel, width=13).grid(row=9,column=0)
199     tk.Button(row1, text="确定", command=self.ok, width=13).grid(row=9,column=3)
200     
201   def ok(self):
202     self.userinfo_A = [self.A00.get(), self.A01.get(),self.A10.get(),self.A11.get(),self.A20.get(),self.A21.get(),self.A30.get(),self.A31.get()] # 设置数据
203     self.userinfo_B = [self.B00.get(), self.B01.get(),self.B10.get(),self.B11.get(),self.B20.get(),self.B21.get(),self.B30.get(),self.B31.get()] # 设置数据
204     # print(self.userinfo)
205     # print(self.userinfo_A[7])
206     # print(self.userinfo_B[7])
207     self.userinfo_A[7] = str(self.userinfo_A[7])
208     self.userinfo_B[7] = str(self.userinfo_B[7])
209     data = self.userinfo_A + self.userinfo_B
210     # print(data)
211     assist.write_txt_data(data,os.path.dirname(os.path.realpath(__file__))+"\data_set.txt")
212     self.destroy() # 销毁窗口
213   def cancel(self):
214     self.userinfo = None # 空!
215     self.destroy()
216     
217 ################################
218 class main_code(tk.Tk):
219   def __init__(self):
220     super().__init__()
221     self.audio_path = ""
222     self.run = True
223     self.vartext = tkinter.StringVar()
224     
225     self.txt=''
226     
227     
228     self.mark_text = '欢迎使用!'
229     self.insert_text = ''
230     self.vartext.set(self.mark_text)
231     self.filename = ""
232     self.audio_path = ""
233     self.audio_len = 0
234     self.data_play = []
235     self.sound = 0
236     self.title('音频标记')
237     self.setupUI()
238     
239   def setupUI(self):
240     
241     
242     row4 = tk.Frame(self)
243     row4.pack(fill="x")
244     
245     tk.Button(row4,text='导入文本',width=27,command=self.select).grid(row=0,column=0)
246     tk.Button(row4,text='设置文本',width=27,command=self.setup_config).grid(row=0,column=1)
247     tk.Button(row4,text='生成文本',width=27,command=self.lay).grid(row=0,column=2)
248     
249     label = tkinter.Label(row4,height=3,textvariable=self.vartext, bg='white', font=('黑体', 10), anchor='w').grid(row=1,column=0,columnspan=3)
250     
251     
252     entry1 = tkinter.Entry(row4,width=85)
253     entry1.bind('<Key>', self.insert_mark)
254     entry1.grid(row=2,column=0,columnspan=3)
255     self.insert_text = entry1.get()
256 
257 
258   def select(self):   #获取audio_path和audio_len
259     self.audio_path = tkinter.filedialog.askopenfilename(initialdir = 'C:\Users\Administrator\Desktop',filetypes=( ("txt or docx files", "*.txt;*.docx"),("All files", "*.*")))
260     if self.audio_path=="":
261       self.vartext.set('未导入任何文件')
262     else:
263       p,f=os.path.split(self.audio_path)
264       path = os.path.dirname(os.path.realpath(__file__)) + '\data\' + str(os.path.splitext(f)[0])
265       isExists = os.path.exists(path)
266       if not isExists:  #如果不存在这个目录
267         os.makedirs(path)  #创建一个新的路径
268         shutil.copyfile(self.audio_path,path+'\'+f)
269       if str(os.path.splitext(f)[1])=='.txt':
270         file_object = open(self.audio_path,'r', encoding='UTF-8')
271         try:
272           file_context = file_object.read()
273         finally:
274           file_object.close()
275         self.txt=file_context
276         self.vartext.set('已导入txt文本')
277       # print(1)
278       elif str(os.path.splitext(f)[1])=='.docx':
279         import docx
280         document = docx.Document(self.audio_path)
281         txt=''
282         for paragraph in document.paragraphs:
283           txt+=paragraph.text
284         self.txt=txt
285         self.vartext.set('已导入docx文本')
286       self.audio_path=path+'\'+f#更新数据路径
287     
288   def insert_mark(self,event):  #非主动线程
289     # while self.run:
290     # self.insert_text = self.insert_text + event.char
291     pass
292   def lay(self):
293     # txt=entry1.get()
294     print(self.insert_text)
295     print(123)
296     
297     '''
298     self.vartext.set('正在生成文本标记文件')
299     # data_set = assist.read_txt_data(os.path.dirname(os.path.realpath(__file__))+"\data_set.txt")
300     mark_set=[1,1,0,1,1,0,1,1]
301     import re
302     txt_comma=re.split(u'。',self.txt[:-1])
303     p,f=os.path.split(self.audio_path)
304     # print(p)
305     # print(f)
306     for i in range(len(txt_comma)):
307       txt_comma[i]=txt_comma[i].split(',')
308     
309     # print(txt_comma)
310     if mark_set[0]==1:
311       txt_A=''
312       for i in txt_comma:
313         txt_A=txt_A+out_comma(i,mark_set[1],mark_set[2])
314       # print(txt_A)
315       fobj=open(p+'\'+str(os.path.splitext(f)[0])+'_A'+str(os.path.splitext(f)[1]),'w')
316       fobj.write(txt_A)
317       fobj.close()
318     
319     if mark_set[4]==1:
320       txt_B=''
321       for i in txt_comma:
322         txt_B=txt_B+out_comma(i,mark_set[5],mark_set[6])
323       # print(txt_B)
324       fobj=open(p+'\'+str(os.path.splitext(f)[0])+'_B'+str(os.path.splitext(f)[1]),'w')
325       fobj.write(txt_B)
326       fobj.close()
327     '''
328     
329     
330     
331     
332     
333   def setup_config(self):
334     res = self.ask_userinfo()
335     if res is None: return
336   def ask_userinfo(self):
337     inputDialog = out_setconfig()
338     self.wait_window(inputDialog) # 这一句很重要!!!
339 
340 
341 
342 if __name__ == '__main__':
343   app = main_code()
344   app.mainloop()
原文地址:https://www.cnblogs.com/Mufasa/p/10481377.html