音轨压制 With FFmpeg & neroAacEnc —- 我的第二个 wxPython 程序(ffnraudio)
Felix Yan | 2010-06-17 | 409 views
我的第二个在 Boa Constructor 下写的 wxPython 程序…
基本功能:
1, 拖入含音轨的媒体文件(任意格式), 列出音轨, 选中需要压制的音轨, 选择压缩选项, 然后单击”Go”即可开始压制.
***ChangeLog***
20100617 0.1a 发布
下载请移步: http://code.google.com/p/ffnraudio/downloads/list
以下是全部代码:
#Boa:Frame:Frame1 # -*- coding: utf-8 -*- import wx import re import time import sys, os import threading import subprocess #if cmp(sys.platform[:3],'win')!=0: # reload(sys) # sys.setdefaultencoding('utf8') f=[] #File List fd=[] #File Duration List s=[] #Stream List sf=[] #Stream to File arg = '' arg2 = '' fn = 0 #File Index def create(parent): return Frame1(parent) [wxID_FRAME1, wxID_FRAME1BUTTON1, wxID_FRAME1CHECKBOX1, wxID_FRAME1LISTBOX1, wxID_FRAME1RADIOBUTTON1, wxID_FRAME1RADIOBUTTON2, wxID_FRAME1STATICTEXT1, wxID_FRAME1TEXTCTRL1, wxID_FRAME1TEXTCTRL2, ] = [wx.NewId() for _init_ctrls in range(9)] class Frame1(wx.Frame): def _init_coll_flexGridSizer1_Items(self, parent): # generated method, don't edit parent.AddWindow(self.staticText1, 0, border=5, flag=wx.ALL) parent.AddWindow(self.textCtrl1, 1, border=5, flag=wx.GROW | wx.ALL | wx.EXPAND) parent.AddWindow(self.button1, 0, border=5, flag=wx.ALL) parent.AddWindow(self.checkBox1, 0, border=5, flag=wx.ALL) def _init_coll_flexGridSizer2_Items(self, parent): # generated method, don't edit parent.AddWindow(self.radioButton1, 0, border=5, flag=wx.ALL) parent.AddWindow(self.radioButton2, 0, border=5, flag=wx.ALL) parent.AddWindow(self.textCtrl2, 0, border=5, flag=wx.ALL) def _init_coll_boxSizer1_Items(self, parent): # generated method, don't edit parent.AddWindow(self.listBox1, 2, border=5, flag=wx.ALL | wx.GROW | wx.EXPAND) parent.AddSizer(self.flexGridSizer1, 0, border=0, flag=0) parent.AddSizer(self.flexGridSizer2, 0, border=0, flag=0) def _init_sizers(self): # generated method, don't edit self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL) self.flexGridSizer1 = wx.FlexGridSizer(cols=0, hgap=0, rows=1, vgap=0) self.flexGridSizer2 = wx.FlexGridSizer(cols=0, hgap=0, rows=1, vgap=0) self._init_coll_boxSizer1_Items(self.boxSizer1) self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) self._init_coll_flexGridSizer2_Items(self.flexGridSizer2) self.SetSizer(self.boxSizer1) def _init_ctrls(self, prnt): # generated method, don't edit wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt, pos=wx.Point(766, 341), size=wx.Size(518, 349), style=wx.DEFAULT_FRAME_STYLE, title=u'\u97f3\u8f68\u538b\u5236 v0.1a - By Felix Yan') self.SetClientSize(wx.Size(518, 349)) self.SetBackgroundColour(wx.Colour(222, 222, 222)) self.Bind(wx.EVT_CLOSE, self.OnFrame1Close) self.listBox1 = wx.ListBox(choices=[], id=wxID_FRAME1LISTBOX1, name='listBox1', parent=self, pos=wx.Point(5, 5), size=wx.Size(508, 267), style=0) self.listBox1.Bind(wx.EVT_LISTBOX, self.OnListBox1Listbox, id=wxID_FRAME1LISTBOX1) self.staticText1 = wx.StaticText(id=wxID_FRAME1STATICTEXT1, label=u'\u8f93\u51fa\u6587\u4ef6\u540d:', name='staticText1', parent=self, pos=wx.Point(5, 282), size=wx.Size(69, 17), style=0) self.textCtrl1 = wx.TextCtrl(id=wxID_FRAME1TEXTCTRL1, name='textCtrl1', parent=self, pos=wx.Point(84, 282), size=wx.Size(160, 27), style=0, value=u'') self.button1 = wx.Button(id=wxID_FRAME1BUTTON1, label=u'Go', name='button1', parent=self, pos=wx.Point(254, 282), size=wx.Size(85, 27), style=0) self.button1.Bind(wx.EVT_BUTTON, self.OnButton1Button, id=wxID_FRAME1BUTTON1) self.checkBox1 = wx.CheckBox(id=wxID_FRAME1CHECKBOX1, label=u'\u964d\u52302.0\u58f0\u9053', name='checkBox1', parent=self, pos=wx.Point(349, 282), size=wx.Size(122, 22), style=0) self.checkBox1.SetValue(True) self.radioButton1 = wx.RadioButton(id=wxID_FRAME1RADIOBUTTON1, label=u'\u5b9a\u8d28\u91cf(-q)', name='radioButton1', parent=self, pos=wx.Point(5, 319), size=wx.Size(90, 21), style=0) self.radioButton1.SetValue(True) self.radioButton1.Bind(wx.EVT_RADIOBUTTON, self.OnRadioButton1Radiobutton, id=wxID_FRAME1RADIOBUTTON1) self.radioButton2 = wx.RadioButton(id=wxID_FRAME1RADIOBUTTON2, label=u'\u5b9a\u7801\u7387(-br)(\u5355\u4f4d:Kbps)', name='radioButton2', parent=self, pos=wx.Point(105, 319), size=wx.Size(191, 21), style=0) self.radioButton2.Bind(wx.EVT_RADIOBUTTON, self.OnRadioButton2Radiobutton, id=wxID_FRAME1RADIOBUTTON2) self.textCtrl2 = wx.TextCtrl(id=wxID_FRAME1TEXTCTRL2, name='textCtrl2', parent=self, pos=wx.Point(306, 319), size=wx.Size(80, 25), style=0, value=u'0.25') self._init_sizers() def __init__(self, parent): self._init_ctrls(parent) dt = MyFileDropTarget(self.listBox1) self.listBox1.SetDropTarget(dt) def OnFrame1Close(self, event): exit() def updateProgress(self, i): self.flag = self.progress.Update(i) def destroyProgress(self): self.flag = self.progress.Destroy() def OnButton1Button(self, event): global sf,f,s,arg,arg2,fn a = self.listBox1.GetSelections()[:] if len(a)>0: pstream = re.compile('\#(\d\.\d)') map=pstream.findall(s[a[0]/3].encode(sys.getfilesystemencoding()))[0].replace('.',':') if self.checkBox1.GetValue(): ac = ' -ac 2 ' else: ac = ' ' if cmp(sys.platform[:3],'win')==0: path = "\\".join(f[sf[a[0]/3]].split("\\")[:-1]) + "\\" else: path = "/".join(f[sf[a[0]/3]].split("/")[:-1]) + "/" if self.radioButton1.GetValue(): q='-q '+self.textCtrl2.GetValue().encode(sys.getfilesystemencoding()) else: q='-br '+self.textCtrl2.GetValue().encode(sys.getfilesystemencoding()) arg = 'ffmpeg -i \"' + f[sf[a[0]/3]].encode(sys.getfilesystemencoding()) + '\" -vn -f wav -map ' arg += map + ac + '-' arg2 = 'neroAacEnc -ignorelength ' + q + ' -if - -of \"' + path.encode(sys.getfilesystemencoding()) + self.textCtrl1.GetValue().encode(sys.getfilesystemencoding()) +'\"' fn = a[0]/3 #wx.MessageBox(arg) print arg self.progress = wx.ProgressDialog(u"Working...", u"正在压制音轨, 请稍候…", 100, style=wx.PD_AUTO_HIDE) self.t = TRun(self) self.t.setDaemon(True) self.t.start() event.Skip() def OnListBox1Listbox(self, event): global sf,f a = self.listBox1.GetSelections() if len(a)>0: self.listBox1.SetSelection(a[0]/3*3+1) self.textCtrl1.SetValue('.'.join(f[sf[a[0]/3]].split("\\")[-1].split("/")[-1].split('.')[:-1])+'.m4a') event.Skip() def OnRadioButton1Radiobutton(self, event): self.textCtrl2.SetValue('0.25') event.Skip() def OnRadioButton2Radiobutton(self, event): self.textCtrl2.SetValue('64') event.Skip() class BoaApp1(wx.App): def OnInit(self): self.main = create(None) self.main.Show() self.SetTopWindow(self.main) return True class TRun(threading.Thread): def __init__(self, caller): threading.Thread.__init__(self) self.caller = caller self.flag = True def run(self): global arg,arg2,fd,fn import subprocess p = subprocess.Popen(args=arg, stdout=subprocess.PIPE, shell=True) p2 = subprocess.Popen(args=arg2, stdin=p.stdout, stderr = subprocess.PIPE, shell=True) r1 = re.compile('Processed\s(\d+)\ssecond') all = fd[fn] #print all ans = '' while p2.poll()==None: ans+=p2.stderr.read(100) #print ans #wx.MessageBox(ans) k = r1.findall(ans) if len(k)>0: #print int(float(k[-1])/all) wx.CallAfter(self.caller.updateProgress, int(float(k[-1])*100/all)) time.sleep(0.01) wx.CallAfter(self.caller.destroyProgress) class MyFileDropTarget(wx.FileDropTarget): def __init__(self, window): wx.FileDropTarget.__init__(self) self.window = window def OnDropFiles(self, x, y, filenames): global f,s,sf #print "\n%d file(s) dropped at (%d,%d):\n" % (len(filenames), x, y) for file in filenames: #file = file.decode(sys.getfilesystemencoding()) #print file,sys.getfilesystemencoding() arg='ffmpeg -i \"'+file.encode(sys.getfilesystemencoding())+'\"' #print arg p = subprocess.Popen(args=arg,stderr=subprocess.PIPE, shell=True) a = p.communicate()[1] pd = re.compile("Duration:\s(\d\d)\:(\d\d)\:(\d\d)\.(\d\d)\,") b = a.split('Stream') d = pd.findall(b[0]) fd.append(int(d[0][0])*60*60+int(d[0][1])*60+int(d[0][2])) f.append(file) for c in b[1:]: if c.find(': Audio:')>=0: d = c.split('\n') while len(d) <= 2: d.append(' ') s.append(file+'\n'+d[0]+'\n'+d[2]) sf.append(len(f)-1) k=[] for m in s: n = m.split('\n') for o in n: k.append(o) self.window.Set(k) return def main(): application = BoaApp1(0) application.MainLoop() if __name__ == '__main__': main()




