inlife/nexrender

Add support for -renderSettings and -outputSettings overrides.

olekristensen opened this issue · 9 comments

Is your feature request related to a problem? Please describe.
If you want to setup nexrender to use customized output module settings and/or render settings they need to be configured manually first.

However, aerender allows us to modify the selected RStemplate and OMtemplate by using the command line options -renderSettings and -outputSettings.

This is super useful for nexrender, as it allows us to eg. select Field rendering for broadcast targets programmatically instead of having to manually setup a renderSetting that enables Field rendering.

Other use cases is setting draft render and downscaling in the template.json

Describe the solution you'd like
The template json should support two additional keys, renderSettings and outputSettings that map directly to the aerender flags.

Describe alternatives you've considered
Before we've maintained a repository of After Effects preferences text files, and used them to overwrite AE's preferences before each render. This is error-prone and cumbersome.

Additional context
Documentation from aerender -h scroll down to the bottom two lines to see how it's presented by Adobe.

aerender version 23.4x53
USAGE:
   1] aerender renders After Effects comps. The render may be performed either
      by an already running instance of AE or by a newly invoked instance. By
      default, aerender will invoke a new instance of AE, even if one is
      already running. To change this, see the "-reuse" flag below.
   2] aerender takes a series of optional arguments.
      Some are single flags, like "-reuse". Some come in flag-argument
      pairs, like "-project project_path". And one comes in a triplet,
      -mem_usage image_cache_percent max_mem_percent.
   3] aerender with 0 arguments, or with any argument equaling "-help" 
      or "-h", prints this usage message.
   4] The arguments are:
      "-h"                    print this usage message
      "-help"                 print this usage message
      "-reuse"                use this flag if you want to try and reuse
                              an already running instance of AE to perform the
                              render.  By default, aerender will launch a new
                              instance of After Effects, even if one is already
                              running.  But, if AE is already running, and the
                              "-reuse" flag is provided, then aerender will
                              ask the already running instance of AE to perform
                              the render. Whenever aerender launches a new
                              instance of AE, it will tell AE to quit when
                              rendering is completed; otherwise, it will not
                              quit AE. Also, the preferences will be written
                              to file upon quit when the "-reuse" flag is
                              specified; otherwise it will not be written.
      "-project project_path" where project_path is a file path or URI
                              specifying a project file to open. 
                              If none is provided, aerender will work with the
                              currently open project.
                              If no project is open and no project is provided,
                              an error will result.
      "-teamproject project_name"	where project_name is a name of a
                              team project to open.
      "-comp comp_name"       where comp_name specifies a comp to be rendered.
                              If the comp is in the render queue already, and
                              in a queueable state, then (only) the first
                              queueable instance of that comp on the render
                              queue will be rendered. If the comp is in the
                              project but not in the render queue, then it will
                              be added to the render queue and rendered.
                              If no -comp argument is provided, aerender will
                              render the entire render queue as is. In this
                              case (no -comp), the only other arguments used
                              will be -project, -log, -v, -mem_usage, and
                              -close; the -RStemplate, -OMtemplate, -output,
                              -s, -e,  and -i arguments will be ignored.
      "-rqindex index_in_render_queue"       where index_in_render_queue specifies a
                              render queue item to be rendered. Options that make
                              sense when rendering a single render queue item
                              are available like with the -comp flag.
      "-RStemplate render_settings_template"  where render_settings_template
                              is the name of a template to apply to the render
                              queue item.If the template does not exist it is
                              an error.
                              Default is to use the render template already
                              defined for the item.
      "-renderSettings render_settings"  where render_settings is a formatted
                              list of individual render settings to
                              override in the render queue item, after any 
                              RS templates have been applied. If no render
                              queue item is specified it is an error. Settings
                              are in the form "key1: value1; key2: value2" 
                              Keys and values are defined by the After Effects
                              Guide for Render Settings. See EXAMPLES below.
      "-OMtemplate output_module_template"  where output_module_template
                              is the name of a template to apply to the
                              output module. If the template does not exist
                              it is an error.
                              Default is to use the template already defined
                              for the output module.
      "-outputSettings output_settings"  where output_setting is a formatted
                              list of individual output module settings to
                              override in the render queue item, after any 
                              OM templates have been applied. If no render
                              queue item is specified it is an error. Settings
                              are in the form "key1: value1; key2: value2" 
                              Keys and values are defined by the After Effects
                              Guide for Output Module Settings. See EXAMPLES below.
      "-output output_path"  where output_path is a file path or URI
                              specifying the destination render file.
                              Default is the path already in the project file.
      "-log logfile_path"     where logfile_path is a file path or URI
                              specifying the location of the log file.
                              Default is stdout.
      "-s start_frame"        where start_frame is the first frame to render.
                              Default is the start frame in the file.
      "-e end_frame"          where end_frame is the last frame to render.
                              Note, this is "inclusive;" the final frame
                              will be rendered.
                              Default is the end frame in the file.
      "-i increment"          where increment is the number of frames to
                              advance before rendering a new frame. A value
                              of 1 (the default) results in a normal rendering
                              of all frames. Higher increments will repeat the
                              same (frame increment-1) times and then render a
                              new one, starting the cycle again. Higher values
                              result in faster renders but choppier motion.
                              Default is 1.
      "-mem_usage image_cache_percent max_mem_percent"
                              where image_cache_percent specifies the maximum
                              percent of memory used to cache already rendered
                              images/footage, and max_mem_percent specifies
                              the total percent of memory that can be 
                              used by After Effects.
      "-mfr mfr_flag max_cpu_percent"
                              where mfr_flag ("ON"|"OFF") specifies if
                              Multi-Frame Rendering should be used, and
                              max_cpu_percent (1-100) specifies the desired maximum
                              CPU percentage power to use during rendering.
                              Because Multi-Frame Rendering has the ability
                              to use 100 percent of your CPU's capability, you may
                              choose to limit the CPU power so other
                              applications can be used.
                              max_cpu_percent will be ignored when the mfr_flag
                              is set to "OFF".
      "-v verbose_flag"       where verbose_flag specifies the type of
                              messages reported.  Possible values are ERRORS
                              (prints only fatal and problem errors) or 
                              ERRORS_AND_PROGRESS (prints progress of rendering
                              as well).
                              Default value is ERRORS_AND_PROGRESS.
      "-close close_flag"     where close_flag specifies whether or not to
                              close the project when done rendering, and
                              whether or not to save changes. If close_flag is
                              DO_NOT_SAVE_CHANGES, project will be closed
                              without saving changes. If close_flag is
                              SAVE_CHANGES, project will be closed and changes
                              will be saved. If close_flag is DO_NOT_CLOSE the
                              project will be left open; but the project is
                              left open only if using an already-running
                              instance of AE, since new invocations of AE must
                              always close and quit when done.
                              Default value is DO_NOT_SAVE_CHANGES.
      "-sound sound_flag"     where sound_flag specifies whether or not to play
                              a sound when rendering is complete. Possible
                              values are "ON" or "OFF".
                              Default value is "OFF".
      "-version"              displays the version number of aerender to the
                              console. Does not render.
      "-continueOnMissingFootage"  
                              Do not stop rendering on missing footage. Log and
                              render with placeholder color bars.
   5] EXAMPLES:
      To render just Comp 1 to a specified file:
          aerender -project /Volumes/Stuff/projects/proj1.aep -comp "Comp 1"
                   -output /Volumes/Stuff/output/proj1/proj1.mov
      To render everything in the render queue as is in the project file:
          aerender -project /Volumes/Stuff/projects/proj1.aep
      To render frames 1-10 using multi-machine render:
          aerender -project /Volumes/Stuff/projects/proj1.aep
                   -comp "Comp 1" -RStemplate "Multi-Machine Settings"
                   -OMtemplate "Multi-Machine Sequence" -s 1 -e 10 
                   -output /Volumes/Stuff/output/proj1/frames\[####\].psd
      To render Comp 1 at Draft quality, Half resolution with top 4 lines cropped:
          aerender -project /Volumes/Stuff/projects/proj1.aep -comp "Comp 1"
                   -renderSettings "Resolution: Half; Quality: Draft"
                   -outputSettings "Crop: true; Crop Top: 4"

Good point Mr @olekristensen! I totally missed the new options folks from Adobe introduced in the latest versions.

Will work on adding that!

p.s. Finally, they added support for something like this, this is a lifesaver! 🎉

@inlife I could possibly contribute this, I would want to work on it from Monday-tuesday next week... could possibly get it done within a day or so. I would just pass the strings to the command -

I actually added this commit an hour ago. Could you take a look and verify that you were thinking about a similar approach?

b8fcd80

Exactly - one consideration I do have in general, is that there is a security impact when strings that are passed directly to the command line are not sanitised. For me it's not a problem, I'm using nexrender programatically, and the template.json is built internally in my render server code, but it does potentially leave the nexrender server vulnerable for shell script injection...

using something like https://www.npmjs.com/package/escape-it could at least help

adding some regex matching to validate options in the params would also be an option.

Those are good points, probably could be added in the future updates

But what are the settings?

The renderSettings and outputSettings are really not documented by Adobe, but they can be retrieved by running the following .jsx script asking for the settings specs as 'JSON' strings (it's not valid json unless you replace the illegal keys -1 with a string representation).

var rqItem1_spec_str = app.project.renderQueue.item(1).getSettings(GetSettingsFormat.SPEC);
var rqItem1_spec_str_json = rqItem1_spec_str.toSource();
alert("Render Settings:\n" + rqItem1_spec_str_json);

var rqItem1_om_spec_str = app.project.renderQueue.item(1).outputModule(1).getSettings(GetSettingsFormat.SPEC);
var rqItem1_om_spec_str_json = rqItem1_om_spec_str.toSource();
alert("Output Module Settings:\n" + rqItem1_om_spec_str_json);

Below are the results:

Render Settings Spec:

({
  "3:2 Pulldown": {
    type: "int",
    enums: { Off: 0, WSSWW: 1, SSWWW: 2, SWWWS: 3, WWWSS: 4, WWSSW: 5 },
    "enums-reverse": {
      0: "Off",
      1: "WSSWW",
      2: "SSWWW",
      3: "SWWWS",
      4: "WWWSS",
      5: "WWSSW",
    },
    range: [0, 5],
  },
  "Color Depth": {
    type: "int",
    enums: {
      "Current Settings": -1,
      "8 bits per channel": 0,
      "16 bits per channel": 1,
      "32 bits per channel": 2,
    },
    "enums-reverse": {
      "-1": "Current Settings",
      0: "8 bits per channel",
      1: "16 bits per channel",
      2: "32 bits per channel",
    },
    range: [-1, 2],
  },
  "Disk Cache": {
    type: "int",
    enums: { "Read Only": 0, "Current Settings": 2 },
    "enums-reverse": { 0: "Read Only", 2: "Current Settings" },
    range: [0, 2],
  },
  Effects: {
    type: "int",
    enums: { "All Off": 0, "All On": 1, "Current Settings": 2 },
    "enums-reverse": { 0: "All Off", 1: "All On", 2: "Current Settings" },
    range: [0, 2],
  },
  "Field Render": {
    type: "int",
    enums: { Off: 0, "Upper Field First": 1, "Lower Field First": 2 },
    "enums-reverse": {
      0: "Off",
      1: "Upper Field First",
      2: "Lower Field First",
    },
    range: [0, 2],
  },
  "Frame Blending": {
    type: "int",
    enums: {
      "Off for All Layers": 0,
      "On for Checked Layers": 1,
      "Current Settings": 2,
    },
    "enums-reverse": {
      0: "Off for All Layers",
      1: "On for Checked Layers",
      2: "Current Settings",
    },
    range: [0, 2],
  },
  "Frame Rate": {
    type: "int",
    enums: { "Use comp's frame rate": 0, "Use this frame rate": 1 },
    "enums-reverse": { 0: "Use comp's frame rate", 1: "Use this frame rate" },
    range: [0, 1],
  },
  "Guide Layers": {
    type: "int",
    enums: { "All Off": 0, "Current Settings": 2 },
    "enums-reverse": { 0: "All Off", 2: "Current Settings" },
    range: [0, 2],
  },
  "Motion Blur": {
    type: "int",
    enums: {
      "Off for All Layers": 0,
      "On for Checked Layers": 1,
      "Current Settings": 2,
    },
    "enums-reverse": {
      0: "Off for All Layers",
      1: "On for Checked Layers",
      2: "Current Settings",
    },
    range: [0, 2],
  },
  "Proxy Use": {
    type: "int",
    enums: {
      "Use No Proxies": 0,
      "Use All Proxies": 1,
      "Current Settings": 2,
      "Use Comp Proxies Only": 3,
    },
    "enums-reverse": {
      0: "Use No Proxies",
      1: "Use All Proxies",
      2: "Current Settings",
      3: "Use Comp Proxies Only",
    },
    range: [0, 3],
  },
  Quality: {
    type: "int",
    enums: { "Current Settings": -1, Wireframe: 0, Draft: 1, Best: 2 },
    "enums-reverse": {
      "-1": "Current Settings",
      0: "Wireframe",
      1: "Draft",
      2: "Best",
    },
    range: [-1, 2],
  },
  Resolution: {
    type: '{"x": <int>, "y": <int>}',
    enums: {
      "Current Settings": "0,0",
      Custom: "x,y",
      Custom2: '{"x": <x_val>, "y": <y_val>}',
      Custom3: "[<x_val>,<y_val>]",
      Full: "1,1",
      Half: "2,2",
      Quarter: "4,4",
      Third: "3,3",
    },
    "enums-reverse": {
      "0,0": "Current Settings",
      "x,y": "Custom",
      '{"x": <x_val>, "y": <y_val>}': "Custom2",
      "[<x_val>,<y_val>]": "Custom3",
      "1,1": "Full",
      "2,2": "Half",
      "4,4": "Quarter",
      "3,3": "Third",
    },
  },
  "Skip Existing Files": { type: "bool" },
  "Solo Switches": {
    type: "int",
    enums: { "All Off": 0, "Current Settings": 2 },
    "enums-reverse": { 0: "All Off", 2: "Current Settings" },
    range: [0, 2],
  },
  "Time Span": {
    type: "int",
    enums: { "Length of Comp": 0, "Work Area Only": 1, Custom: 2 },
    "enums-reverse": { 0: "Length of Comp", 1: "Work Area Only", 2: "Custom" },
    range: [0, 2],
  },
  "Time Span Duration": { type: "double" },
  "Time Span End": { type: "double" },
  "Time Span Start": { type: "double" },
  "Use comp's frame rate": { type: "double" },
  "Use this frame rate": { type: "double" },
});

Output Settings Spec:

({
  "Audio Bit Depth": {
    type: "int",
    enums: { "8 Bit": 1, "16 Bit": 2, "32 Bit": 4 },
    "enums-reverse": { 1: "8 Bit", 2: "16 Bit", 4: "32 Bit" },
    range: [1, 4],
  },
  "Audio Channels": {
    type: "int",
    enums: { Mono: 1, Stereo: 2 },
    "enums-reverse": { 1: "Mono", 2: "Stereo" },
    range: [1, 2],
  },
  "Audio Sample Rate": {
    type: "int",
    enums: {
      "16,000 kHz": 16000,
      "22,050 kHz": 22050,
      "24,000 kHz": 24000,
      "32,000 kHz": 32000,
      "44,100 kHz": 44100,
      "48,000 kHz": 48000,
    },
    "enums-reverse": {
      16000: "16,000 kHz",
      22050: "22,050 kHz",
      24000: "24,000 kHz",
      32000: "32,000 kHz",
      44100: "44,100 kHz",
      48000: "48,000 kHz",
    },
    range: [16000, 48000],
  },
  Channels: {
    type: "int",
    enums: { RGB: 0, "RGB + Alpha": 1, Alpha: 2 },
    "enums-reverse": { 0: "RGB", 1: "RGB + Alpha", 2: "Alpha" },
    range: [0, 2],
  },
  Color: {
    type: "int",
    enums: { "Straight (Unmatted)": 0, "Premultiplied (Matted)": 1 },
    "enums-reverse": { 0: "Straight (Unmatted)", 1: "Premultiplied (Matted)" },
    range: [0, 1],
  },
  Crop: { type: "bool" },
  "Crop Bottom": { type: "int" },
  "Crop Left": { type: "int" },
  "Crop Right": { type: "int" },
  "Crop Top": { type: "int" },
  Depth: {
    type: "int",
    enums: {
      "Floating Point Gray": -32,
      "256 Colors": 8,
      "Millions of Colors": 24,
      "Millions of Colors+": 32,
      "256 Grays": 40,
      "Trillions of Colors": 48,
      "Trillions of Colors+": 64,
      "Floating Point": 96,
      "Floating Point+": 128,
    },
    "enums-reverse": {
      "-32": "Floating Point Gray",
      8: "256 Colors",
      24: "Millions of Colors",
      32: "Millions of Colors+",
      40: "256 Grays",
      48: "Trillions of Colors",
      64: "Trillions of Colors+",
      96: "Floating Point",
      128: "Floating Point+",
    },
    range: [-32, 128],
  },
  Format: {
    type: "int",
    enums: {
      AIFF: 0,
      "DPX/Cineon Sequence": 1,
      "H.264": 2,
      "IFF Sequence": 3,
      "JPEG Sequence": 4,
      MP3: 5,
      "OpenEXR Sequence": 6,
      "PNG Sequence": 7,
      "Photoshop Sequence": 8,
      QuickTime: 9,
      "Radiance Sequence": 10,
      "SGI Sequence": 11,
      "TIFF Sequence": 12,
      "Targa Sequence": 13,
      WAV: 14,
    },
    "enums-reverse": {
      0: "AIFF",
      1: "DPX/Cineon Sequence",
      2: "H.264",
      3: "IFF Sequence",
      4: "JPEG Sequence",
      5: "MP3",
      6: "OpenEXR Sequence",
      7: "PNG Sequence",
      8: "Photoshop Sequence",
      9: "QuickTime",
      10: "Radiance Sequence",
      11: "SGI Sequence",
      12: "TIFF Sequence",
      13: "Targa Sequence",
      14: "WAV",
    },
    range: [0, 14],
  },
  "Include Project Link": { type: "bool" },
  "Include Source XMP Metadata": { type: "bool" },
  "Lock Aspect Ratio": { type: "bool" },
  "Output Audio": {
    type: "int",
    enums: { Off: 1, On: 2, Auto: 3 },
    "enums-reverse": { 1: "Off", 2: "On", 3: "Auto" },
    range: [1, 3],
  },
  "Output File Info": {
    type: {
      "Full Flat Path": "string",
      "Base Path": "string",
      "Subfolder Path": "string",
      "File Name": "string",
      "File Template": "string",
    },
  },
  "Post-Render Action": {
    type: "int",
    enums: { None: 0, Import: 1, "Import & Replace Usage": 2, "Set Proxy": 3 },
    "enums-reverse": {
      0: "None",
      1: "Import",
      2: "Import & Replace Usage",
      3: "Set Proxy",
    },
    range: [0, 3],
  },
  Resize: { type: "bool" },
  "Resize Quality": {
    type: "int",
    enums: { Low: 0, High: 1 },
    "enums-reverse": { 0: "Low", 1: "High" },
    range: [0, 1],
  },
  "Resize to": {
    type: '{"x": <int>, "y": <int>}',
    enums: {
      "Cineon Full  \u2022  3656x2664 \u2022 24 fps": "3656,2664",
      "Cineon Half  \u2022  1828x1332 \u2022 24 fps": "1828,1332",
      Custom: "x,y",
      Custom2: '{"x": <x_val>, "y": <y_val>}',
      Custom3: "[<x_val>,<y_val>]",
      "DVCPRO HD  \u2022  1280x1080 (1,5) \u2022 29,97 fps": "1280,1080",
      "DVCPRO HD  \u2022  1440x1080 (1,33) \u2022 25 fps": "1440,1080",
      "DVCPRO HD  \u2022  960x720 (1,33) \u2022 23,976 fps": "960,720",
      "DVCPRO HD  \u2022  960x720 (1,33) \u2022 25 fps": "960,720",
      "DVCPRO HD  \u2022  960x720 (1,33) \u2022 29,97 fps": "960,720",
      "Film (2K)  \u2022  2048x1556 \u2022 24 fps": "2048,1556",
      "Film (4K)  \u2022  4096x3112 \u2022 24 fps": "4096,3112",
      "HD  \u2022  1920x1080 \u2022 24 fps": "1920,1080",
      "HD  \u2022  1920x1080 \u2022 25 fps": "1920,1080",
      "HD  \u2022  1920x1080 \u2022 29,97 fps": "1920,1080",
      "HDV  \u2022  1440x1080 (1,33) \u2022 25 fps": "1440,1080",
      "HDV  \u2022  1440x1080 (1,33) \u2022 29,97 fps": "1440,1080",
      "HDV/HDTV  \u2022  1280x720 \u2022 25 fps": "1280,720",
      "HDV/HDTV  \u2022  1280x720 \u2022 29,97 fps": "1280,720",
      "Social Media Landscape  \u2022  1280x720 \u2022 30 fps": "1280,720",
      "Social Media Landscape HD  \u2022  1920x1080 \u2022 30 fps": "1920,1080",
      "Social Media Portrait  \u2022  720x1280 \u2022 30 fps": "720,1280",
      "Social Media Portrait HD  \u2022  1080x1920 \u2022 30 fps": "1080,1920",
      "Social Media Square  \u2022  1080x1080 \u2022 30 fps": "1080,1080",
      "UHD (4K)  \u2022  3840x2160 \u2022 23,976 fps": "3840,2160",
      "UHD (4K)  \u2022  3840x2160 \u2022 25 fps": "3840,2160",
      "UHD (4K)  \u2022  3840x2160 \u2022 29,97 fps": "3840,2160",
      "UHD (8K)  \u2022  7680x4320 \u2022 23,976 fps": "7680,4320",
    },
    "enums-reverse": {
      "3656,2664": "Cineon Full  •  3656x2664 • 24 fps",
      "1828,1332": "Cineon Half  •  1828x1332 • 24 fps",
      "x,y": "Custom",
      '{"x": <x_val>, "y": <y_val>}': "Custom2",
      "[<x_val>,<y_val>]": "Custom3",
      "1280,1080": "DVCPRO HD  •  1280x1080 (1,5) • 29,97 fps",
      "1440,1080": "HDV  •  1440x1080 (1,33) • 29,97 fps",
      "960,720": "DVCPRO HD  •  960x720 (1,33) • 29,97 fps",
      "2048,1556": "Film (2K)  •  2048x1556 • 24 fps",
      "4096,3112": "Film (4K)  •  4096x3112 • 24 fps",
      "1920,1080": "Social Media Landscape HD  •  1920x1080 • 30 fps",
      "1280,720": "Social Media Landscape  •  1280x720 • 30 fps",
      "720,1280": "Social Media Portrait  •  720x1280 • 30 fps",
      "1080,1920": "Social Media Portrait HD  •  1080x1920 • 30 fps",
      "1080,1080": "Social Media Square  •  1080x1080 • 30 fps",
      "3840,2160": "UHD (4K)  •  3840x2160 • 29,97 fps",
      "7680,4320": "UHD (8K)  •  7680x4320 • 23,976 fps",
    },
  },
  "Starting #": { type: "int" },
  "Use Comp Frame Number": { type: "bool" },
  "Use Region of Interest": { type: "bool" },
  "Video Output": { type: "bool" },
});

@olekristensen this is super helpful, in what context would one run that script above?