Function

Function

The function node allows you to use custom javascript code to process within the flow.

It can let you make decision paths based on previous nodes, compute variables for future nodes, log information, and many more features.

Return codes

  • Return 1+ to specify which output is to be called. Define the number of outputs using the “Outputs” fields. This will add more output connections to the node
  • Return 0 to complete the flow successfully. This will immediately stop the flow and mark it as successful
  • Return -1 to indicate an error and stop the flow. This will mark the flow as unsuccessful.

Members

This is a list of available builtin members available to a function

// Flow object that is executing
Flow: object
// The name of the machine executing this 
Hostname: string
// Logger available to log messages
Logger: object
// Sleep the execution for passed in milliseconds
Sleep: function(millisecond: number)
// Variables that can be used in many textfields
Variables: map

Variables

It includes the “Variables” object which exposes variables from the flow. And you can set future variables for the flow in here

   Varabiles.MyFutureVariable = 'to be used in another flow node';

   // an example of variables from a 'Video Input' node
   let video = Variables.vi.VideoInfo.VideoStreams[0];
   // or a safe way to get that incase any of those objects are null
   let video = Variables.vi?.VideoInfo?.VideoStreams[0];
   if(!video) return -1; // video was null

Logger

Lets you log messages to the flow log

   Logger.ILog('an information log message');
   Logger.WLog('an warning log message');
   Logger.ELog('an error log message');
   Logger.DLog('an debug log message');

Sleep

Allows you to “Sleep” for a specified amount of milliseconds

// Sleep for 10 seconds (10,000 milliseconds)
Sleep(10_000);

Flow

The “Flow” object lets you perform actions on the flow, it exposes helper methods to the code.

   // will create a directory if it does not already exist
   // if it does exist this function simply returns 
   // its a safe way to ensure a directory exists 
   Flow.CreateDirectoryIfNotExists(path);

   // return the size in bytes as a number
   Flow.GetDirectorySize(path); 

   // get/set a parameter value with a given key
   Flow.SetParameter(key, value); 
   Flow.GetParameter(key); 

   // maps a path to the local processing node
   Flow.MapPath(path); 

   // unmaps a path from the local processing node
   Flow.UnMapPath(path);

   // moves the working file to the destination file
   Flow.MoveFile(destination); 

   // this will reset the working file to the original File, 
   // this lets you effectively reprocess the original file.  
   // Useful if you want to perform multiple operations on the same file
   Flow.ResetWorkingFile(); 

   // Sets the current working file to the file passed in
   // don't delete is a boolean that if true will not delete the current working file
   // note: if the current working file is the original file, it will NEVER be deleted
   Flow.SetWorkingFile(filename, dontDelete);

   /// Replaces variables in a given string
   /// @input the input string</param>
   /// @stripMissing if missing variables should be removed</param>
   /// @cleanSpecialCharacters if special characters (eg directory path separator) should be replaced
   /// @returns the string with the variables replaced
   Flow.ReplaceVariables(input: string, stripMissing:bool, cleanSpecialCharacters:bool);
   
   // returns a new GUID as string
   Flow.NewGuid();

   // the full path of the temp path eg /temp/Runner-42f99fc9-158e-408d-9133-de91a56a6ac8
   Flow.TempPath

   // the short name of the temp folder, eg Runner-42f99fc9-158e-408d-9133-de91a56a6ac8
   Flow.TempPathName

   // Gets the temp path on the host if running on docker from the environmental variable "TempPathHost"
   // If not running on docker just returns TempPath
   Flow.TempPathHost

   // the unique identifier of the runner instance eg 42f99fc9-158e-408d-9133-de91a56a6ac8
   // Note: this is used for the TempPathName
   Flow.RunnerUid

   // the original name fo the file that started the flow
   Flow.FileName

   // the relative filename to the library, eg 
   // library /mnt/media/videos
   // full filename /mnt/media/videos/sub/myfile.mkv
   // relative name would be sub/myfile.mkv
   Flow.RelativeFile

   // the fullname of the working file, eg /mnt/media/videos/myfile.mkv
   Flow.WorkingFile

   // The shortname of the working file, eg myfile.mkv
   Flow.WorkingFileName

   // the path of the library the file belongs to
   Flow.LibraryPath

   // Get a variable by it's name.  
   // Note: Variables were formally called "Tools" but to make them more generic they were renamed variables.
   Flow.GetToolPath(toolname);


   // Tests if a input string matches a variable
   // @param variableName The name of the variable
   // @param input the input string
   // @returns true if matches, otherwise false
   Flow.MatchesVariable(variableName: string, input: string);

   // if the flow is running inside a docker container
   Flow.IsDocker

   // if the flow is running on windows
   Flow.IsWindows

   // if the flow is running on linux, will also be true if running inside docker as docker is linux
   Flow.IsLinux
   
   // if the flow is running on mac
   Flow.IsMac
   
   // if the flow is running on an ARM processor
   Flow.IsArm

   /// Copies a file into the temporary directory if it is not already in the temporary directory
   /// @filename [Optional] the filename to copy, if not set the working file will be set
   /// @returns the new filename
   Flow.CopyToTemp(filename);

   // Execute a process and capture the output
   // you can use arguments for a string argument list, or argumentList which is an string array and will escape the arguments for you correctly
   // timeout is optional, number of seconds to wait before killing the process
   // returns ProcessResults
   //    Completed:bool; // if the process ran to completion or timedout/was canceled
   //    ExitCode:number; // the exit code of the process, may be null
   //    Output:string; // the output, if error output was detected this will contain that output
   //    StandardOutput: string; // the standard output from the process
   //    StandardError: string; // the standard error from the process if any
   Flow.Execute({command:'somecommand.exe', arguments: '-a -b -c', argumentList: ['can', 'use', 'instead of arguments'], timeout: 0, workingDirectory: 'optional'});

