constantworkflow

render-clean-silent

Render_Clean_Silent: One-Shot Clean Render for Fusion Studio

Fusion Studio's render workflow requires three separate steps: clean up old outputs before rendering, render the comp, then finalize outputs after rendering. This script collapses all three into a single keystroke—pre-render cleanup, silent rendering, and post-render finalization—without manual intervention or popup dialogs interrupting the workflow.

The Problem

In my previous post on ClearSaverOutputs.lua, I explained how Fusion Studio lacks DaVinci Resolve's "Delete before render" feature, requiring manual cleanup of old frames and movie files before every render. I built ClearSaverOutputs to automate the pre-render cleanup step.

But that script is only one-third of the full workflow:

  1. Pre-render cleanup (ClearSaverOutputs.lua): Delete old frames, redirect movie outputs to temp files
  2. Rendering (Cmd+R): Fusion renders the comp
  3. Post-render finalization (separate PostRender script): Swap temp movie files to final names

This three-step process works, but it's still three manual actions:

And between steps, Fusion displays the "Render Completed" dialog, forcing me to click "OK" before continuing. When I'm rendering multiple comps in sequence or iterating on a motion graphics project, this dialog is pure friction—I already know the render completed because the progress bar finished.

Render_Clean_Silent.lua solves both problems by combining all three steps into one script and suppressing the completion dialog entirely.

The Solution

This script is a one-shot clean render that handles the entire workflow:

  1. Pre-render cleanup: Deletes old image sequence frames, redirects movie outputs to temp files (same logic as ClearSaverOutputs)
  2. Silent rendering: Renders the comp with comp:Lock() to suppress the "Render Completed" popup
  3. Post-render finalization: Swaps temp movie files to final names, restores Saver paths

The workflow is now:

  1. Make changes to the Fusion comp
  2. Hit Cmd+Shift+R (my custom keybinding for this script)
  3. Wait for render to complete
  4. Output files are finalized and ready—no popups, no manual cleanup

Total time: render duration + ~1 second for cleanup/finalization. Zero popups, zero manual steps, zero leftover temp files.

Technical Implementation

This script combines the logic from ClearSaverOutputs.lua (pre-render cleanup) with two new features: silent rendering and post-render finalization.

1. Pre-Render Cleanup (Same as ClearSaverOutputs)

The script starts by iterating through all Saver nodes and applying cleanup logic:

For movie outputs (.mov, .mp4, etc.):

For image sequences (.exr, .dpx, .png, etc.):

Opt-out mechanism:

This is identical to ClearSaverOutputs—the code is the same. The difference is that this script continues instead of stopping at cleanup.

2. Silent Rendering with comp:Lock()

After cleanup, the script renders the comp using Fusion's Lua API:

comp:Lock()  -- suppress UI popups (including "Render Completed")
local ok = comp:Render({ Start=R0, End=R1, Wait=true, RenderAll=true })
comp:Unlock()

What comp:Lock() does:

comp:Lock() freezes the Fusion UI while the script is running, preventing any dialogs from interrupting the render. This includes:

The Wait=true parameter tells Fusion to render synchronously—the script waits for the render to finish before continuing. This ensures post-render finalization doesn't run until the output files are fully written.

After rendering, comp:Unlock() restores normal UI behavior.

Result: The render happens silently. No popups, no interruptions. If the render fails, the script prints an error to the console but doesn't display a dialog.

3. Post-Render Finalization: Swapping Temp → Final

After the render completes, the script finalizes movie outputs by swapping temp files to their final names:

for _, m in ipairs(maps) do
  if bmd.fileexists(m.tmp) then
    if clear_final(m.final) then
      local moved = os.rename(m.tmp, m.final)
      if not moved then
        local okcopy = copy_file(m.tmp, m.final)
        if okcopy then os.remove(m.tmp) end
      end
      print("[CleanRender] Finalized: "..m.final)
    end
  end
end

