Skip to main content
New Participant
June 29, 2015
Question

DPX sequence to MOV script with Audio & TC - Batch not working

  • June 29, 2015
  • 1 reply
  • 1362 views

Can please someone here help me out on this topic, i am new to AFX/java scripting and i already spent around 15h on that

subject but it simply does not work-

the background:

we are shooting DPX sequences with a Convergent Design ODYSSEY SSD recorder, thats the only way for it to get perfect

image quality inside the box, i want 4:4:4 and RGB together with minimal compression (and the box is not yet able to do ProRes4444).

For editing/finishing purpose it is way easier to work with .MOV files instead of image sequences (as we are producing around 100.000 DPX files a day,

compared to around 80 .MOV files)

the task:

create a script that imports a DPX sequence from a folder,

imports the corresponding .WAV file with same starting name too,

creates a new timeline in AFX "from DPX sequence selection" (to keep the timcode!)

renders that timeline with a given output module to another given folder

deletes all items and projects afterwards

Somehow, I managed to do that, it works most of the time but function "app.executeCommand(app.findMenuCommandId("New Comp from Selection"

seems to be buggy somehow, does not work everytime or just after you did that at least once manually inside AFX ?

the bonus task (thats where i failed)

create a folder selection dialog that reads all subfolders (with the corresponding DPX sequences inside) to an array

use that array to get the sequence file names and count the number of Sub-directories

do the above (Seq conversion from "the task") to ALL THOSE SUBDIRECTORIES (using the names from the array)

this cant be that complex ... right ???

i tried to implement it but somehow i always get the error "/e/ODYSSEY/S020_AK0787/S020_AK0787_0000000.dpx is not a File or Folder"

(as this is the image sequence that should be imported - there must be some wrong interpretation between the file name with whole filepath and

the import function ?)

Any help is hugely appreciated, i am also willing to donate for help/a working script

(as i cannot afford to enter around 1.000 folders by myself)


i can also provide such a Odyssey file structure for testing/help purposes via wetransfer

thanks

Script below:

_______________________________________________________

var SourceFolder = Folder.selectDialog("Choose SOURCE folder: ");

var SourcePath = decodeURI(SourceFolder.toString()); 

var DestFolder = Folder.selectDialog("Choose DESTINATION folder: ");   

var DestPath = decodeURI(DestFolder.toString()); 

var scriptName = "DPX Sequence TO MOV DNxHD with Audio + TC";

var intendedFootageFPS = 25;

var fileToImport, fileToImport2;sidecarFile, sidecarContents, importOpts, footageItem, filePath, fileBaseName, audioFile, audioFootageItem;

var FolderName, SourcePath;

var scriptName = "Change Render Locations";

function checkForFiles(folderItem, tabString) {

    var theFiles = folderItem.getFiles();

    for(var c = 0; c < theFiles.length; c++){

        //resultArray.push(tabString + theFiles.name + "\r");

        resultArray.push(tabString + theFiles.name);

        //if (theFiles instanceof Folder)

        {

           // checkForFiles(theFiles, tabString + "\t");

        }

    }

}

