AfterEffect(AE)插件是Adobe公司开发的特效制作软件,稳定快速的功能和特效,在视频制作领域使用非常广泛,本文向大家介绍如何在项目里进行命令行渲染功能。源代码如下所示:

// Command line renderer for After Effects.// This function constructs an AECommandLineRenderer object.
// One and only one of these will be created to perform rendering tasks
// at the end of this file.
//
// The constructor has 3 sections:
// [1] define all the variable-type attributes used by this class;
// [2] define all the functions used by this class;
// [3] assign all the functions to be method-type attributes.
//
function AECommandLineRenderer()
{// [1] define all the variable-type attributes used by this class//// Input before parsing//this.inArgs = null;//// Input after parsing//this.in_project_path     = null;this.in_teamproject_name    = null;this.in_comp_name           = null;this.in_rq_index            = null;this.in_RStemplate          = null;this.in_OMtemplate          = null;this.in_output_path         = null;this.in_logfile_path        = null;this.in_start_frame         = null;this.in_end_frame           = null;this.in_increment           = null;this.in_image_cache_percent = null;this.in_max_mem_percent     = null;this.in_verbose_flag        = null;this.in_close_flag          = null;this.in_sound_flag          = null;this.in_port_address        = null;this.in_stop_on_missing_frame = true;//// Exit codes://this.EXIT_OK                                = 0;this.EXIT_FAILURE_CODE_FROM_APP                = 1;this.EXIT_SHOW_USAGE                       = 2;this.EXIT_SYNTAX_ERROR                     = 3;this.EXIT_SYNTAX_ERROR_USER_LOG                = 4;this.EXIT_OTHER_SCRIPTING_ERROR                = 5;this.EXIT_OTHER_SCRIPTING_ERROR_USER_LOG   = 6;this.EXIT_AERENDER_RUNTIME                 = 7;this.EXIT_AERENDER_RUNTIME_USER_LOG            = 8;this.EXIT_AE_RUNTIME                       = 9;this.EXIT_AE_RUNTIME_USER_LOG              = 10;this.EXIT_CANNOT_OPEN_SOCKET              = 11;this.EXIT_CODE_NO_LONGER_IN_USE               = 12;//// Exit code message prefixes://this.EXIT_MSG_PREFIX = new Array("",                 // EXIT_OK"ERROR: ",          // EXIT_FAILURE_CODE_FROM_APP"USAGE: ",           // EXIT_SHOW_USAGE"SYNTAX ERROR: ",   // EXIT_SYNTAX_ERROR"SYNTAX ERROR: ", // EXIT_SYNTAX_ERROR_USER_LOG"ERROR: ",           // EXIT_OTHER_SCRIPTING_ERROR"ERROR: ",           // EXIT_OTHER_SCRIPTING_ERROR_USER_LOG"ERROR: ",          // EXIT_AERENDER_ERROR"ERROR: ",          // EXIT_AERENDER_ERROR_USER_LOG"ERROR: ",         // EXIT_AE_RUNTIME"ERROR: ",          // EXIT_AE_RUNTIME_USER_LOG"ERROR: ",         // EXIT_CANNOT_OPEN_SOCKET"",                 // EXIT_CODE_NO_LONGER_IN_USE);//// Messages://this.MSG_NONE                        = "";this.MSG_NOT_HANDLED_HERE           = "reported by another script or AE runtime.";this.MSG_SHOW_USAGE                    = "";this.MSG_TRIED_TO_PARSE_UNDEFINED   = "aerender tried to parse an undefined argument.";this.MSG_UNDEFINED_VALUE_FOR_FLAG = "no value given for flag: "; this.MSG_BAD_FLAG                 = "Illegal argument flag: ";this.MSG_NO_PROJECT                  = "No project provided and no project open.";this.MSG_BAD_VERBOSE_FLAG           = "Bad value for -verbose.";this.MSG_BAD_CLOSE_FLAG              = "Bad value for -close.";this.MSG_BAD_SOUND_FLAG                = "Bad value for -sound.";this.MSG_BAD_INCREMENT             = "Bad value for -increment. Must be between 1 and 100, inclusive.";this.MSG_COMP_NOT_FOUND              = "No comp was found with the given name.";this.MSG_RQINDEX_NOT_FOUND            = "No render queue item was found with the given index.";this.MSG_AE_RUNTIME                 = "Runtime error in After Effects.";this.MSG_ADDING_TO_RQ                = "PROGRESS: Adding specified comp to Render Queue";this.MSG_NEEDS_OUTPUT                = "Specified render queue item needs output file but none provided.";this.MSG_RS_TEMPLATE_NOT_FOUND      = "No render settings template was found with the given name.";this.MSG_OM_TEMPLATE_NOT_FOUND        = "No output module template was found with the given name.";this.MSG_CAN_NOT_OPEN_SOCKET        = "Can not open socket.";this.MSG_NO_COMP_YES_TEMPLATE       = "WARNING: -RStemplate argument ignored since no -comp or -rqindex provided.";this.MSG_NO_COMP_YES_OMTEMPLATE       = "WARNING: -OMtemplate argument ignored since no -comp  or -rqindex provided.";this.MSG_NO_COMP_YES_OUTPUT          = "WARNING: -output argument ignored since no -comp  or -rqindex provided.";this.MSG_NO_COMP_YES_START_OR_END    = "WARNING: -s and/or -e arguments ignored since no -comp  or -rqindex provided.";this.MSG_NO_COMP_YES_INCREMENT     = "WARNING: -i argument ignored since no -comp  or -rqindex provided.";this.MSG_SKIPPING_WILL_CONTINUE       = "INFO: Skipping render queue item with correct comp name but marked to continue from a partly complete render.";this.MSG_RENDER_ABORTED                = "INFO: Render aborted.";// These three don't get the prefix printed since they are not exit messagesthis.MSG_LOG_DIR_NO_EXISTS            = "aerender ERROR: Directory specified for log file does not exist: ";this.MSG_LOG_DIR_NOT_A_DIR         = "aerender ERROR: Directory specified for log file is a file, not a directory: ";this.MSG_LOG_CAN_NOT_OPEN          = "aerender ERROR: Can not open log file. Try checking write protection of directory: ";//// Variables for rendering//this.log_file              = null;this.has_user_log_file      = false;this.is_verbose_mode       = true;this.saved_sound_setting    = null;this.my_sound_setting       = null;// [2] define all the functions used by this class//// Report an error. This writes errors to the log file, if present.// This is called from the context of the application, so we// need to precede variable names with gAECommandLineRenderer// function checkParentDied(){var result = false;if(gAECommandLineRenderer.log_file instanceof Socket) {if(! gAECommandLineRenderer.log_file.connected) {app.project.renderQueue.stopRendering();  result = true;}}      return result;}function my_onError(error_string, severity_string){// This method is called with a variety of types of messages.// The severity_string tells us what kind.// Choices are:// NAKED, INFO, WARNING, PROBLEM, FATAL, PROGRESS, and DEBUG// Two of these, PROBLEM and FATAL, are errors that should cause us to change// the exit code:checkParentDied();if (severity_string == "PROBLEM" || severity_string == "FATAL") {// These two errors cause us to change the exit code.// We don't write an error or throw here, because we got here as part of a thrown // error already, and the message will be printed as part of the catch.gAECommandLineRenderer.SetExitCode(gAECommandLineRenderer.EXIT_AE_RUNTIME);} else {// PROBLEM and FATAL will throw exceptions, and so will be logged to the file// when we catch the exception.// All other errors (NAKED, INFO, WARNING, PROGRESS, and DEBUG) will not // throw exceptions.  So we log them to the file right here:if (gAECommandLineRenderer.is_verbose_mode) {if (gAECommandLineRenderer.log_file != null) {if (severity_string == "NAKED") {// everybody is confused by this category.  Just use INFO instead.gAECommandLineRenderer.log_file.writeln("INFO:" + error_string);} else {gAECommandLineRenderer.log_file.writeln(severity_string + ":" + error_string);}}}}// call the error handler that was in place before we started rendering.if (gAECommandLineRenderer.oldErrorHandler) {gAECommandLineRenderer.oldErrorHandler(error_string,severity_string);}}// Report an error and throw an exception.// Causes the script to exit.function my_SetExitCodeAndThrowException(code, message){this.SetExitCode(code);throw (this.EXIT_MSG_PREFIX[code] + message);}// Report an error. This establishes exitCodes for reporting errors from AfterFX.function my_SetExitCode(code){// Some codes are set differently depending on whether we have a custom user // log file.  Check for these and use the alternate if appropriate.var real_code = code;if (gAECommandLineRenderer.has_user_log_file) {switch (real_code) {case gAECommandLineRenderer.EXIT_SYNTAX_ERROR:real_code = gAECommandLineRenderer.EXIT_SYNTAX_ERROR_USER_LOG;break;case gAECommandLineRenderer.EXIT_OTHER_SCRIPTING_ERROR:real_code = gAECommandLineRenderer.EXIT_OTHER_SCRIPTING_ERROR_USER_LOG;break;case gAECommandLineRenderer.EXIT_AERENDER_RUNTIME:real_code = gAECommandLineRenderer.EXIT_AERENDER_RUNTIME_USER_LOG;break;case gAECommandLineRenderer.EXIT_AE_RUNTIME:real_code = gAECommandLineRenderer.EXIT_AE_RUNTIME_USER_LOG;break;}}// Always keep the first error. So only set if the exitCode is still EXIT_OK.if (app.exitCode == gAECommandLineRenderer.EXIT_OK) {app.exitCode = real_code;}}// Arguments may be enclosed in quotes.  This // will remove them and return the result.function my_StripAnyEnclosingQuotes(inString){var result = inString;if (inString && inString.charAt(0) == '"' && inString.charAt(inString.length-1) == '"') {result = inString.substring(1,inString.length-1);}return result;}// Make sure the value is there, and returns it, stripping away any enclosing quotes.//function my_GetValueForFlag(arg_num, the_flag){if (!this.inArgs[arg_num]) {this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, (this.MSG_UNDEFINED_VALUE_FOR_FLAG + the_flag));}return this.StripAnyEnclosingQuotes(this.inArgs[arg_num]);}// Parse the parameter.// Return the number of arguments used in parsing the parameter.function my_ParseParamStartingAt(arg_num){if (!this.inArgs[arg_num]) {this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_TRIED_TO_PARSE_UNDEFINED);}var num_args_parsed = 0;// Check for a valid flag:var my_flag = this.inArgs[arg_num];if (my_flag == "-port") {// -port is used by aerender to specify a port address for a socket.//// Note: this value is sought/parsed earlier, in the SetupDefaultLog method.// We can just ignore here.var dummy  = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-project") {this.in_project_path   = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-teamproject") {this.in_teamproject_name   = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-comp") {this.in_comp_name   = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-rqindex") {this.in_rq_index   = parseInt(this.GetValueForFlag(arg_num+1,my_flag));num_args_parsed = 2;}if (my_flag == "-RStemplate") {this.in_RStemplate   = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-OMtemplate") {this.in_OMtemplate   = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-output") {this.in_output_path = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-log") {this.in_logfile_path = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-s") {this.in_start_frame = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-e") {this.in_end_frame = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-i") {this.in_increment = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-mem_usage") {this.in_image_cache_percent   = this.GetValueForFlag(arg_num+1,my_flag);this.in_max_mem_percent     = this.GetValueForFlag(arg_num+2,my_flag);num_args_parsed = 3;}if (my_flag == "-v") {this.in_verbose_flag = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-close") {this.in_close_flag = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-sound") {this.in_sound_flag = this.GetValueForFlag(arg_num+1,my_flag);num_args_parsed = 2;}if (my_flag == "-doSavePrefsOnQuit") {// The effect of this flag will be taken into account when we// exit the app. See comment in the "finally" block.// All we do here is increment the num_args_parsed count.num_args_parsed = 1;}if (my_flag == "-continueOnMissingFootage") {this.in_stop_on_missing_frame = false;num_args_parsed = 1;}if (num_args_parsed == 0) {this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, (this.MSG_BAD_FLAG + my_flag));}return num_args_parsed;}// This parses the inArgs array.  Assumes// the array has already been filled.function my_ParseInArgs(){// First, undefine all the inputs we're potentially looking forthis.in_project_path     = null;this.in_teamproject_name    = null;this.in_comp_name           = null;this.in_rq_index            = null;this.in_RStemplate          = null;this.in_OMtemplate          = null;this.in_output_path         = null;this.in_logfile_path        = null;this.in_start_frame         = null;this.in_end_frame           = null;this.in_increment           = null;this.in_image_cache_percent = null;this.in_max_mem_percent     = null;this.in_verbose_flag        = null;this.in_close_flag          = null;this.in_sound_flag          = null;// Special case: check if any argument is "-help"for (var i = 0; i < this.inArgs.length; i++) {if (this.inArgs[i] == "-help") {this.SetExitCodeAndThrowException(this.EXIT_SHOW_USAGE, this.MSG_SHOW_USAGE);}}var arg_num = 0; while (arg_num < this.inArgs.length) {// ParseParamStartingAt returns the number of arguments used up parsing the param.arg_num += this.ParseParamStartingAt(arg_num);}}// This arg is treated differently than others because it's extra important// that we exit properly in the face of anything that might go wrong even// during initialization. So we don't parse the standard way, we check this// before exit...function my_IsSavePrefsArgGiven(arglist){return this.IsInArray("-doSavePrefsOnQuit", arglist);}// Returns true if the item equals an item in the array, false if otherwise.function my_IsInArray(needle, haystack){result = false;for (var i = 0; i < haystack.length; i++) {if (needle == haystack[i]) {result = true;break;}}return result;}function my_SetupDefaultLog(arg_list){this.has_user_log_file = false;// Clean up after a potentially bad exit last time:if (this.log_file && this.log_file != null) {this.log_file.close();this.log_file = null;}// Open the socket.// It is used:// [a] to log errors if there is no user-specified log file (specified with a "-log" arg)// [b] to log errors encountered while opening any user-specified log file.// See if a -port argument was passed:this.log_file = null;for (var i = 0; i < arg_list.length; i++) {if (arg_list[i] == "-port") {if (arg_list.length > i+1) {// The argument value is the port addressthis.in_port_address = arg_list[i+1];// Yes, the log_file variable is being used to hold a socket.this.log_file = new Socket();// cprosser [26961]// could possibly use ISO-8856-1 for non japanese systems,// but I am going for small changes now.// and again cprosser 8/8/2005 [33884]// CP_OEMCP means use the OEM code page, the default// for the console.// alas, it doens't understand that so we are hardcoding// codepage 850. Not the default on windows for US systems// but should be the default on european systems and will// get the high ascii correct.// Search for chcp at microsoft for info on changing// the console.// on the mac, leave as binaryvar encoding_string = "binary";if (system.osName.search("Windows") != -1) {encoding_string = "WINDOWS-850";//encoding_string = "CP_OEMCP";}if (app.language == Language.JAPANESE) {encoding_string = "Shift-JIS";    }if (app.isoLanguage == "ko_KR") {encoding_string = "EUC-KR";                        }if (!this.log_file.open(this.in_port_address,encoding_string)) {this.log_file = null;this.SetExitCodeAndThrowException(this.EXIT_CANNOT_OPEN_SOCKET, this.MSG_CAN_NOT_OPEN_SOCKET);}}}}this.is_verbose_mode   = true;}function my_CleanupDefaultLog(){// Close the log fileif (this.log_file != null) {this.log_file.close();this.log_file = null;}}// This is the external entry point.// Bat files or executables may call this method.//// This function assumes that it has been passed all the arguments.// It parses the arguments and then renders.function my_Render() {app.beginSuppressDialogs();if(checkParentDied()) {return;}try {this.SetupDefaultLog(my_Render.arguments);// start by assuming successful execution, exit code 0.app.exitCode = 0;// Check number of argumentsif (!my_Render.arguments || my_Render.arguments.length == 0) {this.SetExitCodeAndThrowException(this.EXIT_SHOW_USAGE, this.MSG_SHOW_USAGE);}var numArgs = my_Render.arguments.length;// Allocate the array of arguments:this.inArgs = new Array(numArgs);// Load the input arguments into the inArgs array.for (var i = 0; i < numArgs; i++) {this.inArgs[i] = my_Render.arguments[i];}// Parse the arguments, and renderthis.ParseInArgs();if(checkParentDied()) {return;}this.ReallyRender();} catch(error) {// Add any errors to the log file.if (this.log_file != null) {this.log_file.writeln("aerender " + error.toString());}this.SetExitCode(this.EXIT_AE_RUNTIME);} finally {// This arg is treated differently than others because it's extra important// that we exit properly in the face of anything that might go wrong even// during initialization. So we don't parse the standard way, we check this// before exit...app.setSavePreferencesOnQuit(this.IsSavePrefsArgGiven(my_Render.arguments));this.CleanupDefaultLog();app.endSuppressDialogs(false);app.reportErrorOnMissingFrame = false;}}function my_ReallyRender(){this.saved_sound_setting = null;app.reportErrorOnMissingFrame =  this.in_stop_on_missing_frame;try {// While rendering we'll report errors to the log file.if (app.onError == this.onError) {// If the previous error handler is just this one, don't store it. // That can happen in extreme cases where this script does not get a// chance to clean up and put back the oldErrorHandler when it's done.this.oldErrorHandler = null;} else {this.oldErrorHandler = app.onError;}app.onError = this.onError;// Open the user log file, if specified, and use it instead of the socket.if (this.in_logfile_path) {// Keep the socket open; errors we encounter while opening the// user log file will be logged to the socket.var user_log_file = new File(this.in_logfile_path);var parent_dir = user_log_file.parent;if (!parent_dir.exists) {if (this.log_file) {this.log_file.writeln(this.MSG_LOG_DIR_NO_EXISTS + this.in_logfile_path);}this.SetExitCodeAndThrowException(this.EXIT_AE_RUNTIME, this.MSG_AE_RUNTIME);}var test_folder = Folder(parent_dir);if (!(test_folder instanceof Folder)) {if (this.log_file) {this.log_file.writeln(this.MSG_LOG_DIR_NOT_A_DIR + this.in_logfile_path);}this.SetExitCodeAndThrowException(this.EXIT_AE_RUNTIME, this.MSG_AE_RUNTIME);}if (!user_log_file.open("w",'TEXT','ttxt')) {if (this.log_file) {this.log_file.writeln(this.MSG_LOG_CAN_NOT_OPEN + this.in_logfile_path);}this.SetExitCodeAndThrowException(this.EXIT_AE_RUNTIME, this.MSG_AE_RUNTIME);}// no errors were encountered opening the file.// Close the socket and use this one instead.if (this.log_file != null) {this.log_file.close();}this.log_file = user_log_file; // which is still openthis.has_user_log_file = true;}if (this.in_verbose_flag) {if (this.in_verbose_flag == "ERRORS") {this.is_verbose_mode   = false;} else if (this.in_verbose_flag == "ERRORS_AND_PROGRESS") {this.is_verbose_mode   = true;} else {this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, this.MSG_BAD_VERBOSE_FLAG);}}if (this.in_close_flag) {if (this.in_close_flag != "DO_NOT_CLOSE" &&this.in_close_flag != "DO_NOT_SAVE_CHANGES" &&this.in_close_flag != "SAVE_CHANGES") {this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, this.MSG_BAD_CLOSE_FLAG);}}if (this.in_sound_flag) {if (this.in_sound_flag != "ON" &&this.in_sound_flag != "OFF" &&this.in_sound_flag != "on" &&this.in_sound_flag != "off") {this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, this.MSG_BAD_SOUND_FLAG);}}// Set the memory usage, if specified as an argument.if (this.in_image_cache_percent && this.in_max_mem_percent) {app.setMemoryUsageLimits(this.in_image_cache_percent, this.in_max_mem_percent);}// If the user provided a project, close the current project and open the project specified.// Else, leave the current project open.if (this.in_project_path) {// Close the current projectif (app.project != null) {app.project.close(CloseOptions.DO_NOT_SAVE_CHANGES);}// Open the specified project:var proj_file = new File(this.in_project_path);app.openFast(proj_file);}if (!app.project) {this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_NO_PROJECT);}// If the user provided a teamproject, close the current project and open the teamproject specified.// Else, leave the current project open.if (this.in_teamproject_name) {// Close the current projectif (app.project != null) {app.project.close(CloseOptions.DO_NOT_SAVE_CHANGES);}// Open the specified team project:app.openTeamProject(this.in_teamproject_name);}if (!app.project) {this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_NO_PROJECT);}// Get the RenderQueueItem for the specified comp, if specified.var rqi = null;if (this.in_comp_name) {rqi = this.GetFirstQueuedRQItemWithName(this.in_comp_name);} else if (this.in_rq_index != null) {this.log_file.writeln("rqindex " + this.in_rq_index+ "num " + app.project.renderQueue.numItems);if (this.in_rq_index >= 1 && this.in_rq_index <= app.project.renderQueue.numItems) {rqi = app.project.renderQueue.item(this.in_rq_index);} else {this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_RQINDEX_NOT_FOUND);}}if (this.in_comp_name && !rqi) {// Try to find the comp in the project and add to the render queue:rqi = this.AddCompToRenderQueue(this.in_comp_name);if (rqi) {if (this.log_file != null) {this.log_file.writeln(this.MSG_ADDING_TO_RQ);}} else {this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_COMP_NOT_FOUND);}}// Apply the templates, if providedif (this.in_RStemplate) {if (!rqi) {if (this.log_file != null) {this.log_file.writeln(this.MSG_NO_COMP_YES_TEMPLATE);}} else {if (!this.IsInArray(this.in_RStemplate, rqi.templates)) {this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_RS_TEMPLATE_NOT_FOUND);}rqi.applyTemplate(this.in_RStemplate);}}if (this.in_OMtemplate) {if (!rqi) {if (this.log_file != null) {this.log_file.writeln(this.MSG_NO_COMP_YES_OMTEMPLATE);}} else {if (!this.IsInArray(this.in_OMtemplate, rqi.outputModule(1).templates)) {this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_OM_TEMPLATE_NOT_FOUND);}rqi.outputModule(1).applyTemplate(this.in_OMtemplate);}}// If a comp was specified, make it the only one to render.// If none was provided, leave everything alone so render queue renders as is.if (rqi) {this.EstablishAsOnlyQueuedItem(rqi);}if (rqi) {// If the user provided a path, set the output path on rqi's OutputModuleif (rqi.status == RQItemStatus.NEEDS_OUTPUT && !this.in_output_path) {this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_NEEDS_OUTPUT);}if (this.in_output_path) {var om = rqi.outputModule(1);om.file = new File(this.in_output_path);}} else {if (this.in_output_path) {if (this.log_file != null) {this.log_file.writeln(this.MSG_NO_COMP_YES_OUTPUT);}}}// Set the start and end frames.if (this.in_start_frame || this.in_end_frame) {if (!rqi) {if (this.log_file != null) {this.log_file.writeln(this.MSG_NO_COMP_YES_START_OR_END);}} else {// Render times are stored as timeSpanStart and timeSpanDuration.// Setting only the timeSpanStart will not change the timeSpanDuration and // so will move the end time, but we want the end time unchanged if // it was not specified.// So we must calculate both start_time and end_time, // then set both timeSpanStart and timeSpanDuration.// Note: frameDuration is stored in the comp.var start_time = rqi.timeSpanStart;var end_time   = rqi.timeSpanStart + rqi.timeSpanDuration;if (this.in_start_frame) {start_time = -rqi.comp.displayStartTime + ((parseInt(this.in_start_frame,10) - app.project.displayStartFrame) * rqi.comp.frameDuration);}if (this.in_end_frame) {// The way AE works, final frame is not included.// But aerender wants final frame included.// So, just add 1 to end frame right here before setting// duration for AE:// Note: must call parseInt() here, or the 1 will be added as if it// were a string. For example, 35 would become 351, not 36. Hoo boy!var end_frame_plus_one = parseInt(this.in_end_frame,10) + 1.0 - app.project.displayStartFrame;end_time = -rqi.comp.displayStartTime + (end_frame_plus_one * rqi.comp.frameDuration);}rqi.timeSpanStart = start_time;rqi.timeSpanDuration = end_time - start_time;}}// Set the skipFrames (based on increment).if (this.in_increment) {if (this.in_increment < 1 || this.in_increment > 100) {this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, this.MSG_BAD_INCREMENT);}if (!rqi) {if (this.log_file != null) {this.log_file.writeln(this.MSG_NO_COMP_YES_INCREMENT);}} else {// Set the skipFrames based on the increment.//// Increment as defined here is one greater then the// the render queue item's skipFrames.// skipFrames 0 is the same as increment of 1.// rqi.skipFrames = (this.in_increment - 1);}}// If we are in verbose mode, set the log type to ERRORS_AND_PER_FRAME_INFO // for all RQ items we are about to render.if (this.is_verbose_mode) {this.SetLogPerFrameInfoInRQ();}this.SaveAndSetRenderSoundSetting();// Render!// true skips the recursive check for footage files// and will only check the one's usedif(checkParentDied()) {return;}app.project.renderQueue.render(true);} catch(error) {// Add any errors to the log file.if (this.log_file != null) {this.log_file.writeln("aerender " + error.toString());}// It's possible that errors were encountered while trying to render.// Stop the render if in progress for a clean exit from the application.if (app.project && app.project.renderQueue && app.project.renderQueue.rendering) {// This will prevent the message "render stopped by user" from showing up...app.onError = null;app.project.renderQueue.stopRendering();// This will print a better message:if (this.log_file != null) {this.log_file.writeln(this.MSG_RENDER_ABORTED);}app.onError = this.onError;}this.SetExitCode(this.EXIT_AE_RUNTIME);} finally {// Close the project.this.CloseProjectIfDesired();// Put back the old error handlerapp.onError = this.oldErrorHandler;// Restore the setting for hearing the render-done sound.this.RestoreRenderSoundSetting()}}// Returns the first item on the render queue that:// [a] contains a comp named comp_name// [b] has a render status of QUEUED or UNQUEUED or NEEDS_OUTPUT//     Note that if the status is NEEDS_OUTPUT, one better be provided or//     an error will result.//// If not found, returns null.//function my_GetFirstQueuedRQItemWithName(comp_name){var result = null;var rq = app.project.renderQueue;if (rq &&  rq.numItems > 0) {var cur_item;// the items are indexed from 1 to numItems.for (var i = 1; i <= rq.numItems; i++) {cur_item = rq.item(i);if (cur_item.comp.name == comp_name && cur_item.status == RQItemStatus.WILL_CONTINUE) {if (this.log_file != null) {this.log_file.writeln(this.MSG_SKIPPING_WILL_CONTINUE);}}if (cur_item.comp.name == comp_name && (cur_item.status == RQItemStatus.QUEUED ||// pmi 9/24/03 -- do not render unqueued items. Let a new// one be added instead.// cur_item.status == RQItemStatus.UNQUEUED ||cur_item.status == RQItemStatus.NEEDS_OUTPUT)) {// We found it!result = cur_item;break;}}}return result;}// Find a comp with the given name, and adds it to the render queue.// Returns the newly added render queue item//// If not found, returns null.//function my_AddCompToRenderQueue(comp_name){var result = null;// Get the comp with the name we are aftervar cur_item;var desired_comp = null;// the items in the project are indexed from 1 to numItemsfor (var i = 1; i <= app.project.numItems; i++) {cur_item = app.project.item(i);if (cur_item instanceof CompItem && cur_item.name == comp_name) {desired_comp = cur_item;break;}}// Add the desired_comp to the render queue.  The add() method// returns the new render queue item.if (desired_comp) {result = app.project.renderQueue.items.add(desired_comp);}return result;}// Sets the render flag on all RenderQueueItems other than rqi to false,//function my_EstablishAsOnlyQueuedItem(rqi){var rq = app.project.renderQueue;if (rq &&  rq.numItems > 0) {var cur_item;// the items are indexed from 1 to numItems.for (var i = 1; i <= rq.numItems; i++) {cur_item = rq.item(i);if (cur_item == rqi) {cur_item.render = true;} else {// You can only change the render flag when these are the current status value:if (cur_item.status == RQItemStatus.QUEUED || cur_item.status == RQItemStatus.UNQUEUED || cur_item.status == RQItemStatus.NEEDS_OUTPUT || cur_item.status == RQItemStatus.WILL_CONTINUE) {cur_item.render = false;}}}}}// Sets the log type to be ERRORS_AND_PER_FRAME_INFO for all items that are going to render.//function my_SetLogPerFrameInfoInRQ(){var rq = app.project.renderQueue;if (rq &&  rq.numItems > 0) {var cur_item;// the items are indexed from 1 to numItems.for (var i = 1; i <= rq.numItems; i++) {cur_item = rq.item(i);if (cur_item.render == true) {if (cur_item.status != RQItemStatus.USER_STOPPED &&cur_item.status != RQItemStatus.ERR_STOPPED &&cur_item.status != RQItemStatus.RENDERING &&cur_item.status != RQItemStatus.DONE) {cur_item.logType = LogType.ERRORS_AND_PER_FRAME_INFO;}}}}}// Closes the project if the close flag specifies to do so//function my_CloseProjectIfDesired(){if (app.project) {// Close the project we just used, if desiredif (!this.in_close_flag || this.in_close_flag == "DO_NOT_SAVE_CHANGES") {// If no flag provided, this is the default.app.project.close(CloseOptions.DO_NOT_SAVE_CHANGES);} else {if (this.in_close_flag == "SAVE_CHANGES") {app.project.close(CloseOptions.SAVE_CHANGES);}// otherwise, flag is DO_NOT_CLOSE, so we do nothing.}}}function my_SaveAndSetRenderSoundSetting(){// Save the current setting for hearing the render-done sound, we'll restore it later.if (app.preferences.havePref("Misc Section","Play sound when render finishes", PREFType.PREF_Type_MACHINE_INDEPENDENT)) {// Get the current value if the pref exists.this.saved_sound_setting = app.preferences.getPrefAsLong("Misc Section","Play sound when render finishes", PREFType.PREF_Type_MACHINE_INDEPENDENT);} else {// default is to play the sound, value of 1.// Use this if the pref does not yet exist.this.saved_sound_setting = 1;}// Set the setting for hearing the render-done sound, based on the input, default is off.this.my_sound_setting = 0;  // 0 is offif (this.in_sound_flag && (this.in_sound_flag == "ON" || this.in_sound_flag == "on")) {this.my_sound_setting = 1;  // 1 is on}app.preferences.savePrefAsLong("Misc Section","Play sound when render finishes",this.my_sound_setting, PREFType.PREF_Type_MACHINE_INDEPENDENT);}function my_RestoreRenderSoundSetting(){if (this.saved_sound_setting) {app.preferences.savePrefAsLong("Misc Section","Play sound when render finishes",this.saved_sound_setting, PREFType.PREF_Type_MACHINE_INDEPENDENT);}}// [3] assign all the functions to be method-type attributes.//this.onError                     = my_onError;this.SetExitCodeAndThrowException = my_SetExitCodeAndThrowException;this.SetExitCode                 = my_SetExitCode;this.StripAnyEnclosingQuotes      = my_StripAnyEnclosingQuotes;this.GetValueForFlag              = my_GetValueForFlag;this.ParseParamStartingAt         = my_ParseParamStartingAt;this.ParseInArgs                 = my_ParseInArgs;this.IsInArray                        = my_IsInArray;this.SetupDefaultLog                = my_SetupDefaultLog;this.CleanupDefaultLog                = my_CleanupDefaultLog;this.Render                         = my_Render;this.ReallyRender                  = my_ReallyRender;this.GetFirstQueuedRQItemWithName    = my_GetFirstQueuedRQItemWithName;this.AddCompToRenderQueue            = my_AddCompToRenderQueue;this.EstablishAsOnlyQueuedItem       = my_EstablishAsOnlyQueuedItem;this.SetLogPerFrameInfoInRQ         = my_SetLogPerFrameInfoInRQ;this.CloseProjectIfDesired         = my_CloseProjectIfDesired;this.SaveAndSetRenderSoundSetting   = my_SaveAndSetRenderSoundSetting;this.RestoreRenderSoundSetting       = my_RestoreRenderSoundSetting;this.IsSavePrefsArgGiven            = my_IsSavePrefsArgGiven;
}var gAECommandLineRenderer = new AECommandLineRenderer();

  合理的脚本代码可以有效的提高工作效率,减少重复劳动。

