• 多线程的音频打标记的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()
  • 相关阅读:
    找零问题-完全背包
    可同时在nodejs和浏览器端使用的websocket
    C++ vector 比较大小
    npm ERR! Unexpected token in JSON at position 0 while parsing near '<HTML> 解决办法
    C/C++宏定义中#与##区别
    解析日志工具。
    3
    2
    dssfsfsfs
    android获取USB设备的名称
  • 原文地址:https://www.cnblogs.com/Mufasa/p/10481377.html
Copyright © 2020-2023  润新知