Files
vfxreview/VFXReviewConnector.md
twotalesanimation 93137cdcd2 fix(connector): anchor built comps on the plate's own EXR timecode
Build Shot produced comps starting at 00:00:00:00 because the panel never
actually read the EXR timecode. getFootageStartFrames ranked a fragile "New
Comp from Selection" probe first: it toggles the Project panel via the Window
menu to get focus, and where that does not land the menu item is greyed out,
executeCommand silently does nothing, and the probe returns null. A shot with
no timecodeStart then fell through the API rank to zero.

The worker already reads EXR headers properly in ExrHeader.cs, and its
validation ranks the plate's own timeCode above the API value, which stores the
editorial in-point and sits a handle-length ahead of the plate by design. Shots
were therefore being built from rank 3 and validated against rank 1. That is a
timecode desync waiting to reach a delivery, not just a cosmetic start frame.

readExrTimecode ports the worker's reader to ExtendScript and becomes rank 1:
one short header read, walking `name\0 type\0 int32 size data` for timeCode and
falling back to timeCodeString where a writer omitted the packed attribute.
decodePackedTimecode mirrors Timecode.FromPacked, decoding the SMPTE 12M BCD a
byte at a time so the arithmetic never touches the sign bit. The menu probe is
kept as rank 2 and now runs only when the plate carries no timecode at all, so
the Project-panel toggle is off the normal path.

setCompStartFrame was the second failure. Assigning displayStartFrame on a
version of AE that does not have the property is ignored silently rather than
throwing, so the early return skipped the displayStartTime fallback entirely.
It now reads the value back, falls through when it did not take, and returns
whether anything stuck; buildShotFromCode logs when nothing does. A start frame
that cannot be set is now visible in the diagnostics report instead of a comp
quietly sitting at zero.

A plate whose timecode is present but zero still falls through to the API rank,
keeping the existing frames > 0 convention so the safety net survives. If a
genuine 00:00:00:00 plate should win outright that is a deliberate follow-up.

The parser is covered against synthetic headers, including the 0x18585712
example documented in ExrHeader.cs, drop-frame, truncated and non-EXR input.
What is not yet exercised in a live After Effects session is mainSource.file
resolving to the sequence's first frame and displayStartFrame taking on a given
AE build, so build one shot and check its start against the plate before
relying on this. Picture-lock automation was reverted for a timecode desync of
the same shape.

PANEL_VERSION goes to 2.6.0 per the documented rule, so Pipeline → Machines
does not show two workstations on one version behaving differently. The
startSource comment in the manifest schema enumerated only the two older
values; the queue-time provenance check keys on /\bAPI\b/ and so already reads
"EXR timecode …" as trustworthy rather than suspect.

The same silent-failure setCompStartFrame still exists in the farm-side
vfxr_build_preview.jsx, which is fed the right value from the manifest but can
drop it the same way. Left for its own change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 16:53:49 +02:00

28 KiB

VFXReview Connector

A dockable ScriptUI panel for Adobe After Effects 2024+ that integrates with the VFXReview platform to streamline shot management, render queuing, and workspace setup for VFX production pipelines.


Configuration

