constantworkflow

auto-project-structure

Auto Project Structure: Never Manually Create Bins Again

When you start a new DaVinci Resolve project, the Media Pool is empty. No bins, no structure, no organization. Most editors create bins ad-hoc as they import media—"footage," "audio," maybe "graphics"—but the structure varies project to project. This script creates a standardized bin hierarchy automatically the moment you open a new project, ensuring every project uses the same organizational structure so you can find assets months later without guessing where they were stored.

The Problem

Every new DaVinci Resolve project starts with a blank Media Pool. The manual workflow is:

  1. Create a seq bin for timelines
  2. Create a media bin for assets
  3. Create subfolders under media: footage, audio, gfx
  4. Create deeper subfolders: footage/interview, footage/broll, audio/mx, audio/sfx, etc.
  5. Manually navigate back to the seq bin to start creating timelines

Total time: 20-30 seconds of right-clicking → "Add Bin" → typing names → repeat.

But the bigger problem isn't the time—it's inconsistency across projects. When I'm working on multiple client projects simultaneously (QuikTrip social content, AirCo commercials, Galaxy long-form), each project evolves its own bin structure:

Three months later, when I reopen Project B to pull a shot for a new edit, I spend 10-15 seconds hunting for footage because I don't remember if I named the bin "broll," "b-roll," or "b roll."

This inconsistency compounds over time. I have dozens of archived projects, each with a slightly different organizational structure, making asset retrieval a guessing game.

The Solution

folders.py automates the creation of a standardized bin hierarchy in DaVinci Resolve. Combined with a background watcher script (not shown here, but part of my workflow automation suite), this script runs automatically when I create a new project with an empty Media Pool.

The workflow is now:

  1. Open DaVinci Resolve
  2. Create a new project (or open an existing empty project)
  3. The watcher script detects the empty Media Pool
  4. folders.py runs automatically, creating the full bin structure
  5. Media Pool cursor is set to the seq bin, ready for timeline creation