文章引用至 作者知了-联系方式1
文章引用至 作者知了-联系方式2

AfterEffect插件--常规功能开发--命令行渲染--js脚本开发--AE插件相关推荐

  1. AfterEffect插件-常规功能开发-高斯特效添加-js脚本开发-AE插件

    文章目录 1.程序算法 2.应用 3.作者答疑 1.程序算法   高斯模糊(英语:Gaussian Blur),也叫高斯平滑 ,通常用它来减少图像噪声以及降低细节层次. 从数学的角度来看,图像的高斯模 ...

  2. AfterEffect插件-常规功能开发-复制组合图层-js脚本开发-AE插件

    文章目录 1.算法程序 2.作者答疑 1.算法程序   AfterEffect(AE)插件是Adobe公司开发的特效制作软件,稳定快速的功能和特效,在视频制作领域使用非常广泛,本文向大家介绍如何在项目 ...

  3. AfterEffect(AE)插件-常规功能开发-放大缩小图层-js脚本开发-AE插件

    文章目录 1.算法程序 2.文本转执行 3.作者答疑 1.算法程序   AfterEffect(AE)插件是Adobe公司开发的特效制作软件,稳定快速的功能和特效,在视频制作领域使用非常广泛,本文向大 ...

  4. AfterEffect插件--常规功能开发--合成放大缩小--js脚本开发--AE插件

    文章目录 1.算法程序 2.作者答疑 1.算法程序   AfterEffect(AE)插件是Adobe公司开发的特效制作软件,稳定快速的功能和特效,在视频制作领域使用非常广泛,本文向大家介绍如何在项目 ...

  5. illustrator插件--常用功能开发--生成出血线--js脚本开发--AI插件--动作--菜单

    文章目录 1.算法程序 2.作者答疑 1.算法程序   illustrator是矢量编辑软件,画板是绘制处理的重要容器,在印刷方面的一个重要功能就生成出血线,开发一个生成出血线功能,以下功能仅用于学习 ...

  6. illustrator插件-拼版功能开发-自动拼版-js脚本开发-ai插件

    文章目录 1.算法程序 2.作者答疑 1.算法程序   illustrator是矢量编辑软件,画板是绘制处理的重要容器,在印刷方面的一个重要功能就是拼版,开发一个自动拼版功能,源代码如下所示: if ...

  7. illustrator插件-拼版功能开发-一键拼版-js脚本开发-ai插件

    文章目录 1.算法程序 2.作者答疑 1.算法程序   illustrator是矢量编辑软件,画板是绘制处理的重要容器,在印刷方面的一个重要功能就是拼版,开发一个一键拼版功能,源代码如下所示: fun ...

  8. illustrator插件--常用功能开发--标注横尺寸--js脚本开发--AI插件

    1.算法功能   illustrator是矢量编辑软件,画板是绘制处理的重要容器,在印刷方面的一个重要功能就是标注横尺寸,开发一个标注横尺寸功能,以下功能仅用于学习交流,请勿用于非法用途和商业用途,源 ...

  9. illustrator插件--常用功能开发--查找白色叠印--js脚本开发--AI插件

      illustrator是矢量编辑软件,画板是绘制处理的重要容器,在印刷方面的一个重要功能就是查找白色叠印,开发一个查找白色叠印功能,以下功能仅用于学习交流,请勿用于非法用途和商业用途,源代码如下所 ...

