Please help a dummie like me with batch cropping

Started by Stavdem, February 01, 2020, 11:20:41 AM

Previous topic - Next topic

Stavdem

Hello there,

recently I started recording videos. Unfortunately something went wrong. I know the cause, that's not the problem. But since the damage is already done I badly need to crop the ones I already created. To be more exact I need to crop 236 pixels on the left and on the right side.

I figured out how to do it in avidemux. I load the source file (which is mp4), select video output "Mpeg4 AVC (x264), leave the Audio output unchanged (Copy), select "Crop" as filter and let avidemux process the file. All fine, all dandy

but

I do already have dozens of videos that I need to "fix" this way. And I couldn't find a batch processing option in avidemux.

So I googled and I read that this has to be / can be done by using a script. Unfortunate I'm an idiot on this stuff. I have no idea wha python is, how to install or use it. I even read a tutorial but that didn't work for me either (which is no surprise since I know myself).

Can you guys help me? Thank you in advance.

eumagga0x2a

#1
Quote from: Stavdem on February 01, 2020, 11:20:41 AM
recently I started recording videos. Unfortunately something went wrong. I know the cause, that's not the problem. But since the damage is already done I badly need to crop the ones I already created. To be more exact I need to crop 236 pixels on the left and on the right side.

Please explain why. It is generally a bad idea to end up with non-standard dimensions, so please provide some insight.

QuoteI have no idea wha python is, how to install or use it.

There is nothing to install, an internal to Avidemux, minimal trimmed-down variety of python language interpreter is used. But it is necessary to understand the big picture first, which will allow to identify the best way to achieve the goal.

Stavdem

Don't get this wrong but please don't turn this into a discussion about (standard) dimensions. I know what I did wrong and already fixed it. But know I need to crop about 60 videos.

Again, please don't be offended by my answer. Thank you.


eumagga0x2a

The procedure to write your own script should start with loading a single video to convert, configuring the encoder, the video filters and the output container to get the desired result and to save this state as a project script (File --> Project Script --> Save As Project...).

The second step would be to look at the sample script at https://github.com/mean00/avidemux2/blob/master/autononreg/py/sample_script/convert_avi_to_x264_mkv.py and use it as the skeleton to fill with the values you need. You will need to replace the arguments for adm.videoCodec as well as for adm.setContainer with those matching your saved project script and probably drop adm.audioReset and adm.audioCodec entirely ("copy" is the default setting) so that all audio tracks get automatically copied (the conversion will fail if the chosen container doesn't support the particular codec).

Some functions have changed significantly since that sample script was created almost 9 years ago, so all those calls should be replaced with their parallels from the previously saved project script.

You should keep in mind that crop may be a wrong tool, especially with factors like anamorphic display. Depending on problem to solve, "blacken borders" or even "mplayer delogo2" may be a better choice.

Stavdem

Thank you for your answer. Don't worry about that cropping might be the wrong tool because I don't understand anything.

Like seriously, I don't understand step two and beyond at all. Use as skeleton? Arguments? Some functions have changed? And what do I do afterwards? Holy hell, this sounds like reading a book of code written in cyrillic. Can't I just automate what I already done for a single file in Avidmus for all files in a folder? I remember like 8 years ago I used a tool called VirtualDub I thing to batch convert videos. Isn't there something like that today? Something for dummies like me?

But thank you again for trying to help me.

eumagga0x2a

Either you provide all details which would allow me to write the script for you (it will target the latest Avidemux nightly, which should not pose a problem as current nightlies are so much better than the last release) or you have to acquire some basic understanding of the structure of python language (the very minimal subset of it used by Avidemux) so that you could come up with some intermediate state of your project which I would be able to build upon to provide you with a final working version.

Quote from: Stavdem on February 01, 2020, 05:52:32 PM
Use as skeleton?

As a template.

QuoteArguments?

What you see between "(" and ")" in the sample script I linked to.

QuoteSome functions have changed?

Yes, they have, especially those to configure output container (MKV, MP4 etc.).

QuoteAnd what do I do afterwards?

Post what you have written so that I can proofread.

QuoteCan't I just automate what I already done for a single file in Avidmus for all files in a folder?

This is exactly what we are going to do.

QuoteI remember like 8 years ago I used a tool called VirtualDub I thing to batch convert videos. Isn't there something like that today? Something for dummies like me?

There is "VirtualDub2", but I have no experience with it. Maybe it offers graphical tools for batch converting.

eumagga0x2a

I'll provide a sample script in a moment, it should greatly facilitate all further steps.

eumagga0x2a

#7
You could try the following (untested):