Total time: ~1 second (the script executes in the background while I'm opening the project).

Total manual effort: zero. I don't think about bin structure anymore. Every project starts with the same layout.

The Folder Structure

The script creates a hierarchical bin structure optimized for my editorial workflow:

Master Bins:
├── seq/                    (timelines go here)
└── media/                  (all media assets go here)
    ├── footage/
    │   ├── interview/      (talking head content)
    │   └── broll/          (b-roll, cutaways, inserts)
    ├── audio/
    │   ├── mx/             (music)
    │   ├── sfx/            (sound effects)
    │   └── on location/    (production audio, room tone)
    └── gfx/
        ├── logos/          (client logos, branding)
        ├── ae/             (After Effects imports)
        ├── fusion comps/   (Fusion compositions)
        └── compound clips/ (nested sequences, multicam clips)

This structure is consistent across every project. Whether I'm editing a 15-second QuikTrip social spot or a 10-minute Galaxy Home Recreation video, the bins are identical.

Why This Structure?

1. seq bin for timelines

I keep timelines separate from media assets. This prevents the Media Pool from getting cluttered with timelines mixed between footage bins. When I need to duplicate a timeline or export an XML, I know it's always in seq.

2. media as the root asset bin

All imported media lives under media, not scattered in the root. This keeps the Media Pool clean—only two top-level bins (seq and media), not 10+ bins competing for visual space.

3. footage split by type (interview vs broll)

For corporate/commercial work, most projects have two types of footage:

Separating these makes rough cutting faster. When I need an interview soundbite, I go to footage/interview. When I need a cutaway, I go to footage/broll. No hunting.

4. audio split by source (mx, sfx, on location)

Audio organization is critical for Fairlight mixing:

When I'm in Fairlight and need to pull a music cue, I go straight to audio/mx. No digging through a generic "audio" bin with 30 files.

5. gfx split by source (logos, ae, fusion comps, compound clips)

Graphics assets come from different sources:

Splitting by source makes it easy to find and update graphics. If a client sends a new logo, I know exactly where to replace it (gfx/logos).

Technical Implementation

The script uses DaVinci Resolve's Python API to programmatically create bins in the Media Pool.

1. Defining the Folder Hierarchy

The bin structure is defined as nested Python dictionaries:

masterFolders = {
    'seq': None,
    'media': None
}

mediaSubFolders = {
    'footage': None,
    'audio': None,
    'gfx': None
}

footageSubFolders = {
    'interview': None,
    'broll': None
}

Each dictionary key is a bin name. The None value is a placeholder—the script populates it with the actual bin object after creation.

This structure is declarative—I define the bin hierarchy once, and the script handles the creation logic. To add a new bin (e.g., vfx under media), I just add it to the dictionary:

mediaSubFolders = {
    'footage': None,
    'audio': None,
    'gfx': None,
    'vfx': None  # New bin
}

No need to modify the creation loop—the script auto-creates it.

2. Getting the DaVinci Resolve API Instance

The script connects to the running DaVinci Resolve instance via the Python API:

dvr = bmd.scriptapp("Resolve")
projectManager = dvr.GetProjectManager()
project = projectManager.GetCurrentProject()
mPool = project.GetMediaPool()
mPMaster = mPool.GetRootFolder()

Step-by-step:

This setup is standard for all DaVinci Resolve Python scripts. The API is well-documented (available in Resolve's installation folder under Developer/Scripting/README.txt).

3. Creating Master Bins

The script creates the top-level bins (seq, media):

for k in masterFolders:
    masterFolders[k] = mPool.AddSubFolder(mPMaster, k)

How this works:

After this loop, masterFolders['seq'] contains a reference to the seq bin object, and masterFolders['media'] contains a reference to the media bin object.

4. Creating Nested Subfolders with a Reusable Function

For subfolders under media, the script uses a reusable function:

def add_subfolders(subfolders: dict, masterKey: str) -> dict:
    for k in subfolders:
        subfolder = masterFolders.get(masterKey, mPMaster)
        if subfolder is not None:
            subfolders[k] = mPool.AddSubFolder(subfolder, k)
    return subfolders

How this works:

This function is reusable—calling add_subfolders(mediaSubFolders, 'media') creates footage, audio, and gfx under the media bin.

5. Creating Deeper Nesting (footage/interview, audio/mx, etc.)

For bins nested under footage, audio, and gfx, the script uses manual loops (since each has a different parent):

# Create footage subfolders
for k in footageSubFolders:
    footageSubFolder = mediaSubFolders.get('footage', None)
    if footageSubFolder is not None:
        footageSubFolders[k] = mPool.AddSubFolder(footageSubFolder, k)

This creates interview and broll under footage.

The same pattern repeats for audio and gfx subfolders. This is slightly verbose, but it's explicit—I can see exactly what bins are being created and where.

6. Setting the Active Bin to seq

After creating all bins, the script sets the Media Pool's active folder to seq:

mPool.SetCurrentFolder(masterFolders['seq'])

Why?

When the script finishes, the Media Pool cursor is in the seq bin, ready for me to create a new timeline. I don't have to manually navigate to seq after the bins are created—the script does it for me.

This is a small UX detail, but it saves a click and ensures I start in the right place every time.

The Watcher Script (Automatic Execution)

The folders.py script creates the bin structure, but the real magic is folders on demand.py—a background watcher that monitors DaVinci Resolve and automatically creates bins when you open a new project with an empty Media Pool.

How the watcher works:

import time
import DaVinciResolveScript as dvr_script

resolve = dvr_script.scriptapp("Resolve")
pm = resolve.GetProjectManager()

last_project = None

while True:
    current_project = pm.GetCurrentProject()
    
    # Check if project changed
    if current_project and current_project != last_project:
        media_pool = current_project.GetMediaPool()
        root_folder = media_pool.GetRootFolder()
        
        # Check if zero bins exist
        if len(root_folder.GetSubFolderList()) == 0:
            # Create standardized bin structure
            seq_bin = media_pool.AddSubFolder(root_folder, "seq")
            media_bin = media_pool.AddSubFolder(root_folder, "media")
            
            # Create media subfolders
            footage_bin = media_pool.AddSubFolder(media_bin, "footage")
            audio_bin = media_pool.AddSubFolder(media_bin, "audio")
            gfx_bin = media_pool.AddSubFolder(media_bin, "gfx")
            
            # Create deeper nesting
            media_pool.AddSubFolder(footage_bin, "interview")
            media_pool.AddSubFolder(footage_bin, "broll")
            media_pool.AddSubFolder(audio_bin, "mx")
            media_pool.AddSubFolder(audio_bin, "sfx")
            media_pool.AddSubFolder(audio_bin, "on location")
            media_pool.AddSubFolder(gfx_bin, "logos")
            media_pool.AddSubFolder(gfx_bin, "ae")
            media_pool.AddSubFolder(gfx_bin, "fusion comps")
            media_pool.AddSubFolder(gfx_bin, "compound clips")
            
            # Set active folder to seq
            media_pool.SetCurrentFolder(seq_bin)
            
        last_project = current_project
    
    time.sleep(2)  # Check every 2 seconds

Step-by-step breakdown:

  1. Connect to Resolve: scriptapp("Resolve") connects to the running DaVinci Resolve instance
  2. Track project state: last_project stores the previous project to detect when you switch or create a new project
  3. Polling loop: Check every 2 seconds if the current project has changed
  4. Detect empty projects: len(root_folder.GetSubFolderList()) == 0 checks if the Media Pool has zero bins
  5. Create bins: If empty, create the full bin structure inline
  6. Set active folder: Position the Media Pool cursor in the seq bin for immediate timeline creation

This means I never manually run the script. I just:

  1. Open DaVinci Resolve
  2. Create a new project or open an empty project
  3. Bins appear automatically within ~1 second

Why use a watcher instead of a Resolve startup script?

DaVinci Resolve doesn't support "on project create" hooks natively. The Python API allows scripts to run on demand, but there's no built-in event system for "new project created" or "empty project opened."

The watcher polls Resolve's state every 2 seconds and creates bins when it detects an empty project. It's a workaround, but it's effective—I've used this setup for months without issues.

Use Cases

Primary: Every New Project

I use this for every new DaVinci Resolve project regardless of client or project type:

The bin structure is generic enough to handle all project types. Even if I don't use every bin (e.g., a project with no graphics wouldn't use gfx/ae), having the bins present doesn't hurt—I just don't populate them.

Secondary: Reopening Old Projects

The real value of this script becomes clear months after a project wraps. When I reopen an old project to pull a shot for a new edit or export a different version for a client, I know exactly where to find assets:

I don't have to remember how I organized this specific project—every project uses the same structure.

Tertiary: Onboarding Collaborators

If I hand off a project to another editor or assistant, they don't have to learn my organizational system. The bins are self-explanatory:

This reduces the onboarding friction from "let me walk you through my bin structure" to "bins are self-explanatory, go ahead."

Time Savings

Manual process: Right-click → Add Bin → Type name → Repeat 15+ times (for all master bins, subfolders, and nested bins). Estimated time: 20-30 seconds depending on typing speed and familiarity with the desired structure.

Automated process: 0 seconds (watcher script auto-runs, bins appear automatically). Total manual effort: zero.

Savings per project: 20-30 seconds.

I create 2-5 new projects per week (client revisions, new spots, personal projects). At 3 projects per week, this saves 60-90 seconds (1-1.5 minutes) weekly.

But the real value isn't time—it's consistency. The script ensures every project uses the same organizational structure, which pays dividends months later when I reopen old projects and need to find assets quickly.

Why Consistency Matters More Than Time

This script saves 20-30 seconds per project, but that's not the primary value. The real benefit is eliminating inconsistency across projects.

Before this script, I'd create bins ad-hoc:

Three months later, when I reopen Project B to pull a shot, I waste 10-15 seconds hunting for the broll bin because I don't remember if I named it "broll," "b-roll," or "b roll."

With this script, every project uses the same structure. I know exactly where to find assets in any project, even years later. This eliminates cognitive overhead and reduces the "where did I put that?" frustration.

The automation also prevents decision fatigue. I don't have to think about bin names when starting a new project. The script handles it, and I can focus on importing media and cutting.

Implementation Notes

This script requires:

Running the Script Manually

To run the script manually (if not using the watcher automation):

  1. Open DaVinci Resolve and create a new project
  2. Open the Script Editor (Workspace → Console)
  3. Load folders.py and click "Run Script"

Or trigger it from the command line (macOS/Linux):

python3 /path/to/folders.py

Customizing the Folder Structure

To add, remove, or rename bins, edit the dictionaries at the top of the script:

mediaSubFolders = {
    'footage': None,
    'audio': None,
    'gfx': None,
    'vfx': None  # Add a new bin
}

The script will auto-create the new bin on the next run.

To add deeper nesting (e.g., subfolders under gfx/ae), define a new dictionary and add a creation loop:

aeSubFolders = {
    'lower thirds': None,
    'titles': None
}

# Create ae subfolders
for k in aeSubFolders:
    aeSubFolder = gfxSubFolders.get('ae', None)
    if aeSubFolder is not None:
        aeSubFolders[k] = mPool.AddSubFolder(aeSubFolder, k)

Setting Up the Background Watcher

To run the watcher automatically when you boot your Mac:

  1. Save folders on demand.py to a permanent location (e.g., ~/Scripts/folders_on_demand.py)

  2. Create a launchd plist at ~/Library/LaunchAgents/com.user.resolve-folders.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.user.resolve-folders</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python3</string>
        <string>/Users/YOUR_USERNAME/Scripts/folders_on_demand.py</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>
  1. Load the agent:
launchctl load ~/Library/LaunchAgents/com.user.resolve-folders.plist

The watcher now runs automatically at login and monitors DaVinci Resolve for empty projects.

To run the watcher manually (for testing):

python3 ~/Scripts/folders_on_demand.py

The terminal will stay open (the script runs in an infinite loop). When you create a new project with an empty Media Pool, bins appear automatically within 2 seconds.

Why This Matters

This script isn't about saving 20-30 seconds per project—it's about building a sustainable organizational system. When you're managing dozens of projects simultaneously and dozens more archived, consistency is the difference between "I know exactly where that asset is" and "let me spend 5 minutes hunting through bins."

The automation removes decision fatigue. I don't think about bin names or structure when starting a new project—the script handles it. I import media, create timelines, and start cutting. The bins are already there, organized the way I expect.

For anyone working on multiple client projects, collaborative edits, or long-term archives, this pattern is worth adopting. Define your ideal bin structure once, automate its creation, and never manually create bins again. Your future self (and any collaborators) will thank you when reopening old projects months or years later.

The watcher script integration takes it one step further: zero-click automation. I don't even think about running the script—it just happens. Open a new project, bins appear, start editing. That's the power of thoughtful workflow automation.