function AFXConvert(FolderName) {  

   

     app.newProject();

//     fileToImport = File.openDialog("Select file from the DPX sequence", "*.dpx", false);

//    if (!fileToImport || !fileToImport.exists) {

//    }

    app.beginUndoGroup(scriptName);  

     app.project.showWindow = true;

    

     fileToImport2 = (SourcePath + "/"+ e + "/" + e + "_0000000.dpx");

     alert("Folder Import Name " + fileToImport2);

         

     importOpts = new ImportOptions(fileToImport2);

    importOpts.sequence = true;    // import as sequence

    importOpts.forceAlphabetical = true;    // force alphabetical order (to work around 3709647)

  

    

    app.project.importFile(importOpts);

   

     app.executeCommand(app.findMenuCommandId("New Comp from Selection"));

     //app.executeCommand(app.findMenuCommandId("New Comp from Selection")); //sometimes it works better with 2  or 3x ???

     //app.executeCommand(app.findMenuCommandId("New Comp from Selection"));

    footageItem.name = decodeURI(fileToImport2.name).replace(/\.\d+\.png/, "");    // remove the numeric part for the footage item name

    footageItem.mainSource.conformFrameRate = 25;

    // if matching audio recording (WAV file), import that

   

    filePath = footageItem.file.path;

    fileBaseName = (footageItem.file.name).replace("_0000000.dpx","");

    audioFile = new File(filePath + "/" + fileBaseName + ".WAV");

    audioFootageItem = app.project.importFile(new ImportOptions(audioFile));

    comp = app.project.item(1).layers.add(audioFootageItem);

    audioFootageItem.selected = true;

    

    comp.selected = true;        

    comp = app.project.item(1);

    comp.openInViewer();

    app.project.item(1).layer(2).moveToBeginning();

   

    app.endUndoGroup();

   

    app.project.renderQueue.items.add(comp);

    app.project.renderQueue.item(1);

    app.project.renderQueue.item(1).outputModule(1).file = new File("D:/" + e + ".MOV");

    //alert("d:/" + fileBaseName + ".MOV");

    app.project.renderQueue.item(1).outputModule(1).applyTemplate("QUICKTIME DNxHD 365 RGB444 Audio");       

    app.project.renderQueue.item(1).outputModule(1).postRenderAction.NONE;  

    app.project.renderQueue.render(1);

    app.project.renderQueue.item(1).remove()

    app.project.item(1).remove();

    app.project.item(1).remove();

    app.project.item(1).remove();

   

}

//----------------------------------------------------------------------------------------------------------------------------

//PROGRAM START

//----------------------------------------------------------------------------------------------------------------------------

app.project.close(CloseOptions.DO_NOT_SAVE_CHANGES);

if(SourceFolder != null){

    var resultArray = new Array(1);   //clear old array to 1 entry    

    var resultArray = new Array();   

    checkForFiles(SourceFolder, "");

    $.writeln(resultArray.toString().replace("",""));

    //alert(resultArray);

    var FolderCount = resultArray.length; 

    alert("Number of folders: " + FolderCount);   

    }

    if(DestFolder != null){     //Makes sure root folder choice was not canceled 

      var d1 = resultArray.toString();          

    } 

//----ENCODING LOOP  ----------------------------------------------------------

var e = resultArray.shift();

for(var k=0; k<FolderCount; k++){         

              alert("Array/Folder Counter: " + k +":" + e);

              //resultArray.toString(resultArray);            

              fObj = Folder(DestPath + "/"+ e);

              fObj.create();             

              AFXConvert(e);

              var e = resultArray.shift();

             

     }           

This topic has been closed for replies.

1 reply

Brainiac
July 3, 2015

It's not exactly what you describe, but it may be a good foundation to modify from. I put this together for my own internal batch processing of DPX sequences into Quicktime movies. There are three variables at the top that need to be manually changed for the render output names and structure. I've also only used this on Mac, so I'm not sure if it works on Windows properly yet.