Step-by-step breakdown:

  1. Check if temp file exists: bmd.fileexists(m.tmp) verifies the render actually produced the temp file.
  2. Clear the final path: clear_final(m.final) deletes the old output file (if it exists).
  3. Rename temp → final: os.rename(m.tmp, m.final) is an atomic operation—the file is moved, not copied, so there's no "half-moved" intermediate state.
  4. Fallback to copy+delete: If os.rename() fails (rare, but can happen on network drives), the script falls back to copy_file() then deletes the temp.

Why clear_final() is defensive:

The clear_final() function doesn't just call os.remove(final) once—it retries with a short delay:

local function clear_final(final)
  if not bmd.fileexists(final) then return true end
  for _=1,3 do if os.remove(final) then return true end; nap(0.12) end
  -- fallback: rename to .old
  local old = string.format("%s.%s.%s.old", base, ext, now_ms())
  if os.rename(final, old) then
    os.remove(old)
    return true
  end
  return false
end

Why the retries?

Network drives (SMB, NFS) sometimes hold file locks for a fraction of a second after a process closes the file. On a local SSD, os.remove() succeeds instantly. On a NAS, it might fail the first time, succeed after 120ms.

The retry loop with nap(0.12) (a 120ms sleep) gives the filesystem time to release the lock. If all retries fail, the script renames the old file to .old as a last resort, then cleans it up asynchronously.

This prevents the script from failing just because the NAS was slow to release a file lock—a real problem I encountered when rendering to client network drives at my 9-to-5.

4. Restoring Saver Paths

After finalizing outputs, the script restores any Saver nodes that still point to temp files:

for _, s in pairs(savers) do
  local clip = s.Clip and s.Clip[comp.CurrentTime] or ""
  for _, m in ipairs(maps) do
    if clip == m.tmp then s.Clip = m.final end
  end
end

This ensures the Fusion comp is left in a clean state—all Savers point to their final output paths, not temp files. If I reopen the comp later, the Savers show the correct paths.

Use Cases

Primary: One-Shot Clean Renders for Motion Graphics

When I'm rendering motion graphics comps in Fusion Studio (1-2 times per month), I use this script to:

All with one keystroke (Cmd+Shift+R).

Secondary: Batch Rendering Multiple Comps

If I have 5-10 Fusion comps to render (e.g., a series of lower thirds for a client project), I can:

  1. Open the first comp
  2. Hit Cmd+Shift+R (script runs, render completes silently)
  3. Open the next comp
  4. Repeat

Without the "Render Completed" popup interrupting me, I can batch-render comps faster. The script handles cleanup and finalization automatically, so I don't have to remember to delete old frames or swap temp files.

Why Not Just Use ClearSaverOutputs + Manual Render?

ClearSaverOutputs works great, but it's three manual steps:

  1. Run ClearSaverOutputs (pre-clean)
  2. Cmd+R to render
  3. Wait for PostRender script to finalize

And the "Render Completed" popup still interrupts the workflow.

