Files
vfxreview/RenderWorker
twotalesanimation 783e82eaf5 feat(render-pipeline): sync task title to preview version, fill slate ShotName
finalizePreview now retitles the export's task so its version suffix matches the
preview that was just uploaded (UNG_102_019_010_cmp_TT_v004 -> _v005), which is
the rename the manual batch upload already does on rename-and-upload. The new
nextTaskTitle helper mirrors nextExrOutputBase so the task title, EXR base and
preview filename all derive the suffix the same way. It uses the export's
versionString rather than versionNumber, since the DB number is bumped to stay
monotonic per task while the filename follows the shot's shotVersion.

The rename only fires when a Version was actually created, runs in the same
transaction, and is recorded in the ExportEvent note; the finalize response now
returns the task id, title and whether it changed. Task status is deliberately
untouched (pipeline renders must not resurface in the review flow, S10.0).

The headless preview build was addressing the slate's identity fields by index
only, so ShotName was never filled on the farm. setSlateIdentity writes both the
named property and the index -- the name-with-index-fallback pattern the panel
already uses for VersionName -- and warns with the template's actual property
names when neither resolves, instead of failing silently.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 10:30:47 +02:00
..

VFXReview RenderWorker

Windows service that drives aerender.exe on the artist workstations (RenderPipeline2 §7). It talks only HTTP to the VFXReview server (/api/ext/*, API-key auth) — it never gets a database connection. All scheduling policy (render windows, Render Now, urgent priority) is enforced server-side in the claim endpoint; the worker polls dumbly.

One click → EXR + MOV + MP4

A single Queue Export click produces all three deliverables. The server chains two jobs:

  1. AE_RENDER — aerender writes the clean EXR sequence (no overlay, no LUT).
  2. PREVIEW_ONLY — created automatically when the render completes. The worker runs AfterFX.com -noui -r scripts/vfxr_build_preview.jsx, which opens the studio slate/overlay template AEP, imports the rendered EXRs, rebuilds the shot around them (OCIO → _SHOW LUT → UNG_VFX_OVERLAY), duplicates UNG_EXPORT_TEMPLATE into a preview comp with the slate filled in, queues the MOV (4444 Tri) and MP4 (REVIEW_PREVIEW) output modules, and saves a throwaway AEP. The worker then runs aerender -project <that aep> with no -comp, rendering both outputs in one launch.

The MOV and MP4 land beside the EXRs. The MP4 is uploaded and registered as an ordinary Version — internal-only, never client-visible, and it changes no task or shot status (§10.0). Preview settings live in SystemConfig under preview.*, so template names and paths are changed without redeploying.

If the preview stage fails, only it is retried — the validated EXRs are never re-rendered. The temp AEP is kept on failure so you can open it and see exactly what the farm built.

Proving headless AE first

Headless AE is the one real unknown, so prove it before relying on it (spec 18.2-C4). Close After Effects, then:

.\scripts\test-preview-build.ps1 -ExrDir "V:\_EXPORTS\...\v002" -ShotCode "UNG_111_001_030" -Version "v002"

It runs the exact build the worker runs and prints the result plus any warnings (missing LUT comp, missing slate layer, …), then gives you the aerender command to render what it built. If it reports no result file, AE cannot script headlessly under that account — fall back to having the panel pre-build the preview comp in the artist's AEP (then it is pure aerender), or the ffmpeg engine.

What it does (Phase 2 scope)

  • Registers on startup (E6) and receives server-supplied tuning (poll/heartbeat/lease/stall).
  • Heartbeats every 30 s (E7) — the heartbeat response is also the cancel channel.
  • Claims one AE_RENDER job at a time (E8), runs aerender.exe with the manifest's comp/frame-range/templates, parses PROGRESS: lines, reports progress + ETA (E9, renews the lease).
  • Stall watchdog: no progress for stallTimeoutSeconds (default 600) → kill process tree, retryable fail.
  • Deterministic errors (missing footage / missing comp / unopenable project) → non-retryable fail (E10); transient errors auto-requeue server-side up to maxAttempts.
  • On success: uploads the full aerender log via presign (E20), reports complete (E11).
  • Crash recovery: current-job.json written on claim; on restart the worker asks the server what became of the job and reports a retryable fail if it was still ours. Partial renders are never resumed — the next attempt clears its own output files and re-renders.
  • Durable reporting: complete/fail reports spool to disk and replay in order with backoff — rendering continues while the server is down.

Preview generation (Phase 4) and validation (Phase 3) plug into this same service later.

Packaging for another machine

On a machine with the .NET 8+ SDK (only the packaging machine needs it):

.\scripts\publish.ps1 -Zip

Produces publish\win-x64\ containing exactly two things: a self-contained VFXReviewWorker.exe (~67 MB, no .NET runtime needed on the target) and scripts\vfxr_build_preview.jsx, which the exe loads from its own folder at runtime. Keep them together — the script is deliberately not embedded in the exe so the slate/preview build can be patched without a rebuild. -Zip also writes VFXReviewWorker_<date>.zip for copying.

Installing on the target

  1. Copy the folder to the render machine, e.g. C:\pipeline\VFXReviewWorker.

  2. Create C:\ProgramData\VFXReviewWorker\config.json (next section).

  3. Verify before installing the service:

    .\VFXReviewWorker.exe --check
    

    This resolves every path, confirms aerender.exe / AfterFX.com / the build script exist, checks each pathMappings target is reachable from that machine, and pings the server to confirm the API key is accepted. It exits non-zero if anything would stop the worker running, so a wrong path is caught here instead of in the logs an hour later.

  4. Install the service (below), then confirm the machine appears on the web Pipeline → Machines page.

Run --check again under the service account (runas /user:STUDIO\svc-render) if the service will run as someone other than the logged-in artist — mapped drives and share permissions differ per account, and that is the most common cause of a worker that registers fine but cannot find footage.

Upgrading later: stop the service, replace the folder, start it again. Config lives in ProgramData and is untouched.

Configure

Create C:\ProgramData\VFXReviewWorker\config.json (§7.8):

{
  "serverUrl": "https://review.twotalesvfx.com",
  "apiKey": "<API_SECRET_KEY>",
  "machineName": "RENDER-01",
  "aerenderPath": "C:\\Program Files\\Adobe\\Adobe After Effects 2026\\Support Files\\aerender.exe",
  "aeVersion": "24.3",
  "ffmpegPath": "C:\\pipeline\\bin\\ffmpeg.exe",
  "pathMappings": [
    { "from": "//SAN/", "to": "S:/" }
  ]
}

pathMappings translate the manifest's canonical UNC paths to this machine's drive mappings. Everything tunable (poll interval, lease, stall timeout, max attempts) lives in the server's SystemConfig and arrives at registration — no per-machine tuning files.

Run interactively (first-time smoke test)

VFXReviewWorker.exe

Logs go to the console-less service log at %ProgramData%\VFXReviewWorker\logs\worker_YYYYMMDD.log (14-day rolling). Confirm the machine appears on the web Pipeline → Machines page, then stop it.

Install as a Windows service

Run as a studio account with SAN access (works whether or not an artist is logged in):

sc.exe create VFXReviewRenderWorker binPath= "C:\pipeline\VFXReviewWorker\VFXReviewWorker.exe" start= auto obj= "STUDIO\svc-render" password= "<password>"
sc.exe description VFXReviewRenderWorker "VFXReview render pipeline worker (aerender)"
sc.exe start VFXReviewRenderWorker

Uninstall: sc.exe stop VFXReviewRenderWorker && sc.exe delete VFXReviewRenderWorker.

Rollout notes (spec §17.2)

  • Install on one workstation first; add the second after a clean week.
  • Set render.maxAttempts = 1 in SystemConfig for the first week (observe before auto-retrying).
  • Enter each machine's render windows on the Machines page (availability), defaults: weekdays 19:00–08:00 + full weekends; Render Now override = 4 h.
  • The dashboard warns when the two workstations report different AE versions.

Tests

cd RenderWorker
dotnet test

Covers the progress parser against recorded aerender transcript lines (success, error, non-retryable), ETA math, path mapping, log-tail ring buffer, and the output-dir clearing guard (only files matching the job's own pattern prefix are ever deleted).