对于windows 和linux文件\和/的区别,python有自己的系统来管理,我忘了是哪一个,你不用硬写的。仔细google一下。
谢谢..不过一直没找到= =||||
刚刚找了一下,找到了,是
os.sep
谢谢
看你在shlug里的发言了,所以到这里来看看。BOA这个东西比较老了吧。开发人员也不是很活跃。我还是比较倾向用gtk or PyQt.
我现在在尝试eric4,但是在我的系统上刚安装完就有一堆错误…
eric4是个传说。别信这种不成熟的IDE。直接用qt design 画界面,然后用 vim/emacs/eclipse/gedit 之类的写逻辑。
我对这个逻辑很郁闷,pyuic4貌似不能转含中文的.ui文件…
还是想找类似VB6的开发方式,后来的都习惯不了
你才多大,就说习惯不了。习惯不了的只是自己的懒惰。
后来的各种方式都有尝试过. 用起来觉得没有VB6那样的方便, 仅此而已.
另外, 反对以年龄论事.
不熟neo的软件。是把音频提出成wav, 然后再压成MP3?
如果是,为什么不用lame 把wav 压成 mp3? lame是自由软件。
nero压出来的低码率AAC比低码率的MP3能更好的表现电影配音,这是压片者普遍认同的观点.
首先你的软件真的要有人用,最好先考虑清楚版权。lame之类的比较好的地方就是GPL的。你自己的软件如果是GPL的,你把lame放在一起用就可以了。现在你这个所谓跨平台,因为neo的打原因也只能在windows中用吧。
nero本身也是跨平台的,可以跨平台用.
AAC可以有很多自由软件压吧。handbrake, gstream应该也可以吧。这都是非常出名的自由软件。尤其gstream,现在几乎成了多媒体的底层标准。要多看前沿的东西啊。
是影视组用,他们要求用nero,所以我才用的nero;
另外这个想修改不难的
faac是重点测试过的和nero相比较的编码器, 压片组认为它在低码率时没有nero表现力好
你是有组织的人啊,那就当我没有说。不过也应该,跳开组织,有点自己的思考。
您说的几个都是用的faac,而faac是nero的前身.
现在我在看aacplusenc,这个是另一个开源解决方案:)
label 用 gettext 之类的localization 方案比较好。这样硬写进去不是很好。
我还是新手
为什么要用那么多全局变量?
不怎么会用类,不会传参…
可以跨平台吗?需要装python解释器和安装wx吗?
可以跨平台,需要python 2.6 和 wxpython unicode 2.8 for python 2.6
沙发!一窍不通就像天书!