#!bin/bash/python # -*- coding=utf-8 -*- from __future__ import division import threading import wx import wx.media import os.path, os, gc, sys, pyaudio import wave, numpy, codecs, time import pylab as pl import pyaudio #import win32gui from matplotlib.ticker import MultipleLocator, FormatStrFormatter import sys from wx.lib.pubsub import pub reload(sys) wavCount = 1 input_filename = "input.wav" # 麦克风采集的语音输入 input_filepath = "./" # 输入文件的path in_path = input_filepath + input_filename global_frames = [] xmajorLocator = MultipleLocator(0.5) # 将x主刻度标签设置为0.5的倍数 xmajorFormatter = FormatStrFormatter('%1.1f') # 设置x轴标签文本的格式 xminorLocator = MultipleLocator(0.05) # 将x轴次刻度标签设置为0.05的倍数 class MyFrame(wx.Frame): #初始化全部界面 def __init__(self, wavlist, recList): self.wavTime = 0.000 self.wavLength = 0.000 self.labelcount = 0 self.choosenItem = 0 self.labelPosition = 0 self.cutCount = 1 self.wavList = [] self.recList = [] self.labellist = [] self.labelPos = [] self.tempwavlist = [] self.wavList = wavlist self.recList = recList # self.wavfilepath = wavlist[0][1] # self.recTextStr = recList[0][1] self.wavfilepath = wavlist[0] self.recTextStr = recList[0] print ("wav:", self.wavfilepath) print ("rec:", self.recTextStr) wx.Frame.__init__(self,None,size=(1920,1080)) self.sp=wx.SplitterWindow(self,style=wx.SP_3D) self.mainPanel=wx.Panel(self.sp) self.listPanel=wx.Panel(self.sp) self.sp2=wx.SplitterWindow(self.mainPanel) self.annoPanel=wx.Panel(self.sp2) self.subPanel=wx.Panel(self.sp2) self.box=wx.BoxSizer(wx.VERTICAL) self.box.Add(self.sp2,1,wx.EXPAND) self.sp3=wx.SplitterWindow(self.subPanel) self.cutPanel=wx.Panel(self.sp3) self.statisticPanel=wx.Panel(self.sp3) self.box2=wx.BoxSizer(wx.VERTICAL) self.box2.Add(self.sp3,1,wx.EXPAND) self.sp4=wx.SplitterWindow(self.statisticPanel) self.wavPanel=wx.Panel(self.sp4) # upgrade # self.upwavPanel=wx.Panel(self.sp4) self.infoPanel=wx.Panel(self.sp4) self.box3=wx.BoxSizer(wx.VERTICAL) self.box3.Add(self.sp4,1,wx.EXPAND) self.sp5=wx.SplitterWindow(self.infoPanel) self.labelPanel=wx.Panel(self.sp5) self.aaaPanel=wx.Panel(self.sp5) self.box4=wx.BoxSizer(wx.VERTICAL) self.box4.Add(self.sp5,1,wx.EXPAND) self.sp6=wx.SplitterWindow(self.aaaPanel) self.bbbPanel=wx.Panel(self.sp6) self.cccPanel=wx.Panel(self.sp6) self.box5=wx.BoxSizer(wx.VERTICAL) self.box5.Add(self.sp6,1,wx.EXPAND) self.mainPanel.SetSizer(self.box) self.subPanel.SetSizer(self.box2) self.statisticPanel.SetSizer(self.box3) self.infoPanel.SetSizer(self.box4) self.aaaPanel.SetSizer(self.box5) self.cutPanel.SetBackgroundColour("white") self.bbbPanel.SetBackgroundColour("white") self.cccPanel.SetBackgroundColour("white") print ("debug: wavfilepath:", self.wavfilepath) self.drawBackJpg(str(self.wavfilepath)) # 创建布局 self.CreateListUI(wavlist) self.CreateMainUI(recList) self.CreateWavUI() self.CreateLabelListUI() # 布局 self.sp.SplitVertically(self.listPanel,self.mainPanel,150) self.sp2.SplitHorizontally(self.annoPanel,self.subPanel,300) self.sp3.SplitHorizontally(self.cutPanel,self.statisticPanel,110) self.sp4.SplitHorizontally(self.wavPanel,self.infoPanel,280) self.sp5.SplitHorizontally(self.labelPanel,self.aaaPanel,100) self.sp6.SplitVertically(self.bbbPanel,self.cccPanel,820) self.Bind(wx.EVT_LIST_ITEM_SELECTED,self.OnListBox,self.list) self.wavPanel.Bind(wx.EVT_PAINT, self.OnPaint) self.wavPanel.Bind(wx.EVT_ERASE_BACKGROUND,self.OnErasePass) self.wavPanel.Bind(wx.EVT_MOTION,self.OnMove) self.wavPanel.Bind(wx.EVT_LEFT_DOWN,self.OnLeftDown) self.wavPanel.Bind(wx.EVT_LEFT_UP,self.OnDrawRec) # self.upwavPanel.Bind(wx.EVT_PAINT, self.OnPaint) # self.upwavPanel.Bind(wx.EVT_ERASE_BACKGROUND,self.OnErasePass) # self.upwavPanel.Bind(wx.EVT_MOTION,self.OnMove) # self.upwavPanel.Bind(wx.EVT_LEFT_DOWN,self.OnLeftDown) # self.upwavPanel.Bind(wx.EVT_LEFT_UP,self.OnDrawRec) self.labelPanel.Bind(wx.EVT_MOTION,self.OnLabelMove) self.labelPanel.Bind(wx.EVT_LEFT_UP,self.OnLabelDrawLine) self.labelPanel.Bind(wx.EVT_PAINT,self.OnLabelPaint) self.labelPanel.Bind(wx.EVT_ERASE_BACKGROUND,self.OnErasePass) #左侧列表的点击事件 def OnListBox(self,event): # self.sp.Unsplit() if self.timer: self.timer.Stop() # del self.timer self.cutCount=1 #获取点击对象 index = event.GetIndex() self.choosenItem = index data = self.list.GetItem(index,0) tuple_temp = self.wavList[int(data.GetText())-1] # self.wavfilepath = tuple_temp[1] # self.recTextStr = self.recList[int(data.GetText())-1][1] self.wavfilepath = self.wavfilepath self.recTextStr = self.recTextStr print ("wav:", self.wavfilepath) print ("rec:", self.recTextStr) self.OnFreshUI() #刷新界面 def OnFreshUI(self): self.InitMedia() self.rec_tc.SetValue(self.recTextStr) self.label_tc.SetValue("") self.anno_tc.SetValue("") self.wavpath_ST.SetLabel(u"当前操作文件 : "+ self.wavfilepath) self.drawBackJpg(str(self.wavfilepath)) self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnTimer) self.timer.Start(100) self.cutPanel.Refresh() self.annoPanel.Refresh() self.mainPanel.Refresh() #绘制音频波形的paint事件的回调函数 def OnPaint(self, event): brush = wx.Brush("white") img = wx.Bitmap("mic4_output.png") dc = wx.BufferedPaintDC(self.wavPanel) dc.SetBackground(brush) # dc.Clear() dc.DrawBitmap(img,-172,0) #据说可以解决屏闪问题 def OnErasePass(self, event): pass #-------------------------------------------------- #列表界面的UI创建 def CreateListUI(self,wavlist): self.ListBox = wx.BoxSizer(wx.HORIZONTAL) self.list = wx.ListCtrl(self.listPanel, -1, style=wx.LC_REPORT) self.list.InsertColumn(0, u'序号', width=50) self.list.InsertColumn(1, u'完成情况', width=150) for i in wavlist: index = self.list.InsertStringItem(sys.maxint, str(i[0])) self.list.SetStringItem(index, 1, u"未完成") self.ListBox.Add(self.list,1,wx.EXPAND) self.listPanel.SetSizerAndFit(self.ListBox) #-------------------------------------------------- #标注界面的UI创建 #wx.media的load初始化 def InitMedia(self): try: self.mc = wx.media.MediaCtrl(self.mainPanel, style=wx.SIMPLE_BORDER) except NotImplementedError: self.Destroy() raise if not self.mc.Load(self.wavfilepath): wx.MessageBox("Unable to load: Unsupported format?","ERROR", wx.ICON_ERROR | wx.OK) else: print "load success" print self.mc.Length() self.slider.SetRange(0, self.mc.Length()) #self.mc.Pause=0 #初始完成后各按键才可使用 def OnMediaLoaded(self, evt): self.buttonPlay.Enable() #创建标注界面(播放器,文本框) def CreateMainUI(self,recList): font=wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT) font.SetPointSize(12) font20=wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT) font20.SetPointSize(16) self.annoPanel.SetBackgroundColour("white") self.MainSizer=wx.GridBagSizer(0,0) self.num_st=wx.StaticText(self.annoPanel,label="") self.num_st.SetFont(font) self.MainSizer.Add(self.num_st,pos=(0,0),span=(1,2),flag=wx.ALL,border=10) self.num1=wx.StaticText(self.annoPanel,label="",style=wx.ALIGN_CENTER) self.num1.SetFont(font) self.MainSizer.Add(self.num1,pos=(2,0),span=(1,2),flag=wx.ALL,border=10) self.wav_st=wx.StaticText(self.annoPanel,label=u"音频") self.wav_st.SetFont(font) self.MainSizer.Add(self.wav_st,pos=(0,2),span=(1,5),flag=wx.EXPAND|wx.ALL,border=10) self.MainSizer.AddGrowableCol(6,1) self.buttonPlay=wx.Button(self.annoPanel,wx.ALL,label=u"&▷ F1") self.buttonPause=wx.Button(self.annoPanel,label=u"&‖ Esc") self.buttonStop=wx.Button(self.annoPanel,label=u"&■ Ctrl-S") self.Bind(wx.EVT_BUTTON,self.playWav,self.buttonPlay) #accelTb1 = wx.AcceleratorTable([wx.ACCEL_CTRL,ord('S'),self.buttonPlay.GetId()]) #self.SetAcceleratorTable(accelTb1) self.Bind(wx.EVT_BUTTON,self.pauseWav,self.buttonPause) self.Bind(wx.EVT_BUTTON,self.stopWav,self.buttonStop) self.MainSizer.Add(self.buttonPlay,pos=(2,2),flag=wx.ALL,border=10) self.MainSizer.Add(self.buttonPause,pos=(2,3),flag=wx.ALL,border=10) self.MainSizer.Add(self.buttonStop,pos=(2,4),flag=wx.ALL,border=10) self.slider=wx.Slider(self.annoPanel,-1,0,0,1) self.slider.SetMinSize((150,-1)) self.MainSizer.Add(self.slider,pos=(3,2),span=(1,3),flag=wx.ALL|wx.EXPAND,border=10) self.Bind(wx.EVT_SLIDER,self.OnSeek,self.slider) self.timer=wx.Timer(self) self.Bind(wx.EVT_TIMER,self.OnTimer) self.timer.Start(100) self.rec_st=wx.StaticText(self.annoPanel,label=u"语音识别结果") self.rec_st.SetFont(font) self.MainSizer.Add(self.rec_st,pos=(0,7),span=(1,4),flag=wx.EXPAND|wx.ALL,border=10) self.MainSizer.AddGrowableCol(10,1) self.rec_tc=wx.TextCtrl(self.annoPanel,value=self.recTextStr,style=wx.TE_READONLY|wx.TE_MULTILINE) self.MainSizer.Add(self.rec_tc,pos=(2,7),span=(4,4),flag=wx.EXPAND|wx.ALL,border=10) self.label_st=wx.StaticText(self.annoPanel,label=u"音频标记") self.label_st.SetFont(font) self.MainSizer.Add(self.label_st,pos=(0,12),flag=wx.ALL,border=10) self.label_tc=wx.TextCtrl(self.annoPanel,style=wx.TE_MULTILINE) self.MainSizer.Add(self.label_tc,pos=(2,12),span=(4,1),flag=wx.EXPAND|wx.ALL,border=10) self.anno_st=wx.StaticText(self.annoPanel,label=u"文本标注") self.anno_st.SetFont(font) self.MainSizer.Add(self.anno_st,pos=(0,13),span=(1,4),flag=wx.EXPAND|wx.ALL,border=10) self.MainSizer.AddGrowableCol(16,1) self.anno_tc=wx.TextCtrl(self.annoPanel,style=wx.TE_MULTILINE) self.MainSizer.Add(self.anno_tc,pos=(2,13),span=(4,4),flag=wx.EXPAND|wx.ALL,border=10) self.line=wx.StaticLine(self.annoPanel) self.MainSizer.Add(self.line,pos=(1,0),span=(1,18),flag=wx.EXPAND|wx.BOTTOM,border=10) self.save_button=wx.Button(self.annoPanel,label=u"保存") self.clear_button=wx.Button(self.annoPanel,label=u"清空") self.MainSizer.Add(self.save_button,pos=(2,17),flag=wx.ALL,border=10) self.MainSizer.Add(self.clear_button,pos=(3,17),flag=wx.ALL,border=10) self.save_button.Bind(wx.EVT_BUTTON,self.ButtonSave) self.clear_button.Bind(wx.EVT_BUTTON,self.ButtonClear) self.InitMedia() self.annoPanel.SetSizerAndFit(self.MainSizer) #播放器进度条的定时器事件回调 def OnSeek(self, evt): offset = self.slider.GetValue() self.mc.Seek(offset) def OnTimer(self, evt): offset = self.mc.Tell() self.slider.SetValue(offset) #保存结果 def ButtonSave(self,event): with codecs.open('anno_file','w','gbk') as f: anno_text = self.anno_tc.GetValue() print anno_text f.write(anno_text) self.list.SetStringItem(self.choosenItem,1,u"完成") self.list.SetItemBackgroundColour(self.choosenItem,"green") #删除中间操作的temp文件,并对最后保存的文件重命名 if len(self.tempwavlist) != 0: lastfile=self.tempwavlist[-1] self.tempwavlist.pop() for i in self.tempwavlist: print i os.remove(i) data = self.list.GetItem(self.choosenItem,0) tuple_temp = self.wavList[int(data.GetText())-1] print tuple_temp path_str=os.path.split(tuple_temp[1]) wavname=path_str[1].split('.') newname=wavname[0]+"_nocut."+wavname[1] newpath=os.path.join(path_str[0],newname) print newpath os.rename(tuple_temp[1],newpath) os.rename(lastfile,tuple_temp[1]) #清空标注文本框 def ButtonClear(self,event): self.anno_tc.SetValue("") self.label_tc.SetValue("") #播放器播放 def playWav(self,event): if not self.mc.Play(): wx.MessageBox("Unable to Play media : Unsupported format?","ERROR",wx.ICON_ERROR | wx.OK) else: print self.mc.Length() self.slider.SetRange(0, self.mc.Length()) #播放器暂停 def pauseWav(self,event): #if self.mc.Pause == 0: # pygame.mixer.music.pause() # self.buttonPause.SetLabel(u"▷") # self.mc.Pause = 1 #else: # pygame.mixer.music.unpause() # self.buttonPause.SetLabel(u"‖") # self.mc.Pause = 0 self.mc.Pause() #播放器停止 def stopWav(self,event): self.mc.Stop() #-------------------------------------------------- #标签操作的UI创建 def OnLabelPaint(self,event): brush=wx.Brush("white") dc2=wx.PaintDC(self.labelPanel) dc2.SetBackground(brush) dc2.Clear() dc2.DrawRectangle(79,30,1550,40) for i in self.labelPos: print i dc4=wx.PaintDC(self.labelPanel) dc4.DrawLine(i,30,i,70) #-------------------------------------------------- #音频操作的UI创建 def CreateWavUI(self): self.haveDraw = 0 self.haveCut = 0 self.wavpath_ST = wx.StaticText(self.cutPanel,-1,u"当前操作文件 : "+self.wavfilepath,pos=(40,10)) wx.StaticText(self.cutPanel,-1,u"时间 : ",pos=(40,60)) wx.StaticText(self.cutPanel,-1,u"坐标:",pos=(600,60)) self.labelButton=wx.Button(self.cutPanel,-1,"label",pos=(200,60)) self.cutButton=wx.Button(self.cutPanel,-1,"delete",pos=(300,60)) self.playButton=wx.Button(self.cutPanel,-1,"play",pos=(400,60)) self.posCtrl=wx.TextCtrl(self.cutPanel,-1,"",pos=(640,60)) self.timeCtrl=wx.TextCtrl(self.cutPanel,-1,"",pos=(80,60)) self.Bind(wx.EVT_BUTTON,self.OnLabelCreate,self.labelButton) self.Bind(wx.EVT_BUTTON,self.cutWav,self.cutButton) self.Bind(wx.EVT_BUTTON,self.PlayWav,self.playButton) self.testbutton=wx.Button(self.cutPanel, -1, "revoke", pos=(500,60)) self.Bind(wx.EVT_BUTTON,self.testtest, self.testbutton) # 录音 self.recordBtn = wx.Button(self.cutPanel, -1, "Record", pos=(750, 61)) self.Bind(wx.EVT_BUTTON, self.OnPaint2, self.recordBtn) # 接收消息, pub.subscribe(self.record_and_drawBackJpg, "update") # 待实现--还没写 def CreateUpWavUI(self): self.uphaveDraw = 0 self.uphaveCut = 0 self.upwavpath_ST = wx.StaticText(self.upcutPanel,-1,u"当前操作文件 : "+self.wavfilepath,pos=(40,10)) wx.StaticText(self.upcutPanel, -1, u"时间 : ", pos = (40,60)) wx.StaticText(self.upcutPanel, -1, u"坐标:", pos = (600,60)) self.uplabelButton=wx.Button(self.upcutPanel,-1,"label",pos=(200,60)) self.upcutButton=wx.Button(self.upcutPanel,-1,"delete",pos=(300,60)) self.upplayButton=wx.Button(self.upcutPanel,-1,"play",pos=(400,60)) self.upposCtrl=wx.TextCtrl(self.upcutPanel,-1,"",pos=(640,60)) self.uptimeCtrl=wx.TextCtrl(self.upcutPanel,-1,"",pos=(80,60)) self.Bind(wx.EVT_BUTTON,self.OnLabelCreate,self.uplabelButton) self.Bind(wx.EVT_BUTTON,self.cutWav,self.upcutButton) self.Bind(wx.EVT_BUTTON,self.PlayWav,self.upplayButton) self.uptestbutton=wx.Button(self.cutPanel,-1,"revoke",pos=(500,60)) self.Bind(wx.EVT_BUTTON,self.testtest,self.uptestbutton) self.upecordBtn = wx.Button(self.cutPanel, -1, "Record", pos=(750, 61)) self.Bind(wx.EVT_BUTTON, self.OnPaint2, self.uprecordBtn) #左键按下事件的回调函数,绘制一条线 def OnLeftDown(self,event): self.wavPanel.Refresh() self.firstPos=event.GetPosition() #haveDraw为判断是否左键按下后是否有拖动动作 if self.haveDraw == 1: self.haveDraw = 0 dc=wx.BufferedDC(wx.ClientDC(self.wavPanel))#,self.wavPanel # dc=wx.BufferedPaintDC(self.wavPanel) dc.DrawLine(self.firstPos.x, 30, self.firstPos.x, 270) #左键松开事件的回调函数,绘制选中的矩形框 def OnDrawRec(self,event): #haveDraw为判断是否左键按下后是否有拖动拖动动作 if self.haveDraw == 1: dc=wx.BufferedDC(wx.ClientDC(self.wavPanel)) #dc=wx.BufferedPaintDC(self.wavPanel) brush=wx.Brush(wx.Colour(255,23,140)) dc.SetBrush(brush) dc.SetBrush(wx.Brush(wx.Colour(255,23,140),wx.BDIAGONAL_HATCH)) dc.DrawRectangle(self.firstPos.x,30,self.secondPos.x-self.firstPos.x,240) else: #dc=wx.PaintDC(self.wavPanel) dc=wx.BufferedDC(wx.ClientDC(self.wavPanel))#,self.wavPanel dc.DrawLine(self.firstPos.x,30,self.firstPos.x,270) def OnMove(self, event): pos=event.GetPosition() self.posCtrl.SetValue("%s,%s" %(pos.x,pos.y)) #在左键按下和拖动下绘制选中的矩形框 if event.Dragging() and event.LeftIsDown(): self.secondPos=pos self.wavPanel.Refresh() dc = wx.BufferedDC(wx.ClientDC(self.wavPanel)) #dc=wx.BufferedPaintDC(self.wavPanel) brush=wx.Brush(wx.Colour(100,100,100)) dc.SetBrush(brush) dc.SetBrush(wx.Brush(wx.Colour(255,23,140),wx.BDIAGONAL_HATCH)) if self.firstPos.x<80 : self.firstPos = 250 if self.firstPos.x>1630 : self.firstPos = 1630 if self.firstPos.x<80 : self.firstPos = 80 if self.firstPos.x>1630 : self.firstPos = 1630 else: dc.DrawRectangle(self.firstPos.x,30,self.secondPos.x-self.firstPos.x,240) self.haveDraw = 1 #标签界面 def OnLabelMove(self,event): pos=event.GetPosition() #在按下左键拖动后绘制两条指示线 if event.Dragging() and event.LeftIsDown(): self.labelPanel.Refresh() self.wavPanel.Refresh() self.labelPosition=event.GetPosition() a=self.wavTime*self.calPosition(pos.x,self.wavParams,self.wavLength,1) self.timeCtrl.SetValue("%.3fs"%a) dc=wx.ClientDC(self.labelPanel) dc.DrawLine(self.labelPosition.x,30,self.labelPosition.x,70) dc3=wx.BufferedDC(wx.ClientDC(self.wavPanel)) #dc3=wx.BufferedPaintDC(self.wavPanel) dc3.DrawLine(self.labelPosition.x,30,self.labelPosition.x,270) #松开左键后绘制两条指示线 def OnLabelDrawLine(self,event): self.labeltime=self.timeCtrl.GetValue() dc1 = wx.ClientDC(self.labelPanel) dc1.DrawLine(self.labelPosition.x, 30, self.labelPosition.x, 70) dc3 = wx.BufferedDC(wx.ClientDC(self.wavPanel)) #dc3=wx.BufferedPaintDC(self.wavPanel) dc3.DrawLine(self.labelPosition.x, 30, self.labelPosition.x,270) #创建输入标签的文本框 def OnLabelCreate(self,event): self.labelPos.append(self.labelPosition.x) self.labelPos.sort() self.labelCtrl=wx.TextCtrl(self.labelPanel,-1,"",pos=(self.labelPosition.x-93,33),size=(90,33),style=wx.TE_PROCESS_ENTER) self.labelCtrl.Bind(wx.EVT_TEXT_ENTER,self.TestEnter,self.labelCtrl) self.labellist.append((str(self.labeltime),self.labelCtrl)) #标签文本框的enter建回调函数,若有值则保存,若无值按下回车则删除 def TestEnter(self,event): self.labellist.sort() notfind=0 enter_str=event.GetString() label=event.GetEventObject() for j in range(len(self.labellist)): if label == self.labellist[j][1]: labelindex = j itemtime = self.labellist[j][0] if enter_str == "": for i in range(len(self.labellist)): if label == self.labellist[i][1]: del self.labellist[i] del self.labelPos[i] self.showlist.DeleteItem(i) label.Destroy() break else: if self.showlist.GetItemCount() != 0: for i in range(self.showlist.GetItemCount()): if self.showlist.GetItem(i,0).GetText() == itemtime: self.showlist.SetStringItem(i, 1, label.GetValue()) notfind=1 break if notfind == 0: index = self.showlist.InsertStringItem(labelindex, itemtime) self.showlist.SetStringItem(index, 1, label.GetValue()) else: index = self.showlist.InsertStringItem(labelindex, str(self.labellist[0][0])) self.showlist.SetStringItem(index, 1, self.labellist[0][1].GetValue()) self.bbbPanel.Refresh() #创建标签显示的list界面,显示当前插入的标签的时间和内容 def CreateLabelListUI(self): self.listbox=wx.BoxSizer(wx.HORIZONTAL) self.showlist = wx.ListCtrl(self.bbbPanel, -1, style=wx.LC_REPORT|wx.LC_SORT_ASCENDING)#wx.LC_REPORT| self.showlist.InsertColumn(0, u'时间', width=200) self.showlist.InsertColumn(1, u'标签', width=410) for i in self.labellist: index = self.showlist.InsertStringItem(sys.maxint, str(i[0])) label_str = i[1].GetValue() print label_str self.showlist.SetStringItem(index, 1, label_str) self.listbox.Add(self.showlist,1,wx.EXPAND) self.bbbPanel.SetSizerAndFit(self.listbox) self.bbbPanel.Refresh() #插销上一步的剪辑操作,实际为读取再前一次的缓存音频 def testtest(self,event): print self.labellist self.cutCount = self.cutCount - 2 if self.cutCount == 0: self.cutCount = 1 data = self.list.GetItem(self.choosenItem,0) tuple_temp = self.wavList[int(data.GetText())-1] self.wavfilepath=tuple_temp[1] if len(self.tempwavlist) != 0: self.tempwavlist.pop() print self.tempwavlist # self.cutCount = self.cutCount + 1 self.drawBackJpg(self.wavfilepath) self.InitMedia() self.wavPanel.Refresh() else: print os.path.split(self.wavfilepath) path_str=os.path.split(self.wavfilepath) cutfile="temp"+str(self.cutCount)+".wav" temppath=os.path.join(path_str[0],cutfile) print temppath self.cutCount = self.cutCount + 1 self.wavfilepath=temppath self.tempwavlist.pop() print self.tempwavlist self.drawBackJpg(self.wavfilepath) self.InitMedia() self.wavPanel.Refresh() #播放选中部分音频 def PlayWav(self,event): f = wave.open(self.wavfilepath,"rb") print "1.pos:",self.firstPos.x,"2.pos",self.secondPos.x if self.firstPos.x < self.secondPos.x: x1=self.firstPos.x x2=self.secondPos.x else: x2=self.firstPos.x x1=self.secondPos.x print "x1:",x1,"x2",x2 params = f.getparams() nchannels, sampwidth, framerate, nframes = params[:4] str_data = f.readframes(nframes) str_length = len(str_data) print "str length = ",str_length a=self.calPosition(x1,params,str_length,1) b=self.calPosition(x2,params,str_length,1) atime=round(a*self.wavTime,2) btime=round(b*self.wavTime,2) print atime,btime alength=int(a*self.mc.Length()) print alength self.mc.Seek(alength) self.mc.Play() time.sleep(btime-atime) self.mc.Stop() # str_test=str_data[a:b] # print len(str_test) # p = pyaudio.PyAudio() # print f.getnchannels(); # print p.get_format_from_width(f.getsampwidth()) # print f.getframerate() # stream = p.open(format = p.get_format_from_width(f.getsampwidth()), # channels = f.getnchannels(), # rate = f.getframerate(), # output = True) # print "===" # stream.write(str_test) # stream.stop_stream() # stream.close() # f.close() # p.terminate() #剪辑音频 def cutWav(self,event): print self.wavfilepath f = wave.open(self.wavfilepath,"rb") print os.path.split(self.wavfilepath) path_str=os.path.split(self.wavfilepath) cutfile="temp"+str(self.cutCount)+".wav" temppath=os.path.join(path_str[0],cutfile) print ("debug: temppath:", temppath) self.cutCount = self.cutCount + 1 self.tempwavlist.append(temppath) print self.tempwavlist self.wavfilepath = temppath print "1.pos:",self.firstPos.x,"2.pos",self.secondPos.x if self.firstPos.x < self.secondPos.x: x1=self.firstPos.x x2=self.secondPos.x else: x2=self.firstPos.x x1=self.secondPos.x print "x1:",x1,"x2",x2 params = f.getparams() nchannels, sampwidth, framerate, nframes = params[:4] str_data = f.readframes(nframes) str_length = len(str_data) print "str length",str_length a=self.calPosition(x1,params,str_length,0) b=self.calPosition(x2,params,str_length,0) wf = wave.open(self.wavfilepath,"wb") wf.setnchannels(nchannels) wf.setsampwidth(sampwidth) wf.setframerate(framerate) str_test=str_data[0:a]+str_data[b:str_length] print len(str_test) wf.writeframes(str_test) wf.close() self.drawBackJpg(self.wavfilepath) self.InitMedia() self.wavPanel.Refresh() #计算当前坐标的在音频中的相对位置 def calPosition(self,x,params,str_length,type): nchannels, sampwidth, framerate, nframes = params[:4] print nchannels, sampwidth, framerate, nframes bytecount=int(nchannels*sampwidth) print bytecount real_length = int(((str_length//bytecount)/framerate)/((((str_length//bytecount)/framerate)//0.5+1)*0.5)*1550) print real_length aa=(x-79)/real_length print aa a = ((str_length//bytecount)//1000)*(int(((x-79)/real_length)*1000))*bytecount print a if type == 1: # print "aa ",int(aa) return aa else: # print "a",int(a) return int(a) #绘制波形图片 def drawBackJpg(self, path): print ("debug path:", path) f = wave.open(path, "r") params = f.getparams() nchannels, sampwidth, framerate, nframes = params[:4] str_data = f.readframes(nframes) f.close() str_length = len(str_data) self.wavLength = str_length self.wavParams = params time_limit=(((str_length//(nchannels*sampwidth)/framerate)//0.5+1)*0.5) wave_data = numpy.fromstring(str_data,dtype = numpy.short) wave_data.shape = -1, int(params[0]) wave_data = wave_data.T time = numpy.arange(0, nframes)*(1.0/framerate) len_time = len(time) time = time[0:len_time] self.wavTime = len(time)/16000 axes = pl.subplot(111) axes.plot(time, wave_data[0], 'cornflowerblue') axes.xaxis.set_ticks_position('top') axes.xaxis.set_major_locator(xmajorLocator) axes.xaxis.set_minor_locator(xminorLocator) axes.xaxis.grid(True, which='minor') axes.set_xlim([0.0, time_limit]) axes.set_yticks([]) fig = pl.gcf() fig.set_size_inches(20, 3) fig.savefig('mic4_output.png', dpi=100) # gc.collect() pl.close() def record_and_drawBackJpg(self, msg): global input_filename self.wavfilepath = input_filename self.OnFreshUI() # 里面执行了, self.drawBackJpg(self.wavfilepath) # 重绘 brush = wx.Brush("white") img = wx.Bitmap("mic4_output.png") dc = wx.ClientDC(self.wavPanel) dc.Clear() dc.SetBackground(brush) dc.DrawBitmap(img, -172, 0) def OnPaint2(self, event): mythread = threading.Thread(target=self.thread_paint) mythread.start() event.GetEventObject().Disable() def thread_paint(self): len = int(11025 / 256 * 20) for i in range(len): self.get_audio() # 实现一边录音,一边绘图 # 绘图 # self.record_and_drawBackJpg() def get_audio(self): global in_path global global_frames global wavCount CHUNK = 256 FORMAT = pyaudio.paInt16 CHANNELS = 1 # 声道数 RATE = 11025 # 采样率 RECORD_SECONDS = 3 # 每次录音 5s WAVE_OUTPUT_FILENAME = in_path p = pyaudio.PyAudio() stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) print("*"*10, u"start record: please speak in 5s") frames = global_frames for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)): data = stream.read(CHUNK) frames.append(data) print("*"*10, u"speak over ") global_frames = frames stream.stop_stream() stream.close() p.terminate() # ./input.wav wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb') wf.setnchannels(CHANNELS) wf.setsampwidth(p.get_sample_size(FORMAT)) wf.setframerate(RATE) # 写wav wf.writeframes(b''.join(global_frames)) wf.close() wavCount = wavCount + 1 if wavCount == 10: global_frames = [] wavCount = 0 # 和主线程之间进行通信, 发送更新图片消息 wx.CallAfter(pub.sendMessage, "update", msg=wavCount) # start class LoginWin(wx.Frame): def __init__(self,parent,title): super(LoginWin, self).__init__(parent, title=title, size=(590,150)) self.InitUI() self.Centre() self.Show() def InitUI(self): self.LoginPanel = wx.Panel(self) hbox = wx.BoxSizer(wx.HORIZONTAL) fgs = wx.FlexGridSizer(2, 3, 10,10) wavListST = wx.StaticText(self.LoginPanel, label = u"音频列表") recTextST = wx.StaticText(self.LoginPanel, label = u"识别文本") ChooseButton1 = wx.Button(self.LoginPanel, label=u"选择") ChooseButton2 = wx.Button(self.LoginPanel, label=u"选择") ChooseButton1.Bind(wx.EVT_BUTTON, self.ReadList) ChooseButton2.Bind(wx.EVT_BUTTON, self.ReadText) self.ListTC= wx.TextCtrl(self.LoginPanel, style=wx.TE_READONLY) self.TextTC = wx.TextCtrl(self.LoginPanel, style=wx.TE_READONLY) fgs.AddMany([(wavListST), (self.ListTC, 1, wx.EXPAND), (ChooseButton1), (recTextST),(self.TextTC, 1, wx.EXPAND), (ChooseButton2)]) fgs.AddGrowableCol(1, 1) hbox.Add(fgs, proportion = 1, flag = wx.ALL|wx.EXPAND, border = 10) OkButton = wx.Button(self.LoginPanel, label="OK") CancelButton = wx.Button(self.LoginPanel, label="CANCEL") OkButton.Bind(wx.EVT_BUTTON, self.OnClick) sizer = wx.GridBagSizer(hgap=10, vgap=10) sizer.Add(OkButton, pos=(0, 20), flag=wx.ALL) sizer.Add(CancelButton, pos=(0, 21), flag=wx.ALL) bsizer = wx.BoxSizer(wx.VERTICAL) bsizer.Add(hbox,0,wx.EXPAND,10) bsizer.Add(sizer,0,wx.EXPAND,10) self.LoginPanel.SetSizerAndFit(bsizer) sizer.SetSizeHints(self.LoginPanel) def ReadList(self, event): dlg = wx.FileDialog(self, message=u"选择音频列表文件select ",defaultDir=os.getcwd(),defaultFile="",style=wx.OPEN|wx.CHANGE_DIR) self.wavList = ["mic4.wav"] if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.ListTC.SetValue(path) print ("Debug: ", path) # self.wavList = self.ReadFilePath(path) dlg.Destroy() def ReadText(self, event): dlg = wx.FileDialog(self, message=u"选择识别结果文本",defaultDir=os.getcwd(), defaultFile="",style = wx.OPEN|wx.CHANGE_DIR) self.recText = ["recog.txt"] if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.TextTC.SetValue(path) # self.recText = se0lf.ReadFilePath(path) print ("debug: rectext:", self.recText) dlg.Destroy() def ReadFilePath(self,path): tempList = [] i = 1 with open(path, 'rb') as f: for line in f.readlines(): tempList.append((i, line.strip(' ').decode('utf-8'))) i = i + 1 return tempList def OnClick(self, event): self.Close() mainWin = MyFrame(self.wavList, self.recText) mainWin.Show() if __name__ == '__main__': app = wx.App(0) LoginWin(None, 'login') app.MainLoop()
可以通过这个简短的例子, 学习, 线程间通信: https://www.cnblogs.com/douzujun/p/10719458.html
主要流程是: 点击按钮, 执行按钮点击事件函数(录音), 函数里开启一个线程, 同时向主线程发送消息, 主线程接收消息, 将消息发给绘图函数, 让其执行