#PY  <- Needed to identify #
#
ui = Gui()
adm = Avidemux()
ext = "mp4"
separator = "\\"
#
# Function to convert an individual video
#
def convert(filein,out):
    if(1 == adm.loadVideo(filein)):
        adm.videoCodec("x264", "useAdvancedConfiguration=True", "general.params=AQ=20", "general.threads=99", "general.preset=", "general.tuning=", "general.profile=", "general.fast_decode=False", "general.zero_latency=False", "general.fast_first_pass=True"
, "general.blueray_compatibility=False", "general.fake_interlaced=False", "level=-1", "vui.sar_height=1", "vui.sar_width=1", "MaxRefFrames=3", "MinIdr=25", "MaxIdr=250", "i_scenecut_threshold=40", "intra_refresh=False"
, "MaxBFrame=3", "i_bframe_adaptive=1", "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=True", "analyze.b_p16x16=False", "analyze.b_b16x16=False"
, "analyze.weighted_pred=2", "analyze.weighted_bipred=True", "analyze.direct_mv_pred=1", "analyze.chroma_offset=0", "analyze.me_method=1", "analyze.me_range=16", "analyze.mv_range=-1", "analyze.mv_range_thread=-1"
, "analyze.subpel_refine=7", "analyze.chroma_me=True", "analyze.mixed_references=True", "analyze.trellis=1", "analyze.psy_rd=1.000000", "analyze.psy_trellis=0.000000", "analyze.fast_pskip=True", "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=1.000000", "ratecontrol.vbv_max_bitrate=0", "ratecontrol.vbv_buffer_size=0", "ratecontrol.vbv_buffer_init=1", "ratecontrol.ip_factor=1.400000"
, "ratecontrol.pb_factor=1.300000", "ratecontrol.aq_mode=1", "ratecontrol.aq_strength=1.000000", "ratecontrol.mb_tree=True", "ratecontrol.lookahead=40")
        adm.addVideoFilter("crop", "top=0", "bottom=0", "left=236", "right=236", "rubber_is_hidden=False")
        adm.setContainer("MP4", "muxerType=0", "optimize=1", "forceAspectRatio=False", "aspectRatio=1", "rotation=0", "clockfreq=0")
        filename = basename(filein)
        adm.save(out + separator + "cropped_" + filename)
#
# Main
#
# -------- select directory --------
inputFolder = ui.dirSelect("Select the source folder")
outputFolder = ui.dirSelect("Select the target folder")
if(outputFolder is None):
    return
if(inputFolder == outputFolder):
    ui.displayError("Output folder cannot be the same as the input one")
    return
#
list = get_folder_content(inputFolder,ext)
if(list is None):
    return
for i in list:
    convert(i,outputFolder)
print("All done\n")


I'm going to attach the script to this reply. The script targets the latest nightly https://avidemux.org/nightly/win64/

Lines beginning with "#" are comments and are ignored by the python interpreter in Avidemux.

I've edited the script to prepend the filename of each converted file with "cropped_".

Stavdem

Thank you once again but I fear there's a gigantic misunderstanding here. My level of cluelessness is much bigger than you seem to expect. I read about the script/py thing but... ehm... I don't even know what to do with the actual .py file.  :x

eumagga0x2a

File --> Project Script --> Run Project

".py" files are text files (".txt") with a different file name extension.

Stavdem

I tried that before I wrote that and before you replied.

This tool for sure isn't dummy-proof and it met the biggest dummy of all (me). I tried to run the project but selected to same folder twice. It doesn't say input and output there and the resulting error message doesn't say it either. So ofc it didn't work.

But omg, it works. Thank you so very much. Thank you for your time and help.

eumagga0x2a

#11
Quote from: Stavdem on February 01, 2020, 08:36:48 PM
I tried to run the project but selected to same folder twice. It doesn't say input and output there and the resulting error message doesn't say it either. So ofc it didn't work.

My bad, the function displayError() expects two arguments, I gave it only one. Please replace the line

    ui.displayError("Output folder cannot be the same as the input one")

with

    ui.displayError("Error","Output folder cannot be the same as the input one")

in the script and you will get a proper error message when selecting the same folder twice. A fixed version is attached.

edit: oops, I attached a version with directory separator set to "/" because I use Linux. Replacing it with one for Windows with separator = "\\".


andrewk8

Handbrake might be a viable alternative.  It can suggest cropping automatically (e.g. remove letterboxing) and allows you to customize teh crops it if you want different values.  If it guesses right, you can have it transcode an entire folder.  If it guesses wrong, you have to manually do each one.  Not too hard with HB's interface - you're not having to add a filter each time.  Also, HB's queuing lets you start the first transcode while you're adding the 2nd file, 3rd file, etc. to the queue.  Monotonous for 60 files, but it will finish some of them while you're adding the rest to the queue.