[SOLVED] Avidemux batch resize/convert all videos in folder to x264. Windows 8!

Started by Anubioz, November 10, 2013, 08:51:37 AM

Previous topic - Next topic

Anubioz

It took me pretty long to figure out how to use the new python scripting, but finally I managed to write a script, that converts all video  files, (with a given extension) that are larger then 540p (540 height) in a target folder to H.264 in mkv. I not only hope it would be useful to someone, but also I expect it to stay here, so I won't have to learn that stupid python again. I'll probably write some comments (&expand functionality) later :).

#FILL IN THE VARIABLES & ENABLE SILENT MODE IF YOU WANT

targetfileextension = "wmv"
targetheight=540
targetdirectory = "C:\\Videos\\"
outputdirectory = "C:\\Videos_Converted\\"
stringtoappend=".converted.mkv"
silentmode=False

convertedlist=[]
skippedlist=[]

adm = Avidemux()
gui = Gui()

if (silentmode==False):
fileext=gui.fileReadSelect("Please select file type you wanna convert (only files with this extension would be scanned & converted)")[-4:]
ext=fileext.replace(".", "", 1)
gui.displayInfo("Extension","You have selected the following file types to batch-convert: "+ext+"\r\nNow, please select source folder (containing video files)")
folder=gui.dirSelect("Select source Folder")
gui.displayInfo("Source folder","You have selected: "+folder+"\r\nNow, please select target folder (to put converted files into)")
outputfolder=gui.dirSelect("Select target Folder (resulting files would be saved to this folder)")+"\\"
else:
ext=targetfileextension
folder=targetdirectory
outputfolder=outputdirectory



filelist=get_folder_content(folder, ext)
if(filelist is None):
gui.displayError("Error","No files")
raise
quit()
for i in filelist:
if (basename(i)[-len(stringtoappend):]==stringtoappend):
skippedlist.append(basename(i))
else:
adm.loadVideo(i)
rezultfile=outputfolder+basename(i)+stringtoappend
adm.clearSegments()
adm.addSegment(0, 0, 2964498000)
adm.markerA = 0
adm.markerB = 2964498000

fps = adm.getFps1000()
if (fps>29971):
adm.addVideoFilter("resampleFps", "mode=3", "newFpsDen=1001", "newFpsNum=30000")

adm.videoCodec("x264", "general.params=AQ=22", "general.threads=99", "general.fast_first_pass=True", "level=4294967295", "vui.sar_height=1", "vui.sar_width=1", "MaxRefFrames=4", "MinIdr=30", "MaxIdr=300", "i_scenecut_threshold=40"
, "intra_refresh=False", "MaxBFrame=10", "i_bframe_adaptive=2", "i_bframe_bias=0", "i_bframe_pyramid=2", "b_deblocking_filter=True", "i_deblocking_filter_alphac0=0", "i_deblocking_filter_beta=0", "cabac=True"
, "interlaced=False", "constrained_intra=False", "tff=True", "fake_interlaced=False", "analyze.b_8x8=True", "analyze.b_i4x4=True", "analyze.b_i8x8=True", "analyze.b_p8x8=False", "analyze.b_p16x16=True"
, "analyze.b_b16x16=True", "analyze.weighted_pred=1", "analyze.weighted_bipred=True", "analyze.direct_mv_pred=3", "analyze.chroma_offset=0", "analyze.me_method=1", "analyze.me_range=16", "analyze.mv_range=-1"
, "analyze.mv_range_thread=-1", "analyze.subpel_refine=10", "analyze.chroma_me=True", "analyze.mixed_references=True", "analyze.trellis=1", "analyze.psy_rd=1.000000", "analyze.psy_trellis=0.000000", "analyze.fast_pskip=False"
, "analyze.dct_decimate=True", "analyze.noise_reduction=0", "analyze.psy=True", "analyze.intra_luma=11", "analyze.inter_luma=21", "ratecontrol.rc_method=0", "ratecontrol.qp_constant=0", "ratecontrol.qp_min=10"
, "ratecontrol.qp_max=51", "ratecontrol.qp_step=4", "ratecontrol.bitrate=0", "ratecontrol.rate_tolerance=0.680000", "ratecontrol.vbv_max_bitrate=0", "ratecontrol.vbv_buffer_size=0", "ratecontrol.vbv_buffer_init=0"
, "ratecontrol.ip_factor=1.400000", "ratecontrol.pb_factor=1.300000", "ratecontrol.aq_mode=2", "ratecontrol.aq_strength=1.000000", "ratecontrol.mb_tree=True", "ratecontrol.lookahead=50")

audio = adm.audioEncoding(0)
if (audio==255):
adm.audioClearTracks()
adm.setSourceTrackLanguage(0,"unknown")
adm.audioAddTrack(0)
adm.audioCodec(0, "copy");
adm.audioSetDrc(0, 0)
adm.audioSetShift(0, 0,0)
else:
adm.audioClearTracks()

adm.setSourceTrackLanguage(0,"unknown")
adm.audioAddTrack(0)
adm.audioCodec(0, "Faac", "bitrate=112");
adm.audioSetDrc(0, 0)
adm.audioSetShift(0, 0,0)
adm.setContainer("MKV", "forceDisplayWidth=False", "displayWidth=1280")

width = adm.getWidth()
height = adm.getHeight()
ratio = width/height

if (height>targetheight):
ourratio=height/targetheight
ourwidth=width/ourratio
ourheight=height/ourratio
adm.addVideoFilter("swscale", "width="+str(ourwidth), "height="+str(ourheight), "algo=2", "sourceAR=1", "targetAR=1")
adm.save(rezultfile)
convertedlist.append(basename(i))
else:
skippedlist.append(basename(i))

convertedfiles='\r\n'.join(convertedlist)
skippedfiles='\r\n'.join(skippedlist)


gui.displayInfo("The following files were successfully converted",convertedfiles)
gui.displayInfo("The following files were skipped",skippedfiles)

gui.displayInfo("Everything is done","Thanks for using my script")


Update #1: Added (crude) file extension selection via GUI. Also I got the list of commands that should be implemented into avidemux python (it shouldn't be too much of a problem, right? :):
1. getAudioBitrate - self-explanatory (getVideoBitrate would be nice too)
2. renamefile/deletefile
3. shell (system) command execute

Update #2: Added a msgbox with stats on converted/skipped files after the process finishes. Also an Unload file function would be nice, so the program won't lock itself on the last file after the batch finishes.

Update #3: Added silent mode & source/target directory selection, so you can have converted files in any other place. Also found a bug within gui.dirSelect function, which DOES NOT supply a directory ending slash, which results in invalid behavior, when used with "basename" (imagine you select a    folder with gui.dirSelect(), then a file with gui.fileReadSelect() - if you just add folder+file, you won't get what you need, unless you put a slash between them like: folder+"/"+file - and that breaks Linux compatibility of the scripts (in case I need to put +"\\"+ on my windows :)!

P.S. The forum feels so lifeless, I suppose a few more edits/updates to my script (like adding codec configuration window after script launch & it can be included into stable branch :))

P.P.S. Well, it seems there is no way to get user input at the current state of scripting engine, so we'll have to wait until someone introduces the codecprofile=gui.showCodecPanel() function, so it can be later used with adm.videoCodecSetProfile("x264", codecprofile) :)

P.P.P.S Well, I wonder how much more additional visitors from Google will my brand-new SEO-optimized thread title get to this site? :)

phaolo

Noo wait.. do you mean I won't be able to use my 2.5.4 perfect batch script with params anymore?!   :'(
I guess that I'll have to mess with Python too then... thanks for sharing your example (I have WinXp, however).

Anubioz

Exactly, 2.5.4 powerful JS engine is no more, so you'd have to learn python, which probably won't get you anywhere near 2.5 functionality anyway, because it currently has like 10-20 functions total. (also ~50% of them are useless).

http://www.avidemux.org/admWiki/doku.php?id=using:tinypy - check this & start crying

mean


phaolo

Thanks for the info Anubioz.
Well, if all the parameters are gone, someone should also remove\edit this from the wiki:
http://www.avidemux.org/admWiki/doku.php?id=using:command_line_usage

dolufor

QuoteP.P.P.S Well, I wonder how much more additional visitors from Google will my brand-new SEO-optimized thread title get to this site? :)