Render_Clean_Silent collapses all three steps into one action and suppresses the popup. For someone who only uses Fusion Studio 1-2 times per month (I do most work in Resolve's Fusion page), having a single "just render it cleanly" script is easier to remember than a multi-step workflow.

Time Savings

Manual process:

  1. Navigate to output folders, delete old frames/movies: 15-30 seconds
  2. Return to Fusion, Cmd+R to render
  3. Wait for "Render Completed" popup, click OK: 2 seconds
  4. Run PostRender script to finalize temp files: 3-5 seconds

Total manual time: 20-37 seconds of overhead (not counting actual render duration).

Automated process: Hit Cmd+Shift+R, wait for render to complete. Total overhead: ~1 second (cleanup + finalization happen automatically, no popups).

Savings per render: 19-36 seconds.

I use this 1-2 times per month when working in Fusion Studio. At 2 renders per month, this saves 38-72 seconds (0.6-1.2 minutes) monthly.

But the real value is zero mental overhead. I don't have to remember the three-step workflow or deal with the "Render Completed" popup breaking my focus. The script handles everything, and I can move on to the next comp.

Implementation Notes

This script requires:

Setting Up as a Render Script

To use this script:

  1. Save Render_Clean_Silent.lua to your Fusion scripts folder:

    • macOS: ~/Library/Application Support/Blackmagic Design/Fusion/Scripts/Comp/
    • Windows: C:\Users\[USERNAME]\AppData\Roaming\Blackmagic Design\Fusion\Scripts\Comp\
  2. Bind it to a keyboard shortcut:

    • Open Fusion Studio
    • Go to Fusion → Preferences → Global and Default Settings → Scripting
    • Under Comp Scripts, assign a shortcut to Render_Clean_Silent (I use Cmd+Shift+R)
  3. To render a comp with automatic cleanup and finalization, hit your shortcut.

Customizing Sequence Cleanup Policy

The SEQ_POLICY variable controls how image sequences are cleaned:

local SEQ_POLICY = "delete_range"

Options:

I recommend delete_range for most workflows—it's the safest option for iterative rendering where you only re-render specific frame ranges.

Adding New File Formats

To add support for a new movie or image format, update the lookup tables:

local MOVIE_EXT = { mov=true, mp4=true, webm=true }  -- Added webm
local IMAGE_EXT = { exr=true, dpx=true, tga=true }

Using the [KEEP] Opt-Out

To prevent cleanup for a specific Saver node:

  1. Select the Saver in the Flow view
  2. Open the Comments field (right panel, under "Comments")
  3. Add [KEEP] anywhere in the comments (case-insensitive)

The script will skip cleanup for that Saver, preserving its existing output.

Comparison to ClearSaverOutputs

I maintain two Fusion render automation scripts:

Script Use Case Steps Popups Finalization
ClearSaverOutputs.lua Pre-render cleanup only (requires manual render + PostRender script) 3 manual steps "Render Completed" popup Separate PostRender script
Render_Clean_Silent.lua One-shot clean render (cleanup + render + finalization) 1 keystroke None (silent) Built-in

When to use ClearSaverOutputs:

When to use Render_Clean_Silent:

I use Render_Clean_Silent 90% of the time because I trust the cleanup logic and prefer the faster one-shot workflow. ClearSaverOutputs is there for edge cases where I need more granular control.

Why This Matters

Fusion Studio is an incredible compositor, but its render workflow feels dated compared to DaVinci Resolve's streamlined Deliver page. Render_Clean_Silent bridges that gap by automating the entire render pipeline—cleanup, rendering, finalization—with one keystroke and zero popups.

For anyone working in Fusion Studio for complex motion graphics or VFX work—especially if you're coming from Resolve and expect a polished render workflow—this script eliminates friction and prevents the "mixed old/new frames" frustration that plagues iterative rendering.

The silent rendering with comp:Lock() is a quality-of-life improvement that shouldn't be underestimated. When you're batch-rendering multiple comps or rendering overnight, the "Render Completed" popup breaking your workflow (or staying on-screen until you manually dismiss it) is pure friction. Suppressing it entirely makes Fusion feel more like a modern render pipeline.

The defensive clear_final() function with retry logic is a real-world necessity for network drive rendering. On a local SSD, os.remove() succeeds instantly. On a NAS at my 9-to-5 (QuikTrip client projects), file locks can linger for 120-300ms after a process closes the file. The retry loop handles this gracefully instead of failing and leaving temp files scattered across the filesystem.

And the temp name redirection for movie outputs—rendering to .rendering.TIMESTAMP.ext then swapping to the final name—prevents partial overwrites, file lock issues, and data loss from failed renders. It's the same strategy browsers use for downloads ("Downloading… → Move to Downloads folder"), and it's just as valuable for rendering.

This script shows what's possible when you stop accepting software limitations and build the workflow you actually want. Fusion Studio doesn't have "Delete before render" or silent rendering out of the box, but the Lua API is powerful enough to add both. The entire script is ~160 lines—a small investment for eliminating manual cleanup, popup interruptions, and post-render finalization steps.