Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- from gi.repository import Gtk, GObject, Vte
- from gi.repository import GLib
- import os
- import sys, subprocess, shlex, re
- from subprocess import call
- class reuse_init(object):
- def make_label(self, text):
- label = Gtk.Label(text)
- label.set_use_underline(True)
- label.set_alignment(1.0, 0.5)
- label.show()
- return label
- def make_slider_and_spinner(self, init, min, max, step, page, digits):
- controls = {'adj':Gtk.Adjustment(init, min, max, step, page), 'slider':Gtk.HScale(), 'spinner':Gtk.SpinButton()}
- controls['slider'].set_adjustment(controls['adj'])
- controls['slider'].set_draw_value(False)
- controls['spinner'].set_adjustment(controls['adj'])
- controls['spinner'].set_digits(digits)
- controls['slider'].show()
- controls['spinner'].show()
- return controls
- def make_frame_ag(self, f_shadow_type, f_label, alig_pad, gri_row_sp, gri_colu_sp, gri_homog):
- controls = {'frame':Gtk.Frame(), 'ali':Gtk.Alignment(), 'grid':Gtk.Grid()}
- controls['frame'].set_shadow_type(f_shadow_type) # 3 GTK_SHADOW_ETCHED_IN , 1 GTK_SHADOW_IN
- controls['frame'].set_label(f_label)
- controls['ali'].set_padding(alig_pad, alig_pad, alig_pad, alig_pad)
- controls['frame'].add(controls['ali'])
- controls['grid'].set_row_spacing(gri_row_sp)
- controls['grid'].set_column_spacing(gri_colu_sp)
- controls['grid'].set_column_homogeneous(gri_homog) # True
- controls['ali'].add(controls['grid'])
- controls['frame'].show()
- controls['ali'].show()
- controls['grid'].show()
- return controls
- def make_spinbut(self, init, min, max, step, page, digits, numeric):
- controls = {'adj':Gtk.Adjustment(init, min, max, step, page), 'spinner':Gtk.SpinButton()}
- controls['spinner'].set_adjustment(controls['adj'])
- controls['spinner'].set_digits(digits)
- controls['spinner'].set_numeric(numeric)
- controls['spinner'].show()
- return controls
- def make_combobox(self, *vals):
- controls = {'list':Gtk.ListStore(str), 'cbox':Gtk.ComboBox(), 'cellr':Gtk.CellRendererText()}
- for i, v in enumerate(vals):
- controls['list'].append([v])
- controls['cbox'].set_model(controls['list'])
- controls['cbox'].pack_start(controls['cellr'], True)
- controls['cbox'].add_attribute(controls['cellr'], "text", 0)
- controls['cbox'].set_active(0)
- controls['cbox'].show()
- return controls
- class ProgrammaGTK(reuse_init):
- def __init__(self):
- self.window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
- self.window.connect("destroy", self.on_window_destroy)
- self.window.set_title("4FFmpeg video crop resize calculator")
- self.window.set_position(1) # 1 center, 0 none,
- self.window.set_border_width(20)
- self.window.set_default_size(500,-1)
- #----------------------------------
- # deinterlace -----------------------
- self.make_deinterlace()
- # scale ------------------------------
- self.make_scale()
- # crop ----------------------------------------
- self.make_crop()
- # denoise ----------------------------
- self.make_denoise()
- # output------------------------
- self.frame_out = self.make_frame_ag(3, ' FFmpeg video filter string (select and copy): ' , 12, 8, 8, True)
- self.labelout = Gtk.Label("")
- self.labelout.set_selectable(1)
- self.frame_out['grid'].attach(self.labelout, 0, 0, 1 ,1)
- # -----------------------------
- # main VBox -------------------------
- self.vbox1 = Gtk.VBox()
- self.vbox1.set_spacing(12)
- # add deinterlace frame
- self.vbox1.pack_start(self.f_deint['frame'], 1, 0, 0)
- # add crop frame -------------------
- self.vbox1.pack_start(self.frame_crop['frame'], 1, 0, 0)
- # add scale frame------------------
- self.vbox1.pack_start(self.frame_scale['frame'], 1, 0, 0)
- # add denoise frame------------------------
- self.vbox1.pack_start(self.frame_dn['frame'], 1, 0, 0)
- #test-------------------
- #self.f_test = self.make_frame_ag(3, "TEST" , 6, 8, 8, True)
- #self.label_test = Gtk.Label("TEST")
- #self.f_test['grid'].attach(self.label_test, 0, 0, 1, 1)
- #self.vbox1.pack_start(self.f_test['frame'], 1, 0, 0)
- #-------------------------------------
- # add output frame ---------------------
- self.vbox1.pack_start(self.frame_out['frame'], 1, 0, 0)
- # parte bassa con terminale --------------------------
- self.make_low_part()
- # add low part-----------------
- self.vbox1.pack_start(self.gridterm, 1, 1, 0)
- #------------------
- self.window.add (self.vbox1)
- #---------------------------------
- self.window.show_all()
- # inizializza variabili
- self.deint_str = ""
- self.crop_str = ""
- self.scalestr = ""
- self.dn_str = ""
- self.filter_test_str = ""
- self.video_width = "0"
- self.video_height = "0"
- def make_deinterlace(self):
- self.f_deint = self.make_frame_ag(3, "" , 6, 8, 8, True)
- self.checkdeint = Gtk.CheckButton("deinterlace")
- self.checkdeint.connect("toggled", self.on_deint_clicked)
- self.f_deint['grid'].attach(self.checkdeint, 0, 0, 1, 1)
- self.box_deint = self.make_combobox(
- "yadif",
- "postprocessing linear blend"
- )
- self.f_deint['grid'].attach(self.box_deint['cbox'], 1, 0, 1, 1)
- self.box_deint['cbox'].connect("changed", self.on_deint_clicked)
- def make_scale(self):
- self.frame_scale = self.make_frame_ag(3, ' scale ' , 6, 8, 8, True)
- # ------------------------------
- self.box1 = self.make_combobox(
- "None",
- "W",
- "H"
- )
- self.frame_scale['grid'].attach(self.box1['cbox'], 0, 0, 1, 1)
- self.box1['cbox'].connect("changed", self.on_scale_clicked)
- #------------------------------------
- self.box2 = self.make_combobox(
- "16/9",
- "4/3"
- )
- self.frame_scale['grid'].attach(self.box2['cbox'], 0, 1, 1, 1)
- self.box2['cbox'].connect("changed", self.on_scale_clicked)
- #-----------------------------------------
- self.size_spinner = self.make_slider_and_spinner(720, 200, 2000, 1, 10, 0)
- self.frame_scale['grid'].attach(self.size_spinner['slider'], 1, 0, 1, 1)
- self.frame_scale['grid'].attach(self.size_spinner['spinner'], 2, 0, 1, 1)
- self.size_spinner['slider'].set_size_request(150,-1)
- self.size_spinner['adj'].set_value(720.001) #mettere decimali se no non si vede
- self.size_spinner['adj'].connect("value-changed", self.on_scale_clicked)
- #-------------------------------------------------------
- self.check = Gtk.CheckButton("lanczos")
- self.check.connect("toggled", self.on_scale_clicked)
- self.frame_scale['grid'].attach(self.check, 2, 1, 1, 1)
- def make_crop(self):
- self.frame_crop = self.make_frame_ag(3, '' , 6, 2, 0, True)
- # -------
- self.checkcr = Gtk.CheckButton("crop")
- self.checkcr.connect("toggled", self.on_crop_clicked)
- self.frame_crop['grid'].attach(self.checkcr, 0, 0, 1, 1)
- #----------
- self.labelcropinw = self.make_label("input W: ")
- self.frame_crop['grid'].attach(self.labelcropinw, 1, 0, 1, 1)
- self.labelcropinh = self.make_label("input H: ")
- self.frame_crop['grid'].attach(self.labelcropinh, 1, 1, 1, 1)
- #
- self.spincw = self.make_spinbut(640 , 100 , 1920 , 10 , 1 , 0, True )
- self.spincw["adj"].connect("value-changed", self.on_crop_clicked)
- self.frame_crop['grid'].attach(self.spincw["spinner"], 2, 0, 1, 1)
- #
- self.spinch = self.make_spinbut(480 , 100 , 1280 , 10 , 1 , 0, True )
- self.spinch["adj"].connect("value-changed", self.on_crop_clicked)
- self.frame_crop['grid'].attach(self.spinch["spinner"], 2, 1, 1, 1)
- #
- self.labelcroptop = self.make_label("crop Top: ")
- self.frame_crop['grid'].attach(self.labelcroptop, 3, 0, 1, 1)
- self.labelcropbot = self.make_label("crop Bottom: ")
- self.frame_crop['grid'].attach(self.labelcropbot, 3, 1, 1, 1)
- #
- self.spinct = self.make_spinbut(0 , 0 , 600 , 1 , 10 , 0, True )
- self.spinct["adj"].connect("value-changed", self.on_crop_clicked)
- self.frame_crop['grid'].attach(self.spinct["spinner"], 4, 0, 1, 1)
- #
- self.spincb = self.make_spinbut(0 , 0 , 600 , 1 , 10 , 0, True )
- self.spincb["adj"].connect("value-changed", self.on_crop_clicked)
- self.frame_crop['grid'].attach(self.spincb["spinner"], 4, 1, 1, 1)
- #
- self.labelcroplef = self.make_label("crop Left: ")
- self.frame_crop['grid'].attach(self.labelcroplef, 5, 0, 1, 1)
- self.labelcroprig = self.make_label("crop Right: ")
- self.frame_crop['grid'].attach(self.labelcroprig, 5, 1, 1, 1)
- #
- self.spincl = self.make_spinbut(0 , 0 , 600 , 1 , 10 , 0, True )
- self.spincl["adj"].connect("value-changed", self.on_crop_clicked)
- self.frame_crop['grid'].attach(self.spincl["spinner"], 6, 0, 1, 1)
- #
- self.spincr = self.make_spinbut(0 , 0 , 600 , 1 , 10 , 0, True )
- self.spincr["adj"].connect("value-changed", self.on_crop_clicked)
- self.frame_crop['grid'].attach(self.spincr["spinner"], 6, 1, 1, 1)
- def make_denoise(self):
- self.frame_dn = self.make_frame_ag(3, '' , 6, 8, 8, True)
- # ----------------------
- self.checkdn = Gtk.CheckButton("denoise")
- self.checkdn.connect("toggled", self.on_dn_clicked)
- self.frame_dn['grid'].attach(self.checkdn, 0, 0, 1, 1)
- # -------------------------
- self.labeldn = Gtk.Label("hqdn3d:")
- self.labeldn.set_alignment(1.0, 0.5)
- self.frame_dn['grid'].attach(self.labeldn, 1, 0, 1, 1)
- #----------------------------------------
- self.spindn = self.make_spinbut(4 , 2 , 8 , 1 , 10 , 0, True )
- self.spindn["adj"].connect("value-changed", self.on_dn_clicked)
- self.frame_dn['grid'].attach(self.spindn["spinner"], 2, 0, 1, 1)
- def make_low_part(self):
- # grid
- self.gridterm = Gtk.Grid()
- self.gridterm.set_row_spacing(2)
- self.gridterm.set_column_spacing(2)
- self.gridterm.set_column_homogeneous(True) # True
- # filechooserbutton
- self.filechooserbutton = Gtk.FileChooserButton(title="FileChooserButton")
- #
- #self.filechooserbutton.set_action(2) # 0 open file, 1 save file, 2 select folder, 3 create folder
- #
- self.filechooserbutton.connect("file-set", self.file_changed)
- # terminal
- self.terminal = Vte.Terminal()
- self.terminal.fork_command_full(
- Vte.PtyFlags.DEFAULT, #default is fine
- os.getcwd(), #where to start the command? os.environ['HOME']
- ["/bin/sh"], #where is the emulator?
- [], #it's ok to leave this list empty
- GLib.SpawnFlags.DO_NOT_REAP_CHILD,
- None, #at least None is required
- None,
- )
- self.scroller = Gtk.ScrolledWindow()
- self.scroller.set_hexpand(True)
- self.scroller.set_vexpand(True)
- self.scroller.add(self.terminal)
- self.gridterm.attach(self.scroller, 0, 1, 6, 1)
- #ff command button
- self.butplay = Gtk.Button(label="FFplay")
- self.butplay.connect("clicked", self.on_butplay_clicked)
- self.butplay.set_sensitive(False)
- self.butprobe = Gtk.Button(label="FFprobe")
- self.butprobe.connect("clicked", self.on_butprobe_clicked)
- self.butprobe.set_sensitive(False)
- self.butcrode = Gtk.Button(label="Crop detect")
- self.butcrode.connect("clicked", self.on_butcrode_clicked)
- self.butcrode.set_sensitive(False)
- self.buttest = Gtk.Button(label="Test")
- self.buttest.connect("clicked", self.on_buttest_clicked)
- self.buttest.set_sensitive(False)
- self.buttestspl = Gtk.Button(label="Test split")
- self.buttestspl.connect("clicked", self.on_buttestspl_clicked)
- self.buttestspl.set_sensitive(False)
- self.gridterm.attach(self.filechooserbutton, 0, 0, 1, 1)
- self.gridterm.attach(self.butprobe, 1, 0, 1, 1)
- self.gridterm.attach(self.butplay, 2, 0, 1, 1)
- self.gridterm.attach(self.butcrode, 3, 0, 1, 1)
- self.gridterm.attach(self.buttest, 4, 0, 1, 1)
- self.gridterm.attach(self.buttestspl, 5, 0, 1, 1)
- # signal handlers -----------------------------------------------
- def on_window_destroy(self, *args):
- Gtk.main_quit(*args)
- def on_scale_clicked(self, button):
- if (self.box1['cbox'].get_active() != 0):
- self.calcola_scale()
- else:
- self.scalestr = ""
- self.outfilter()
- def on_deint_clicked(self, button):
- self.deint_str = ""
- if self.checkdeint.get_active():
- deint_val = self.box_deint['cbox'].get_active()
- if (deint_val == 0):
- self.deint_str = "yadif"
- elif (deint_val == 1):
- self.deint_str = "pp=lb"
- self.outfilter()
- def on_dn_clicked(self, button):
- self.dn_str = ""
- if self.checkdn.get_active():
- dn_val = int( self.spindn['adj'].get_value() )
- self.dn_str = "hqdn3d=" + str(dn_val)
- self.outfilter()
- def on_crop_clicked(self, button):
- ok = 0
- self.crop_str = ""
- if self.checkcr.get_active():
- ok = 1
- if ok:
- inW = int(self.spincw['adj'].get_value())
- inH = int(self.spinch['adj'].get_value())
- crT = int(self.spinct['adj'].get_value())
- crB = int(self.spincb['adj'].get_value())
- crL = int(self.spincl['adj'].get_value())
- crR = int(self.spincr['adj'].get_value())
- finW = inW - crL - crR
- finH = inH - crT - crB
- if ( (finW < 100) or (finH < 100) ):
- self.crop_str = (" ** invalid crop ** ")
- else:
- self.crop_str = "crop=" + str(finW) + ":" \
- + str(finH) + ":" \
- + str(crL) + ":" \
- + str(crT)
- if (self.box2['cbox'].get_active() != 2):
- self.outfilter()
- else:
- self.calcola_scale()
- def file_changed(self, filechooserbutton):
- if self.filechooserbutton.get_filename():
- self.butplay.set_sensitive(True)
- self.butprobe.set_sensitive(True)
- self.butcrode.set_sensitive(True)
- self.buttest.set_sensitive(True)
- self.buttestspl.set_sensitive(True)
- # need ffprobe
- filename = self.filechooserbutton.get_filename()
- cmnd = ['ffprobe', '-show_format', '-show_streams', '-pretty', '-loglevel', 'quiet', filename]
- p = subprocess.Popen(cmnd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, err = p.communicate()
- for line in out.split('\n'):
- line = line.strip()
- if line.startswith('width='):
- s = line
- width = s.split('width=', 1)
- #print "Video pixel width is: %s" % width[1]
- self.video_width = width[1]
- self.spincw['adj'].set_value(float(self.video_width)) #mettere decimali se no non si vede
- self.spincw['spinner'].set_sensitive(False)
- elif line.startswith('height='):
- s = line
- height = s.split('height=', 1)
- #print "Video pixel height is: %s" % height[1]
- self.video_height = height[1]
- self.spinch['adj'].set_value(float(self.video_height)) #mettere decimali se no non si vede
- self.spinch['spinner'].set_sensitive(False)
- self.box2['list'].append(["as input"])
- def on_butplay_clicked(self, button):
- self.command = "ffplay \"" + self.filechooserbutton.get_filename() + "\"" +"\n"
- length = len(self.command)
- self.terminal.feed_child(self.command, length)
- def on_butprobe_clicked(self, button):
- self.command = "ffprobe \"" + self.filechooserbutton.get_filename() + "\"" + " 2>&1 | grep 'Input\|Duration\|Stream'" + "\n"
- length = len(self.command)
- self.terminal.feed_child(self.command, length)
- def on_butcrode_clicked(self, button):
- self.command = "ffplay \"" + self.filechooserbutton.get_filename() + "\"" + " -vf cropdetect" +"\n"
- length = len(self.command)
- self.terminal.feed_child(self.command, length)
- def on_buttest_clicked(self, button):
- self.command = "ffplay \"" + self.filechooserbutton.get_filename() + "\"" + " -vf " + self.filter_test_str +"\n"
- length = len(self.command)
- self.terminal.feed_child(self.command, length)
- def on_buttestspl_clicked(self, button):
- self.command = "ffplay \"" + self.filechooserbutton.get_filename() + "\"" + " -vf \"split[a][b]; [a]pad=iw:(ih*2)+4:color=888888 [src]; [b]" + self.filter_test_str + " [filt]; [src][filt]overlay=((main_w - w)/2):main_h/2\"" + "\n"
- length = len(self.command)
- self.terminal.feed_child(self.command, length)
- # -------------------------------------
- def calcola_scale(self):
- self.scalestr = ""
- numero = self.size_spinner['adj'].get_value()
- if ( (int(numero) % 2) != 0):
- numero = int(numero) + 1
- else:
- numero = int(numero)
- dar = self.box2['cbox'].get_active()
- lato = self.box1['cbox'].get_active()
- if (dar == 1): # 4/3
- if (lato == 1):
- n2 = numero/4*3
- else:
- n2 = numero/3*4
- setdar = ",setdar=4/3,setsar=1/1"
- elif (dar == 0): # 16/9
- if (lato == 1):
- n2 = numero/16*9
- else:
- n2 = numero/9*16
- setdar = ",setdar=16/9,setsar=1/1"
- elif (dar == 2): #1/1 same as input
- w = int(self.video_width)
- h = int(self.video_height)
- if self.checkcr.get_active():
- crT = int(self.spinct['adj'].get_value())
- crB = int(self.spincb['adj'].get_value())
- crL = int(self.spincl['adj'].get_value())
- crR = int(self.spincr['adj'].get_value())
- h = h - crT - crB
- w = w - crL - crR
- if (lato == 1): # h
- n2 = (float(h)/(w/float(numero)))
- else:
- n2 = (float(w)/(h/float(numero)))
- setdar = ""
- if ( (int(n2) % 2) != 0):
- n2 = int(n2) + 1
- else:
- n2 = int(n2)
- self.scalestr = "scale="
- if (lato == 1):
- self.scalestr = self.scalestr + str(numero) + ":" + str(n2)
- else:
- self.scalestr = self.scalestr + str(n2) + ":" + str(numero)
- lanc = self.check.get_active()
- if lanc:
- self.scalestr = self.scalestr + ":flags=lanczos" + setdar
- else:
- self.scalestr = self.scalestr + setdar
- self.outfilter()
- def outfilter(self):
- final_str = ""
- if (self.deint_str != ""):
- final_str = final_str + self.deint_str
- if (self.crop_str != ""):
- if (final_str == ""):
- final_str = final_str + self.crop_str
- else:
- final_str = final_str + "," + self.crop_str
- if (self.scalestr != ""):
- if (final_str == ""):
- final_str = final_str + self.scalestr
- else:
- final_str = final_str + "," + self.scalestr
- if (self.dn_str != ""):
- if (final_str == ""):
- final_str = final_str + self.dn_str
- else:
- final_str = final_str + "," + self.dn_str
- self.filter_test_str = final_str
- if (final_str != ""):
- final_str = "-vf " + final_str
- self.labelout.set_text(final_str)
- def main(self):
- Gtk.main()
- if __name__ == "__main__":
- hwg = ProgrammaGTK()
- Gtk.main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement