User Tools

Site Tools


tutorial:scripting_tutorial

Scripting tutorial

This page tries to explain how scripting works inside Avidemux.

The scripting engine used by Avidemux is SpiderMonkey, and it is an ECMAScript/JavaScript engine. We will walk through a simple script that removes the evil packed bitstream from a whole directory.

Headers

The following will probably be the two first lines of any Avidemux script:

//AD  <-
  var app = new Avidemux();

The first one is used by Avidemux to identify the file, and must be present (at least the four first characters : //AD).

The second line is where we instantiate the Avidemux class. Almost all Avidemux functions will be accessed through it, in our case app.

Setting up directories

We will declare a bunch of variables and set the incoming and outgoing dirs

//AD  <-
/*
      Simple script that scans the orgDir directory
      and unpack all AVI files
      The resulting file is put in destDir directory
 
      Using new directorySearch API
 
*/
var app = new Avidemux();
var ds = new DirectorySearch();
var orgDir;
var destDir;
var reg =new RegExp(".$");
/*
      This is for Unix
      For Windows change to
      sep="\\";
*/
var sep="/";
var extension;
var target;

If you use paths directly in your script, it is very important not to forget to remove the last /. For example, /foo/bar is ok, /foo/bar/ is not.

Let's ask the user to give input and ouput dir. To do so, we will ask for files and only keep the directory part of it.

      orgDir=fileReadSelect();
      destDir=fileWriteSelect();
      orgDir=pathOnly(orgDir);
      destDir=pathOnly(destDir);
      orgDir=orgDir.replace(reg,"");
      destDir=destDir.replace(reg,"");
 

Note that we use the reg regexp to remove the trailing / or \.

Main loop

Now that the directories are set, we can parse them. Let's get the interesting files:

if(ds.Init(orgDir))
{
 // Only process files we want i.e. AVI
  if(!ds.isNotFile && !ds.isDirectory && !ds.isHidden && !ds.isArchive && !ds.isSingleDot && !ds.isDoubleDot)
      {
          extension=ds.GetExtension();
          if(extension == "avi")
          {
              target=ds.GetFileName();
              target=destDir+sep+target;
              processFile(orgDir+sep+ds.GetFileName(),target);
              }
      }

So we keep only the files that are not directory and have an avi extension. Of course you can replace the extension to your needs. Next we use the reg2 regexp to remove the path.

If the incoming file is /dump/you_are_under/foo.avi, and target directory is /tmp, the following will occur:

target=foo.avi

target=/tmp +/+foo.avi=/tmp/foo.avi

Next we prepend the target directory and call process file with both source and target file.

Taking the same example

source=/dump/you_are_under +/+foo.avi=/dump/you_are_under/foo.avi

target=/tmp+/+foo.avi=/tmp/foo.avi

Processing function

Our main loop is over. The fun continues in the processFile function that will do the real job. It will process one file and is called for each file by our main loop.

function processFile(filename, targetfile)
{
      // Load the file
      app.forceUnpack();
      app.load(filename);
      app.rebuildIndex();
      app.audio.delay=0;
      app.audio.mixer("NONE");
      app.audio.scanVBR();
      app.setContainer("AVI_UNP");
      app.save(targetfile);
      return 1;
}

We just call forceunpack to remove the packed bitstream, and call scanVBR in case it is MP3 VBR. Then set output format to AVI_UNP and save.

Of course it is a simple example. If you have processed a file and want to do the same processing to a bunch of file here is how to do:

  1. Edit the file to your liking
  2. Save the project as /tmp/prj.js for example
  3. Copy paste the /tmp/prj.js file into processFile
  4. Modify to use filename and targetfile as source and destination file

You can perfectly apply audio and video filters, change codec etc…

Complete script

The whole script looks like this:

//AD  <-
/*
      Simple script that scans the orgDir directory
      and unpack all AVI files
      The resulting file is put in destDir directory
      Using new directorySearch API
*/
var app = new Avidemux();
var ds = new DirectorySearch();
var orgDir;
var destDir;
var reg =new RegExp(".$");
/*
      This is for Unix
      For Windows change to
      sep="\\";
      reg2=new RegExp("\\.*\\");
*/
var sep="/";
var reg2 =new RegExp("\/.*\/");
var extension;
var target;
//
//
//
//      select files from original & target directories
//
      orgDir=fileReadSelect();
      destDir=fileWriteSelect();
      orgDir=pathOnly(orgDir);
      destDir=pathOnly(destDir);
//
//      strip last \\ or //
//
      orgDir=orgDir.replace(reg,"");
      destDir=destDir.replace(reg,"");
      print("orgDir : <"+orgDir+">");
      print("destDir : <"+destDir+">");
//
// Go
//
if(ds.Init(orgDir))
{
  while(ds.NextFile())
  {
      // Only process file we want i.e. AVI
      if(!ds.isNotFile && !ds.isDirectory && !ds.isHidden && !ds.isArchive && !ds.isSingleDot && !ds.isDoubleDot)
      {
          extension=ds.GetExtension();
          if(extension == "avi")
          {
              target=ds.GetFileName();
              target=destDir+sep+target;
              print("***"+ds.GetFileName()+"-->"+target);
              processFile(orgDir+sep+ds.GetFileName(),target);
              }
          //print("File: "+ds.GetFileName()+" is "+ds.GetFileSize()+" bytes, extension "+extension);
      }
  }
  print("We just searched in directory \"" + ds.GetFileDirectory() + "\"");
  ds.Close();
}
else
  displayError("Error initializing the directory search");
displayInfo("Finished !");
function processFile(filename, targetfile)
{
      // Load the file
      app.forceUnpack();
      app.load(filename);
      app.rebuildIndex();
      app.audio.delay=0;
      app.audio.mixer("NONE");
      app.audio.scanVBR();
      app.setContainer("AVI_UNP");
      app.save(targetfile);
      return 1;
}

See also

tutorial/scripting_tutorial.txt · Last modified: 2012/11/11 08:51 (external edit)