Avidemux is a free, cross-platform video editing program that is both very simple and immensely powerful. Much of its power is thanks to its command line interface (CLI) and potential for scripting.
In this particular post I will be focusing on the latter aspect: scripting.
Specifically, I will be covering the elements and commands found in a basic Avidemux script. I am currently using Avidemux 2.4.4 on a Mac, though I routinely use 2.5.1 on Linux, and even occasionally on Windows. For those who have multiple platforms available, I recommend the Linux or Windows versions for their increased stability.
Table of Contents
- Declaring variables
- If...Else statements
The Basic Script
Now, let's get down to basics. The easiest way to start learning about Avidemux scripts is to look at one. Lucky for us (since the documentation online is pretty weak), Avidemux project files are actually just basic scripts.
So, if you want to know how to do something in a script, first try accomplishing it from the graphic user interface (GUI), then save your project, and open the project file in a text editor to see how the resulting script is put together.
For the following example, I did just that. This script simply lays down a first video in its entirety, then appends a second video.
//AD <- Needed to identify// //--automatically built-- //--Project: /Volumes/Media_G5/Ben/Tutorials/Test_Script var app = new Avidemux(); //** Video ** // 02 videos source app.load("/Volumes/MEDIA_G5/BEN/TUTORIALS/clip1.mov"); app.append("/Volumes/MEDIA_G5/BEN/TUTORIALS/clip2.mov"); //02 segments app.clearSegments(); app.addSegment(0,0,3587); app.addSegment(1,0,2707); app.markerA=0; app.markerB=6293; //** Postproc ** app.video.setPostProc(3,3,0); app.video.setFps1000(23907); //** Filters ** //** Video Codec conf ** app.video.codec("Copy","CQ=4","0 "); //** Audio ** app.audio.reset(); app.audio.codec("copy",128,0,""); app.audio.normalizeMode=0; app.audio.normalizeValue=0; app.audio.delay=0; app.audio.mixer("NONE"); app.setContainer("AVI"); setSuccess(1); //app.Exit(); //End of script
Again, this script simply loads clip1.mov and then appends clip2.mov to that. Nothing more, nothing less.
Now let's examine the code.
//AD <- Needed to identify// //--automatically built-- //--Project: /Volumes/Media_G5/Ben/Tutorials/Test_Script
This is the header information. The first line must always be included, as it identifies the file as an Avidemux script. The second and third lines contain additional information that can be discarded or re-written.
var app = new Avidemux();
This is the first line of actual code after the header (always). It starts a new instance of Avidemux, so you need to include it (always).
//** Video ** // 02 videos source app.load("/Volumes/Media_G5/Ben/Tutorials/clip1.mov"); app.append("/Volumes/Media_G5/Ben/Tutorials/clip2.mov");
This section loads the videos that will be used by the script. You must always have one (no more, no less) app.load() command, after which you may list any number of additional clips using app.append().
Also, these scripts do not support relative paths. You must include the full paths to the source videos.
//02 segments app.clearSegments(); app.addSegment(0,0,3587); app.addSegment(1,0,2707); app.markerA=0; app.markerB=6293;
Here's the meat of the script. app.clearSegments() clears the timeline to ensure that you are starting with a clean slate. As far as I know, there are no arguments for this command.
app.addSegment() adds the specified frames to the timeline in the order that the app.addSegments() commands appear. They each require three arguments:
- Video clip number
- Starting frame
- Number of frames to add
The Video clips are numbered in the order that they are added in the previous section. The clip referenced by app.load() is always number 0. In this case, clip2.mov is clip number 1.
The starting frame should be self-explanatory, as should the number of frames to add, though it should be noted that the final argument is NOT equivalent to the ending frame. Also, because the starting frame is the first one added, the ending frame is not equal to (startingFrame + numberOfFrames) but rather (startingFrame + numberOfFrames - 1).
For example, app.addSegment(1,15,60); would add frames 15 - 74 from clip2.mov.
app.markerA and app.markerB are optional. They can be used to select a specific section of the timeline (by setting in and out points to specific frames), but if left out then the default is to simply count the whole timeline as selected. This is very fortunate because it keeps us from having to calculate the total number of frames in every script.
//** Postproc ** app.video.setPostProc(3,3,0); app.video.setFps1000(23907); //** Filters ** //** Video Codec conf ** app.video.codec("Copy","CQ=4","0 ");
This section sets post-processing parameters. I don't really know what function app.video.setPostProc() serves, but i know that it isn't necessary to include this line. I leave it out of all my custom scripts and they still function just fine.
UPDATE-06-06-2010: setPostProc() sets the postprocessing value with the following arguments: type, threshold, strength
app.video.setFps1000() sets the framerate of the timeline:
- 1000 = 1 Fps
- 23907 = 23.907 Fps
- 29970 = 29.97 Fps
- 30000 = 30 Fps
You cannot set the framerate below 1 Fps (the value of app.video.setFps1000() cannot be less than 1000).
UPDATE-06-08-2010: You can use getFps1000() to set the frame rate the same as in the input file. For example:
Filters would be listed under // Filters but I haven't applied any to this timeline.
app.video.codec() specifies some codec settings. I often leave this out of my scripts and simply set these parameters via the CLI or GUI when I run the script.
//** Audio ** app.audio.reset(); app.audio.codec("copy",128,0,""); app.audio.normalizeMode=0; app.audio.normalizeValue=0; app.audio.delay=0; app.audio.mixer("NONE");
I'm not going to get deep into audio in this post (you won't find anything about codec settings here), but I'll run through some basics.
The normalizeMode and normalizeValue variables can be replaced with a single normalize on / off variable like so:
Where 0 is "off" and 1 is "on". The same goes for the delay variable, which determines how much of an offset there is between the audio and the video (in milliseconds).
app.audio.mixer can take values of "NONE", "STEREO", or "MONO".
app.setContainer("AVI"); setSuccess(1); //app.Exit(); //End of script
app.setContainer() sets your container format (imagine that!). This accepts the following arguments: PS, ES, TS, OGM, AVI, AVI_DUAL, AVI_UNP, MP4
It may actually accept more that are not documented, MP4 was one that I found through trial and error.
I am not entirely sure what setSuccess(1) does, but I leave it alone and it doesn't bother me.
If you uncomment app.Exit() it will quit Avidemux upon completing the script. This, however, is not recommended unless you add a save command before it. I have never been able to get the save commands to work reliably, so I just incorporate them into the CLI commands I use to run my scripts. That said, app.save(filename_goes_here) is supposed to do the trick.
Running Your Script
You can run a script by opening up the GUI and selecting "Load/Run Project" or with the CLI, as below:
avidemux2_cli --run YOUR_SCRIPT_HERE --save YOUR_OUTPUT_FILE_HERE --quit
That wraps up today's lesson on the basic Avidemux script. Soon I will be posting some more advanced tips and tricks, including elements and commands not found in a basic Avidemux project file.
If you found this post helpful, please leave feedback in the comments section below. If there is anything that you need further clarified, or that you would like included in the next, more advanced post, do the same.