Flow.Execute

This method allows you to execute any command from within a script.

It takes a ExecuteArgs parameter which has the following properties

/// <summary>
/// The command to execute
/// </summary>
string command;
/// <summary>
/// The arguments of the command
/// </summary>
string arguments;
/// <summary>
/// The arguments of the command as a list and will be correctly escaped
/// </summary>
string[] argumentList;
/// <summary>
/// The timeout in seconds of the process
/// </summary>
int timeout;
/// <summary>
/// When silent, nothing will be logged
/// </summary>
bool silent;
/// <summary>
/// The working directory of the process
/// </summary>
string workingDirectory;

Samples

Different outputs based on file size

   if(Variables.file.Size > 10_000_000_000) // 10GB
   	return 1; // output 1
   if(Variables.file.Size > 2_000_000_000) // 2GB
   	return 2; // output 2

   let reducedSize = (Variables.file.Size / Variables.file.Orig.Size) * 100;
   if(reducedSize < 10)
   	return 0; // its too small, something went wrong

   return 3; // output 3

Example showing using the Flow.Execute

    // define the output file, in the temp directory with a guid as the name
    let output = Flow.TempPath + '/' + Flow.NewGuid() + '.mkv';
    // get the ffmpeg tool path
    let ffmpeg = Flow.GetToolPath('ffmpeg');
    // execute the process and capture the result
    let process = Flow.Execute({
    	command: ffmpeg,
      workingDirectory: '/media/my-working/directory',
    	argumentList: [
    		'-i',
    		Variables.file.FullName,
    		'-c:v',
    		'libx265',
    		'-c:a',
    		'copy',
    		output
    	]
    });
    
    // log the standard output/error if found
    if(process.standardOutput)
    	Logger.ILog('Standard output: ' + process.standardOutput);
    if(process.starndardError)
    	Logger.ILog('Standard error: ' + process.starndardError);
    
    // check the exit code of the process
    if(process.exitCode !== 0){
    	Logger.ELog('Failed processing ffmpeg: ' + process.exitCode);
    	return -1;
    }
    
    // update the working file to the newly created file from ffmpeg
    Flow.SetWorkingFile(output);
    return 1;

Copying files in a Function

// file here is a FileInfo object which makes it easy to get the short filename (file.Name)
for(let file in new System.IO.DirectoryInfo('/mnt/source').GetFiles('*.*'))
{
   System.IO.File.Copy(file.FullName, '/mnt/destination/' + file.Name);
}

// alternative, where file is a string of the full filename
for(let file in System.IO.Directory.GetFiles('/mnt/source', '*.*')
{
   System.IO.File.Copy(file, '/mnt/destination/' + file.substring(file.lastIndexOf('/') + 1));
}

Note: This uses C# to do the copy and look for files

© 2022 FileFlows