Well, at least one ;)
Came here to find out whether I could write my own python script and use AviDemux like a command line program to do what I wanted (join files without re-encoding). But seems as if AviDemux can run Python itself (best Scriptlanguage in my opinion) (though I never used tinypy like AviDemux seems to do).
I have to batchconvert several thousand files in hundreds of directories so unfortunately I don't think your script will be that good for me.
Unfortunately tinypy seems to not support os.walk() (gives you all files, dirs, subdirs) so I would probably still write my own stand alone python script to feed avidemux preferably.

Do those http://www.avidemux.org/admWiki/doku.php?id=using:command_line_usage still work? And what would I need to do, to join several mpg together without re-encoding them ("copy" when in the GUI)?

EDIT: Ok
avidemux.exe --load "F:\\x\\01.mpg" --append "F:\\x\\02.mpg" --append "F:\\x\\03.mpg" --save "F:\\x\\blabla.mpg" --quit
seems to do the job.

Thank you

I12learn

@ Anubioz
I found your script very interesting, unfortunately my scope is different. So I'm trying to adapt it for my own use.
To all
I realize that the tiny python isn't interpreted by python, I think it's just python look-alike for the avidemux's internal interpreter.
Said that, I'd like to know whether the python grammar is accepted. For instance the if ..... : statement doesn't need parentheses surrounded and script lines might be broken down to 80 columns (for readability).
I didn't  find reference about single-double quoted string. If strings contains double quote, may I enclose them with quote or viceversa? (general question)
This is because of setting the output codec into a variable
vidCodec='"x264", "general.params=AQ=25", "general.threads=99",
            "general.fast_first_pass=True", "level=31", "vui.sar_height=1",
            "vui.sar_width=1", "MaxRefFrames=2", "MinIdr=100", "MaxIdr=500",
            "MaxBFrame=2", "i_bframe_adaptive=0", "i_bframe_bias=0",
            "i_bframe_pyramid=0", "b_deblocking_filter=False",
            "i_deblocking_filter_alphac0=0", "i_deblocking_filter_beta=0",
            "cabac=True", "interlaced=False", "analyze.b_8x8=True",
            "analyze.b_i4x4=False", "analyze.b_i8x8=False",
            "analyze.b_p8x8=False", "analyze.b_p16x16=False",
            "analyze.b_b16x16=False", "analyze.weighted_pred=0",
            "analyze.weighted_bipred=False", "analyze.direct_mv_pred=0",
            "analyze.chroma_offset=0", "analyze.me_method=0",
            "analyze.subpel_refine=7", "analyze.chroma_me=False",
            "analyze.mixed_references=False", "analyze.trellis=1",
            "analyze.fast_pskip=True", "analyze.dct_decimate=False",
            "analyze.noise_reduction=0", "analyze.psy=True",
            "ratecontrol.rc_method=0", "ratecontrol.qp_constant=0",
            "ratecontrol.qp_min=0", "ratecontrol.qp_max=0",
            "ratecontrol.qp_step=0", "ratecontrol.bitrate=0",
            "ratecontrol.vbv_max_bitrate=0", "ratecontrol.vbv_buffer_size=0",
            "ratecontrol.vbv_buffer_init=0", "ratecontrol.ip_factor=0,000000",
            "ratecontrol.pb_factor=0,000000", "ratecontrol.aq_mode=0",
            "ratecontrol.aq_strength=0,000000", "ratecontrol.mb_tree=False",
            "ratecontrol.lookahead=0"'
adm.videoCodec(vidCodec)

Having this mode, one can decide about which codec to use, or even better to load it from a file instead.
Back to programming, if I cancel the directory selection on the first option it'll cause an exception. TRying to prevent that I haven't found a right solution yet if fileext == "": # who knows what is the returned
                       # code from the selection, "", None or 0 (not found that, yet)?
gui.displayError("File error","No folder specified")
raise


So, it's a long way to go, to find what tiny python will do for me. Additional inputs are welcome

peardox

Remove these lines and it works properly...

Quote
      adm.clearSegments()
      adm.addSegment(0, 0, 2964498000)
      adm.markerA = 0
      adm.markerB = 2964498000

Those lines force the output to be 49.8 minutes in length, remove them and it'll encode the full video