最新文章

  1. 闪退怎么看logcat_iPhone手机点开软件就闪退如何解决?
  2. mysql-proxy 0.8.5_主从读写分离----mysql-proxy0.8.5安装与配置
  3. UIView自定义控件-Swfit
  4. 在阿里云 ECS 上使用 SAP Spartacus
  5. require.ensure与require AMD的区别
  6. Asp.net mvc 实时生成缩率图到硬盘
  7. 面试题(用栈代替队列的操作和原生map实现)
  8. 解决Linux操作系统下SSH等终端乱码问题
  9. arm-none-linux-gnueabi-gcc:未找到命令,arm-none-linux-gnueabi-gcc编译标准库引用
  10. CCNA学习笔记 基础知识回顾(1)
  11. Debug工具的使用
  12. python3GUI--在线小说播放器By:PyQt5(附ui源码)
  13. sqlserver xml 操作:3、对不确定结构、属性的xml进行处理
  14. 交通信息工程 实验三:交通信号机仿真实验
  15. 水晶报表的学习与开发
  16. mac ios 远程桌面连接到服务器配置,手把手教你苹果mac如何远程桌面连接
  17. samba 本地设备名已在使用中 此连接尚未恢复
  18. 读书笔记:Bi-Directional Cascade Network for Perceptual Edge Detection
  19. IAR 配置ICF跟项目走
  20. 从“入世”被裁到中兴事件,18年间中国科技经历了什么?

热门文章

  1. 基于虹软SDK在C/S 模式下的多人脸实时识别(C#)
  2. MacOS磁盘目录结构
  3. 利用verilog将二进制码转换为十进制BCD码
  4. java把mysql大数据量表每个文件最多10MB分批次写入到txt文件中
  5. 数字信号处理奥本海姆pdf_奥本音频处理器9300
  6. 一天一个蛋,刀斧靠边站
  7. matlab三位画图_matlab画三维图像
  8. 罗马数字自动转换成阿拉伯数字
  9. NPOI导出数值格式设置(我是保留四位小数,不足补0)
  10. 5000元手机性价比排行榜2022 5000元左右性价比最高的手机