{

try{

/*

    MANUALLY TYPE IN THE VALUES FOR THE NEXT VARIABLES--------------------

*/

var renderSettingChoice = "Best Settings";

var outputModuleChoice = "Client_LowRezPreview";

var fileNameExpression = "[projectName]_[compName].[fileExtension]";    //Uses After Effects "Output To" syntax

/*

    END USER INPUT--------------------------------------------------------------------------------

*/

var os = ($.os.indexOf("Mac") != (-1));    //True is MAC, false is PC

var sep = (os == true) ? "/" : "\\";

var dpxFolder = Folder.selectDialog("Choose folder containing source DPX folders.");

var renderToFolder = Folder.selectDialog("Select folder to render to.");

var globalFPS = 25;

if(dpxFolder != null){

    if(renderToFolder != null){

        //Declare Variables

        var allSubFolders, allSubFoldersLen, curFolder, dpxFrames, dpxFramesLen, curDPXFrame, nameSplit, dpxFramesCollect, dpxFramesCollectLen, dpxName, dpxDuration, dpxStartFrame, dpxFPS, io, dpxImported, newDPXComp, newQueueItem, fullFilePath;

        allSubFolders = dpxFolder.getFiles();    //Get all files inside folder

        allSubFoldersLen = allSubFolders.length;

        dpxFramesCollect = new Array();

      

        app.beginUndoGroup("Convert DPX to QT");

            //Process Main folder

            for(var f=0; f<allSubFoldersLen; f++){

                dpxFramesCollect.length = 0;

                curFolder = allSubFolders;

                dpxName = curFolder.displayName;

                //Begin per DPX seq processing

                if(curFolder instanceof Folder){    //Verify item is a folder object otherwise skip to next item

                    dpxFrames = curFolder.getFiles();    //Get all DPX frames

                    dpxFramesLen = dpxFrames.length;

                    for(var d=0; d<dpxFramesLen; d++){

                        curDPXFrame = dpxFrames;

                        nameSplit = curDPXFrame.displayName.split(".");

                        ext = nameSplit[nameSplit.length-1];

                        if(ext == "DPX" || ext = "dpx"){    //Verify file is a DPX frame

                            dpxFramesCollect.push(curDPXFrame);

                        }

                    }

                    dpxFramesCollectLen = dpxFramesCollect.length;

                    dpxFramesCollect.sort();

                    if(dpxFramesCollectLen > 0){    //Checks if more than 0 DPX frames exists.

                        firstFrame = dpxFramesCollect[0];

                        dpxFPS = globalFPS;

                      

                        io = new ImportOptions(firstFrame);

                        io.sequence = true;

                        dpxImported = app.project.importFile(io);

                        dpxImported.mainSource.conformFrameRate = dpxFPS;

                      

                        newDPXComp = app.project.items.addComp(dpxName, dpxImported.width, dpxImported.height, dpxImported.pixelAspect, dpxImported.duration, dpxFPS);    //Makes new comp

                            dpxStartFrame = (Number(firstFrame.displayName.split(".")[1]) * newDPXComp.frameDuration) + 0.01;     //0.01 helps fix (mostly) the frameDuration math

                            newDPXComp.displayStartTime = dpxStartFrame;

                        newDPXComp.layers.add(dpxImported);    //Adds footage to comp

                        newQueueItem = app.project.renderQueue.items.add(newDPXComp);    //Adds comp to renderqueue

                        newQueueItem.applyTemplate(renderSettingChoice);

                        newQueueItem.outputModule(1).applyTemplate(outputModuleChoice);

                        fullFilePath = renderToFolder.toString() + sep + dpxName;

                        if(!fullFilePath.exists){    //Creates render folder if it does not already exist

                            Folder(fullFilePath).create();

                        }

                        newQueueItem.outputModule(1).file = File(fullFilePath + sep + fileNameExpression);    //Sets Output To file

                    }

                }

            }

        app.endUndoGroup();

    }else{

        alert("Folder selection for rendering was canceled.");

    }

}else{

    alert("DPX folder selection was canceled.");

}

}catch(e){alert(e.line.toString() + "\n" + e.toString())}

}

New Participant
July 3, 2015

Thank you David, appreciate it!

I will check it out on the weekend and report back to you :-)

Inspiring
July 6, 2015

This will not work if the filename has any periods in it:

nameSplit = curDPXFrame.displayName.split(".");

This is a much better way to detect an extension in a filename:

nameSplit = curDPXFrame.displayName.match(/[^\.]+$/);

And this will match regardless of case:

if(ext.toUpperCase() == "DPX"){ 

Cheers,
Lloyd