Settings are stored per-machine via the ⚙ Settings button in the panel (persisted in After Effects' built-in preferences — no need to edit the JSX file).

Setting Purpose
Server URL Base URL of the VFXReview server (e.g. https://review.twotalesvfx.com)
API Token Bearer token matching API_SECRET_KEY in the server .env
Export Root Local path where renders and deliverables are written
Footage Root Local path where EXR plate folders are read from
Banner Path Path to the panel banner image
Artist Email Used for render attribution in the pipeline
Handle Frames Plate handle frames prepended before the shot's source TC in-point (default: 8)
Path Mappings Optional. Rewrites paths the server supplies — see below

Server paths vs. this machine

The server addresses render folders from its own root (render.outputRoot, e.g. //SAN), which a workstation may not resolve — the render worker translates them with its own pathMappings because it runs as a service account. The panel needs the same translation to open a render for QC.

It resolves this itself in most cases, trying in order:

  1. Path Mappings, if configured — format //SAN/=V:/_EXPORTS/, several separated by ;.
  2. The server path as given — correct when render.outputRoot is already a path this machine can reach.
  3. Re-based on Export Root — the server's export layout mirrors the panel's from the show folder down ({root}/{showId}/{episode}/{shot}/{version}), so the tail is simply re-attached to Export Root.

Step 3 is why this usually needs no configuration. Diagnostics checks the whole thing against a real render folder from the QC queue and names every path it tried when it fails.

More than one on-disk convention

Every candidate is tested for existence and the first that resolves wins, so a studio whose output root changed at some point can map the same prefix more than once and let the panel work out which applies per export:

//SAN/=V:/_EXPORTS/;//SAN/=V:/_EXPORTS/UNG/

Older exports keep whatever path was stored on them when they were queued — changing render.outputRoot on the server only affects new ones — so mixed conventions in one database are normal and permanent. Add a mapping per convention rather than trying to make one rewrite cover them all.


Pipeline Folder Structure

Export Root

All outputs from the connector are written under <Export Root>/{SHOW_ID}/ (e.g. V:/_EXPORTS). The show ID is appended automatically from the selected project — configure exportRoot as the bare root without a show ID.

<Export Root>/
└── {SHOW_ID}/                                     # e.g. UNG/
    ├── {SHOT_CODE}/                                # e.g. UNG_108_001_010/
    │   ├── {shot}_cmp_TT_{ver}.[#####].exr         # Queue EXR / Queue EXR (Review)
    │   └── {shot}_cmp_TT_{ver}.mp4 / .mov          # Queue MP4 / Queue MOV
    │
    ├── DELIVERY/
    │   └── {EPISODE_OR_SCENE}/                     # e.g. UNG_108/
    │       └── {YYYYMMDD}_Delivery/
    │           └── {SHOT_CODE}/
    │               └── {shot}_cmp_TT_{ver}.[#####].exr
    │
    └── (render farm outputs — managed by the server)
        └── {PROJECT_CODE}/{EPISODE}/{SHOT_CODE}/{ver}/
            └── {shot}_cmp_TT_{ver}.[#####].exr

Version naming: {SHOT_CODE}_cmp_TT_{version} — e.g. UNG_108_001_010_cmp_TT_v003.[01001].exr

Versions are set manually via Increment Shot Version or the shot detail page. Queuing a render does not auto-increment the version.


Footage Root

Source EXR plates are read from <Footage Root>/{SHOW_ID}/. Configure footageRoot as the bare root (e.g. V:/_FOOTAGE).

<Footage Root>/
└── {SHOW_ID}/                      # e.g. UNG/ or DH2_VFX/
    ├── {EPISODE_CODE}/             # episodic only: e.g. UNG_108/
    │   └── {SHOT_CODE}/            # standard layout: plates grouped per shot
    │       └── {SHOT_CODE}_{ELEM}_{VER}/
    │           └── *.exr
    │
    └── _PICLOCKS/
        └── {EPISODE_CODE}_*.mov    # matched by episode prefix

Frame rate

Comps are built at the shot record's fps, and plates are conformed to it. That value is the show's delivery rate and the authority; a plate's own rate is whatever happens to be on disk.

fps defaults to 24 when a shot is created, so check it after importing a show that is not 24 — every shot carries its own value, and a wrong one produces comps at the wrong rate, plates conformed to the wrong speed, and timecode-to-frame sums that are quietly off.

A plate at a whole-number multiple of the show rate (50 fps on a 25 fps show) is a deliberate over-crank and is conformed as intended. Validation reports the difference either way, saying which of the two it looks like.

Scenes are not folders. Standard projects have no level between the show folder and the shot folder — the scene picker filters the shot list only.

Two layouts are supported, and neither is migrated. The connector prefers the grouped layout above; where a {SHOT_CODE}/ folder does not exist it falls back to scanning the parent for folders named {SHOT_CODE}_* (the original UNG layout, where plates sit directly in the episode folder). All matching folders are imported as separate footage layers. If a {SHOT_CODE}/ folder exists but holds no plate subfolders, that is reported as no footage — the fallback scan is not attempted, so stray plate folders sitting beside the shot cannot be picked up as its footage. Underscore-prefixed folders (_ARCHIVE, _GFX, _PULLS, …) are never treated as shots or plates.


Episodic vs. Standard productions

Episodic Standard
Shot code format {SHOW}_{EP}_{SCENE}_{NUM} {SHOW}_{SCENE}_{NUM}
Shot Builder Episode dropdown → Shot dropdown Scene dropdown → Shot dropdown
Footage path {footageRoot}/{showId}/{EPISODE}/ {footageRoot}/{showId}/{SCENE}/
Export path {exportRoot}/{showId}/{SHOT_CODE}/ same
Delivery subfolder DELIVERY/{EPISODE}/… DELIVERY/{SCENE}/…

Migrating an existing project (e.g. UNG)

If you previously set exportRoot = V:/_EXPORTS/UNG, update it to V:/_EXPORTS. The code now appends /{showId}/ automatically, so V:/_EXPORTS/UNG/… is still produced — no files need to move.

Same applies to footageRoot: change V:/_FOOTAGE/UNG → V:/_FOOTAGE.


New production checklist

  1. Create <Footage Root>/{SHOW_ID}/[{EPISODE_CODE}/]{SHOT_CODE}/ — episode level for episodic shows only, never a scene level — and place each plate in its own {SHOT_CODE}_{ELEM}_{VER}/ folder inside it.
  2. <Export Root>/{SHOW_ID}/ is created automatically on first render.
  3. Add the project to the VFXReview server with the correct Show ID set.
  4. Open the panel in After Effects, click ⚙, enter the Server URL, API Token, bare exportRoot, and bare footageRoot, then click Save.
  5. The Project dropdown will populate automatically. Select the production and the episode/scene list will load.
Variable Default Description
TOKEN am3O0PWU… Bearer token used to authenticate all API requests
BASE_URL https://review.twotalesvfx.com Base URL of the VFXReview platform
PROJECT_CODE UNG_S1 Project identifier used in all API endpoints
EXPORT_ROOT V:/_EXPORTS/UNG Root path where rendered outputs are written
FOOTAGE_ROOT V:/_FOOTAGE/UNG Root path where source EXR footage sequences live
BANNER_IMAGE_PATH V:/VFXReviewConnector/banner.png Optional banner image displayed at the top of the panel

Panel Layout

The panel is divided into seven sections:

  1. Shot Builder — Episode/shot selection and comp creation
  2. Render Pipeline — Queue Export, status polling, retry, regenerate previews
  3. QC — Technical QC queue for rendered exports
  4. Actions — Per-shot and batch operations
  5. Workspace — One-time project initialisation
  6. Color Space — OCIO effect management
  7. Status — Live feedback, plus Diagnostics and the last report

Shot Builder

Episode Dropdown

Populated automatically on panel load by calling GET /api/ext/projects/{PROJECT_CODE}/episodes. Each item stores the episode label (e.g. UNG_106) and the raw API episode value used for subsequent shot queries.

Shot Dropdown

Populated when an episode is selected by calling GET /api/ext/projects/{PROJECT_CODE}/shots?episode={value}. Displays shot codes (e.g. UNG_106_010_020).

Build Shot

Constructs a full shot composite in the open AE project from the episode and shot selected in the dropdowns.

Process:

  1. Calls the shot lookup API to retrieve metadata (description, notes, episode, scene, etc.).
  2. If a comp with the shot code already exists, updates its overlay instead of rebuilding.
  3. Scans FOOTAGE_ROOT/{episodeCode}/ for subfolders matching {shotCode}_* and imports each as an EXR image sequence, conformed to the shot's frame rate.
  4. Creates a {shotCode}_FOOTAGE precomp containing all imported sequences, each with an OCIO Color Space Transform effect added (disabled by default).
  5. Creates the main {shotCode} comp and places the footage precomp inside it.
  6. Anchors both comps on the plate's start timecode — see Start timecode.
  7. If a _SHOW LUT comp exists in the project, adds it as a collapsed layer on top.
  8. Calls Add Overlay logic to attach the UNG_VFX_OVERLAY comp.
  9. Organises items into __SHOTS/{episodeCode}, _FOOTAGE_4K, and _PRECOMPS project folders.

If any step fails, the status line names the stage and a copyable report opens — see Diagnostics and logging.

Start timecode

Neither comp starts at 00:00:00:00. Both are anchored on the plate's own start timecode, taken from the first source that has one:

Rank Source Notes
1 The first EXR's header The timeCode attribute, or timeCodeString where the packed one is absent. Read straight off disk — no pixel decode, and no dependency on what AE chose to expose.
2 AE's footage metadata What "New Comp from Selection" would have inherited.
3 API timecodeStart less handleFrames The convention Set Start Timecode uses. Last resort: the API stores the editorial in-point, which is a handle-length ahead of the plate by design.

This is the same ranking the render worker's validation uses (RenderPipeline2 §8.1a), so a comp is anchored on exactly the value its EXRs are later checked against — a shot built from rank 3 and validated against rank 1 is how a timecode desync gets into a delivery.

The status line and the diagnostics log both name the rank that was used, e.g. start frame 864108 from EXR timecode 10:00:04:12. A plate carrying no timecode in any rank leaves the comp at 00:00:00:00 and says so.


Render Pipeline

Queue Export

Saves the project, builds the render manifest from the selected comp and the shot record, and submits it to the farm.

Option Effect
Urgent Priority 20 — claimable outside the render window, ahead of normal jobs
No preview Renders the EXRs but builds no preview, inheriting the previous export's MOV, review MP4 and thumbnail

No preview exists for deliverables framed differently from the review — unscaled or un-punched-in EXRs. A preview rebuilt from those frames would be the wrong picture, while the earlier export's MOV is already correct, so it carries over instead. The export still goes through QC, and the delivery package still gets a MOV.

Leave it unticked for an ordinary submission: the preview is what QC and the client review see.


QC

Technical QC on the rendered EXRs, not the H.264 preview — the point is catching mask slips, export glitches and metadata faults at full resolution. QC is per-export: a new export always needs new QC.

Control Behaviour
Load QC Queue Lists every export in READY_FOR_QC for the selected project, oldest first. Entries flagged with a warning count had a non-blocking validation warning worth a closer look.
Open Render (or double-click) Imports that export's actual EXR sequence into a QC_{shot}_{version} comp at full res and opens it. Re-selecting an already-imported shot just reopens the comp.
Notes Sent with the decision. Optional on pass; a fail with no notes asks for confirmation, because the artist only sees what you write here.
QC Pass Marks the version ready for delivery and nothing else — nothing is shared to the client, no approval state changes, no task moves.
QC Fail Sets the export to QC_FAILED and the comp task to CHANGES. The artist fixes and queues a new version; the old export is superseded.

Passing an export is what makes it eligible for a delivery package on the web app's Pipeline → Deliveries page.


Actions

Refresh

Updates the Status panel to show the current count of selected CompItems. Has no effect on the project.


Fix Comp Names

Renames selected comps so their names match the shot code extracted from their current name.

  • Shot codes are read by anchoring on the selected project's showId — see Shot Code Convention.
  • If a comp name contains a valid shot code but has extra text, it is trimmed to the code only.
  • Wrapped in an undo group.

Add Overlay

Adds or updates the UNG_VFX_OVERLAY comp as a layer on each selected comp (or the active comp if nothing is selected).

Process:

  1. Looks up each shot via the API to confirm it exists.
  2. If the overlay layer is not already present, adds the UNG_VFX_OVERLAY comp and moves it to the top of the layer stack.
  3. Sets two Essential Properties on the overlay layer:
    • DATE — today's date in YYYY/MM/DD format.
    • SHOT NAME — {shotCode}_cmp_TT_v001.
  4. Reports how many overlays were added vs. updated vs. skipped.
  5. Wrapped in an undo group.

Requirement: A comp named UNG_VFX_OVERLAY must exist in the project.


Build Preview

Creates a {shotCode}_PREVIEW comp for each selected (or active) comp using a standardised export template.

Process:

  1. Duplicates the UNG_EXPORT_TEMPLATE comp and names the copy {shotCode}_PREVIEW.
  2. Moves the copy into the _PREVIEWS project folder if it exists.
  3. Replaces the SHOT and THUMBNAIL layers with the shot comp.
  4. Populates the NETFLIX_SLATE Essential Properties:
    • Shot name ({shotCode}_cmp_TT_v001)
    • Date, Description, Notes, Shot Code, Episode, Scene, Frame count
  5. Adjusts the preview comp duration to match the shot comp duration.
  6. Wrapped in an undo group.

Requirements:

  • UNG_EXPORT_TEMPLATE comp must exist in the project.
  • Shot metadata must be available from the API.

Queue EXR

Queues each selected comp for EXR sequence render using the EXR Sequence output module template.

Process:

  1. Looks up each shot via the API to get the exrOutput filename stem.
  2. Sets the comp's display start frame to 1001.
  3. Disables any layers named UNG_VFX_OVERLAY or _SHOW LUT in the comp.
  4. Ensures the output folder EXPORT_ROOT/{shotCode}/ exists.
  5. Queues the comp with output path {folderPath}/{exrOutput}.[#####].exr.
  6. Wrapped in an undo group.

Requirement: The EXR Sequence output module template must be configured in AE preferences.


Queue MP4

Queues a preview render for each selected (or active) comp as an MP4 file.

  • Uses the REVIEW_PREVIEW output module template.
  • Output path: EXPORT_ROOT/{shotCode}_cmp_TT_v001.mp4
  • Automatically calls Build Preview first if a {shotCode}_PREVIEW comp does not exist.
  • Updates the overlay on the main shot comp before queuing.
  • Wrapped in an undo group.

Requirement: The REVIEW_PREVIEW output module template must be configured in AE preferences.


Queue MOV

Identical to Queue MP4 but uses the 4444 Tri output module template and writes a .mov file.

  • Output path: EXPORT_ROOT/{shotCode}_cmp_TT_v001.mov

Requirement: The 4444 Tri output module template must be configured in AE preferences.


Import Renders

Imports rendered EXR sequences for the active/selected shot comp from the shared renders folder.

Process:

  1. Resolves the renders folder at X:/shared_projects_2026/UNGO_VFX/production/renders/{shotCode}.
  2. Iterates subfolders first (separate render passes/layers), importing each as an EXR sequence at 24 fps. Falls back to sequences directly in the root folder.
  3. Adds each imported footage item to the _RENDERS project folder.
  4. Adds all footage as layers to the target comp and applies the Extractor effect to each layer.
  5. Pre-composes all added layers into a single {shotCode}_RENDER comp.
  6. Wrapped in an undo group.

Pull Picture Lock

Imports a picture-lock (offline cut) video file and trims it to the correct sequence timecode range for the shot, including handles.

Process:

  1. Calls the API to retrieve seqTimecodeStart and seqTimecodeEnd for the shot.
  2. Searches the _PICLOCKS project folder for already-imported footage matching the episode prefix — {showId}_{episode} on episodic shows (e.g. UNG_106), plain {showId} on standard ones.
  3. If not found, scans FOOTAGE_ROOT/_PICLOCKS/ for a file matching {episodePrefix}_* and imports it.
  4. Calculates the in/out offsets from the sequence timecodes relative to the piclock's start (assumed 01:00:00:00 / 3590 s unless embedded timecode is available), with ±8 frame handles.
  5. Adds the piclock footage as a layer at the top of the comp, scales it to fill the frame, and sets startTime, inPoint, and outPoint to isolate the correct range.
  6. Wrapped in an undo group.

Requirement: Shot must have seqTimecodeStart and seqTimecodeEnd populated in the VFXReview database.


Workspace

Per-project templates

Each show has its own template AEP — its overlay, slate/export template and, most importantly, its show LUT. These are configured per project on the web app under Project → Settings → Pipeline, not in the panel, because the render farm's headless preview build reads the same values: if the two disagreed, a farm preview would be quietly the wrong colour.

Setting Purpose
Template project (.aep) Imported by Initialise Workspace and by every headless preview build
Renders root Where per-shot pre-renders live; the panel appends the shot code (Import Renders)
Overlay / Slate / LUT comp Only needed when a template departs from the naming convention

Comp names default to a convention derived from the show ID: {showId}_VFX_OVERLAY, {showId}_EXPORT_TEMPLATE, _SHOW LUT. A show whose template follows the pattern needs no comp configuration at all — leave the fields blank and they follow the convention, including any later change to it.

Initialise Workspace

One-time setup that creates the standard project folder hierarchy, imports the slate/overlay template AEP, and configures color settings.

Works for any project: the episode folders and the template both come from the selected project rather than being fixed to one show.

Folder structure created:

__SHOTS/
  {EPISODE_CODE}/     ← one per episode, from the project's episode list
  …                     (episodic shows only; standard shows get none)
_PREVIEWS/
_PRECOMPS/
_PICLOCKS/
_FOOTAGE_4K/
_STOCK/
_RENDERS/
_UTILITIES/

Episodes come from GET /api/ext/projects/{code}/episodes. If a show has none entered yet, the folders found under its footage root are used instead, so the button still does something useful on day one.

Template import: Imports the project's Template project (.aep) as a project merge — see Per-project templates. If none is configured the folders and colour settings are still applied, and the status line says the template was not set.

Color settings (applied outside the undo group):

  • Sets project bit depth to 32-bit.
  • Enables color management via app.project.colorSettings.enabled.
  • Attempts to set the working color space to ACES 1.2 by searching the available space list. Falls back to "ACES - ACES2065-1" if the list API is unavailable. If the scripting API does not support this, a message prompts manual configuration.

Color Space

Add OCIO to Footage Layers

Adds an OCIO Color Space Transform effect (disabled) to every footage layer in each selected (or active) comp.

  • Only targets FootageItem layers backed by a FileSource (skips solids, comps, etc.).
  • Sets the Output Color Space property to index 93.
  • The effect is added in a disabled state so it can be enabled selectively during grading.
  • Wrapped in an undo group.

API Reference

All HTTP calls use system.callSystem with curl. Requests include:

Authorization: Bearer {TOKEN}
Accept: application/json
Endpoint Method Description
/api/ext/projects/{PROJECT_CODE}/episodes GET List all episodes for the project
/api/ext/projects/{PROJECT_CODE}/shots?episode={value} GET List shots for a given episode
/api/ext/shots/lookup?shotCode={code}&projectCode={code} GET Retrieve full metadata for a single shot

Shot Metadata Fields Used

Field Used By
shotCode All operations — canonical identifier
exrOutput Queue EXR — filename stem for EXR renders
description Build Preview — slate Description property
notes Build Preview — slate Notes property
episode Build Preview — slate Episode property
scene Build Preview — slate Scene property
seqTimecodeStart Pull Picture Lock — in-point calculation
seqTimecodeEnd Pull Picture Lock — out-point calculation

Shot Code Convention

Shot codes are the project's showId followed by three-digit tokens:

Project type Pattern Example
Episodic {showId}_{episode}_{scene}_{shot} UNG_106_010_020 (showId UNG)
Standard {showId}_{scene}_{shot} DH2_VFX_027_010 (showId DH2_VFX)

The showId is not always three letters and may itself contain underscores, so codes are parsed by stripping the known showId prefix — never by counting underscores or matching a fixed AAA_ pattern. Everything after the showId is three digits per token.

Episode codes follow {showId}_{episode} (e.g. UNG_106).


Required Project Assets

The following comps/items must exist in the AE project for certain features to work:

Name Type Required By
UNG_VFX_OVERLAY Comp Add Overlay, Build Preview, Queue MP4/MOV
UNG_EXPORT_TEMPLATE Comp Build Preview, Queue MP4/MOV
_SHOW LUT Comp Build Shot (optional — applied if present)
_PREVIEWS Folder Build Preview (optional — used if present)
_PRECOMPS Folder Build Shot (optional — used if present)
_FOOTAGE_4K Folder Build Shot (optional — used if present)
_RENDERS Folder Import Renders (optional — created if absent)
_PICLOCKS Folder Pull Picture Lock (optional — created if absent)
__SHOTS Folder Build Shot / Initialise Workspace

Output Module Templates Required

These must be created in After Effects > Edit > Templates > Output Module before using the corresponding queue buttons:

Template Name Used By Format
EXR Sequence Queue EXR OpenEXR image sequence
REVIEW_PREVIEW Queue MP4 H.264 / MP4
4444 Tri Queue MOV ProRes 4444 / MOV

Status Panel

The Status panel at the bottom of the UI shows two lines:

  • Line 1 — Number of currently selected CompItems.
  • Line 2 — Result or progress message from the last operation.

Both lines are updated throughout batch operations so progress is visible in real time.

Below them are two buttons:

  • Diagnostics — runs the environment self-test described below.
  • Show Last Report — re-opens the trace from the last button pressed.

Versions

The panel's version is the PANEL_VERSION constant at the top of VFXReviewConnector.jsx. It appears in the panel title, in every diagnostics report, and is sent to the server when the panel loads.

Pipeline → Machines → Deployed tool versions then shows which version each workstation is running, alongside the render workers. Anything behind the newest version seen for that tool is flagged → rebuild to vX — so updating one machine is what surfaces the ones still to do. No expected-version list to keep in sync; the newest thing reporting in is the benchmark.

Bump PANEL_VERSION whenever you copy the .jsx to a workstation. If two machines report the same version but behave differently, one of them was copied without the bump.


Diagnostics and logging

Every button press is traced: what it tried, in what order, with the paths and HTTP codes it was working with. The trace goes to an in-memory buffer and to a log file, and it is shown automatically when something fails.

Log file: %APPDATA%/VFXReviewConnector/connector.log (next to config.json). It is truncated once it passes 1 MB, so it can always be pasted into a message. The API token is never written to it — only whether one is set.

When Build Shot fails

The status line now names the stage it failed at, and a scrollable report opens with the whole trace. The stages, and what each one means:

Stage Meaning Usual fix
project No project selected in the panel The project dropdown is empty because the server URL or token is wrong
shot lookup The server returned no shot record Report shows the HTTP code: 0 = server unreachable, 401/403 = bad token, 404 = shot not in that project
configuration Footage Root is blank in Settings Settings are per-machine; a fresh workstation starts blank
footage folder The show/episode folder does not exist here Report names the deepest folder that does exist — usually an unmapped drive or a different drive letter/UNC on that machine
plate folders Folder exists, no plates for that shot code Report lists the folders that are there, so a naming mismatch is visible
plate import Plate folders matched but held no importable EXRs Report lists each folder's contents (n .exr, n other files)
comp creation After Effects threw while building the comps Not a path or server problem — the AE error text is in the report
unexpected error Anything thrown that was not anticipated Report carries the error text, line number and stack

Non-fatal conditions are traced too rather than passing silently: a missing _SHOW LUT, an overlay that could not be applied, a missing __SHOTS/{group} folder.

Diagnostics button

Checks everything Build Shot depends on without building anything, so a workstation can be cleared before an artist is blocked. It verifies:

  1. curl.exe is present and runnable (every server call goes through it).
  2. Server URL and API token are set, and GET /api/ext/projects succeeds.
  3. Footage Root resolves to a folder that exists, and lists the plate folders found for the currently selected shot.
  4. Export Root resolves to a folder that exists.
  5. The shot lookup succeeds for the currently selected shot.
  6. The open AE project has UNG_VFX_OVERLAY, UNG_EXPORT_TEMPLATE, _SHOW LUT, and the __SHOTS / _FOOTAGE_4K / _PRECOMPS / _PREVIEWS folders.

Each failure is reported as a PROBLEM line with the offending path or HTTP response, and the report ends with a problem count.

Errors that used to be invisible

ScriptUI silently swallows exceptions thrown inside a button handler, so a hard failure looked like a button that did nothing at all. Every handler is now wrapped: anything thrown is caught, logged with its line number and stack, shown in the status line, and surfaced in the report dialog.