You’re Doing That Wrong is a journal of various successes and failures by Dan Sturm.

Customizing Native Nuke Nodes with addOnCreate

As much as I enjoy building custom gizmos to make my work in Nuke more enjoyable, they're really no replacement for native nodes that (hopefully, eventually) include the tweaked feature that I want.

In fact, trying to use a custom gizmo as a replacement for a native node can add friction since I end up with two results in my tab+search window rather than one. When trying to use my beloved FrameHold gizmo, I end up adding the old, dumb, native FrameHold node about half of the time. It's partly because there are two FrameHold nodes in my results, and partly because my custom gizmo shows up lower in the search results than than the native node. Sure, I could rename my gizmo to something unique to avoid ambiguity in the search, but that would come at the cost of precious muscle memory.

framehold tab search.png

But, thanks to an email from reader Patrick, I've recently become aware of the addOnCreate command in Nuke's Python API. Essentially, addOnCreate allows you to define a function to be run whenever a given Class of node is added, opening the door to customizing the native Nuke nodes as they're added to your script.

As a quick test, I used addOnCreate to add some TCL code to the labels of my TimeOffset and Tracker nodes.

# Time Offset Label Modification

def OnTimeOffsetCreate():
  nTO = nuke.thisNode()
  if nTO != None:
    label = nTO['label'].value()
    nTO['label'].setValue('[value time_offset]')

# Tracker Label Modification

def OnTrackerCreate():
  nTR = nuke.thisNode()
  if nTR != None:
    label = nTR['label'].value()
    nTR['label'].setValue('[value transform]\n[value reference_frame]')

# Add the custom labels to newly created nodes

nuke.addOnCreate(OnTimeOffsetCreate, nodeClass="TimeOffset")
nuke.addOnCreate(OnTrackerCreate, nodeClass="Tracker4")

(code only)

I've long been a fan of using the label of my TimeOffset nodes to show me how many frames have been offset. Especially handy for my kind of work, where a single animated element can be reused dozens times, offset in time, and randomized to make large animations easier to create and manage. For Tracker nodes, it's important to keep track of both the Reference Frame used, as well as the type of Transform being applied. Now, every time I add a TimeOffset or Tracker node, the additional information is automatically added to my node label.

Nuke default nodes on top. With custom labels below.

Nuke default nodes on top. With custom labels below.

As expected, there are limits to what you can modify with the Python API but, henceforth, this method of interface customization is going to be my preference, resorting to creating gizmos as a fall-back when I run into a limitation. The thought of dropping a single Menu.py file into my local .nuke directory, and having all my Nuke customizations show up, is incredibly appealing to me.

Node Sets for Nuke v1.1

Since creating the Node Sets for Nuke toolset back in June, I've been using it like crazy on all of my projects. Which has led to the discovery of one incredibly obnoxious bug.

This little guy is the maxPanels property at the top of the Properties Pane:


This is where you set the maximum number of node properties panels that can be open simultaneously. I usually keep mine set to 3 or 4. When I open a node's properties panel, if I already have the maximum number of panels open, the oldest panel, at the bottom of the list, is closed and the new panel opens on top. Which is great.

Unless, of course, you're trying to simultaneously open an unknown number of properties panels, all at the same time.

When using the Node Sets tool for showing all nodes in a set, I would have to manually set the maxPanels number to a value greater than or equal to the number of nodes I'd already tagged, prior to running the command. Since I usually have no idea how many nodes are in a set, I end up setting the maxPanels property to something I know is way too high, like 35. That way, when the Show Nodes in Set function runs, I won't be left looking at only 3 of my tagged nodes.

But since the Show Nodes in Set command is already searching through all the nodes to see which ones are tagged, wouldn't it be great if it could keep a tally as it searches and automatically update the maxPanels property to match?

Yes. That would be nice.

# Node Sets for Nuke v1.1

# This function opens the control panels of
# all the nodes with "inNodeSet" on their label

def showOnlyChosenNodes():
  names = []
  li = []
  for node in nuke.allNodes():
    if "inNodeSet" in node['label'].value():
  numPan = nuke.toNode('preferences')['maxPanels']
  for i in range(len(li)):
    node = li[i]

# This function adds "inNodeSet" to a
# new line on the label of all the selected nodes

def labelNodes():
  for node in nuke.selectedNodes():
    label = node['label'].value()
    if 'inNodeSet' not in label:
      node['label'].setValue( label +  '\ninNodeSet')

# and this one clears the label of
# all the selected nodes

def unLabelNodes():
  for node in nuke.selectedNodes():
    label = node['label'].value()
    if 'inNodeSet' in label:
      node['label'].setValue( label.replace('\ninNodeSet','') )

toolbar = nuke.menu("Nodes")
nsets = toolbar.addMenu("Node Sets")
nsets.addCommand('Node Set: Show Nodes', 'showOnlyChosenNodes()')
nsets.addCommand('Node Set: Add Selected', 'labelNodes()')
nsets.addCommand('Node Set: Remove Selected', 'unLabelNodes()')

In addition to updating the showOnlyChosenNodes() function, I've also renamed the actual menu commands to all start with Node Set:. This way, I can start a tab+search with the same three letters, nod, and quickly narrow results to the only 3 tools that fit that criteria; my Node Set tools.

node sets tab search

I love using Node Sets in Nuke and I'm glad to finally be rid of this annoying workaround.

iOS Spinner Gizmo for Nuke

Throughout the course of my work, I end up rebuilding and animating a lot of app interfaces. One of the most common pieces of the iOS interfaces I create is the "thinking" spinner.

It's one of those things that I almost always need, and typically forget about until I need one. Which usually results in me grabbing a screenshot of a spinner from the app and animating it to rotate. Which is not actually what it does [1].

Since I like to use my free time between projects to automate repetitive tasks, I built a Nuke Gizmo to take care of this in the future.

Default Spinner

Default Spinner

Dark Mode Spinner

Dark Mode Spinner

In order to make it useful in almost any situation, I made the spinner gigantic. It's built on a 1024x1024 Constant. It's got alpha and it's premultiplied, ready to go. It makes a full revolution in exactly 1 second [2].

Spinner Node Graph

The exposed controls are exceedingly basic. It has Transform, Scale, and Dark Mode controls. The default spinner is white on a semi-transparent black round-rect. Dark Mode switches it to a black spinner with no round-rect backdrop; typically used on mostly-white interface images.

I'm going to get a ton of use out of this little thing and, if you think you will too, hit the download link below. Drop the gizmo file into your .nuke directory and add the following to the bottom of your Menu.py file:

toolbar = nuke.menu("Nodes")
gzmos = toolbar.addMenu("Gizmos")
gzmos.addCommand("iOS Spinner", "nuke.createNode('iOS-spinner')")

Download: iOS-spinner.gizmo

  1. I animate them with an expression, not keyframes. I’m not an animal.  ↩

  2. Not the absurdly slow speed your browser is displaying the GIFs.  ↩

Automated Viewer Frame Handles in Nuke

When working on a VFX shot, more often than not, the plate's image sequence will include frame handles; an additional 8 or 12 frames at the start and end of the shot. The extra half or third of a second at the ends of the shot give us the flexibility to adjust in and out points later without having to come back to our compositing application and re-render the shot with a new frame range. Which is great.

But, when working on a shot in, say, Nuke, you'll often want to play back the shot without viewing the currently-extraneous frames. Lucky for us, Nuke has a these fun little red triangles on its timeline that you can drag around to set custom in and out points as you see fit. It's a great feature for focusing on a smaller range of frames for a specific task.

But, if you're trying to see eactly the frames that are currently in the edit, and only those frames, dragging around tiny red triangles isn't terribly precise. And the other option, typing in the first frame plus the handle, a hyphen, then the last frame minus the handle, is slow and requires math (yuck).

This being a well-defined, menial, and repetitive task, it's a perfect candidate for automation. With help, again, from my good friend Jake at The Foundry Support, I've added two new items to the bottom of my Viewer menu.

Now, all it takes is a single click (or keyboard shortcut, if you're so inclined) to quickly add 12 or 8 frame handles to my Viewer Timeline Range.

Here's the code to add to your Menu.py file in your .nuke folder:

def newViewerRange12():
  # Get the node that is the current viewer
  v = nuke.activeViewer().node()
  # Get the first and last frames from the project settings
  firstFrame = nuke.Root()['first_frame'].value()
  lastFrame = nuke.Root()['last_frame'].value()
  # get a string for the new range and set this on the viewer
  newRange = str(int(firstFrame)+12) + '-' + str(int(lastFrame) - 12)

def newViewerRange8():
  # Get the node that is the current viewer
  v = nuke.activeViewer().node()
  # Get the first and last frames from the project settings
  firstFrame = nuke.Root()['first_frame'].value()
  lastFrame = nuke.Root()['last_frame'].value()
  # get a string for the new range and set this on the viewer
  newRange = str(int(firstFrame)+8) + '-' + str(int(lastFrame) - 8)

# Add the commands to the Viewer Menu
nuke.menu('Nuke').addCommand('Viewer/Viewer Handles - 12f',
nuke.menu('Nuke').addCommand('Viewer/Viewer Handles - 8f',

Naturally, if you only ever deal with one duration for your frame handles, you can add just one of the functions, but I like having the flexibility of both options.

That Jake, he sure is good with the Python code, isn't he?

Update - 2014-10-25

The release of Nuke 9 is just around the corner and its revamped Viewer interface brings with it a small bug in my Viewer Frame Handles code (allegedly).

Design decisions in Nuke's new big brother, Nuke Studio, have made their way into the standalone app (reportedly) and now require the Frame Range Lock to be set before the new Frame Range is defined (or so I hear). Keen observers will notice that the last 2 lines of the newViewerRange functions above have been swapped to reflect this change.

According to a friend who's not me, the old code will still work in Nuke 9, but requires you to have existing In and Out points prior to running the command or run the command twice.

If you're planning on using this tool with Nuke 9 and Nuke Studio, you should update your Menu.py file now. The updated code will run properly in both Nuke 8 and Nuke 9 (so the story goes).

A Better FrameHold for Nuke

The FrameHold node in Nuke is one of my most commonly used tools when doing Roto/Paint/Clean-Up VFX work. When I'm creating patches to replace objects I've removed, I scrub through the sequence, looking for a frame that will work for my patch and, when I find one, I add a FrameHold node and start working.

Since, 99% of the time, my play-head is sitting on the frame I want to use for my FrameHold when I add the node, it would seem smart for the node to have the ability to grab that frame number, rather than requiring me to suffer the indignity of typing it into a parameter box.

On top, the old, dumb FrameHold. Below, my smart, handsome, new FrameHold.

I've created a gizmo called FrameHold_DS that adds exactly one feature to the standard FrameHold node; a "Use Current Frame" button. I submitted this as as feature request to The Foundry a few months ago, but why wait for a software update for such a simple feature.

As ugly as it is to use the "_DS" suffix for the node name, I wanted to make sure my version of the node would always show up in the Tab+Search tool when I started typing "FrameHold".

To Gizmo, Or Not To Gizmo

I've mentioned, on numerous occasions, that I prefer to create ToolSets over Gizmos because of their ease of installation, modification, and general use. Well, one thing Gizmos can do that ToolSets cannot is automatically open their properties pane as soon as the node is added to the node graph. And since the entire point of creating a custom FrameHold node is to make mine more efficient than the built in node, it would seem that use of a Gizmo is required to give this single-node-tool feature parity with the original.

To that end, here is the code required to add the Gizmo to the interface. Drop it into your menu.py file in your .nuke directory.

toolbar = nuke.menu("Nodes")
gzmos = toolbar.addMenu("Gizmos")
gzmos.addCommand("FrameHold_DS", "nuke.createNode('FrameHold_DS')")

And here is the link to download the Gizmo. Save it in the same .nuke folder, with your menu.py file.

Download: FrameHold_DS Gizmo

Node Sets in Nuke

UPDATE: A newer version of this plugin exists here.

The story goes like this. It may sound familiar.

You're working on an animation in your favorite node-based compositing application, and you want to make a timing change. The first half of the animation is perfect, but it should hold a little longer before it finishes, to better match the background plate.

Problem is, you've got animated nodes all over your script, and all of their keyframes need to move in sync. Transform nodes, Grade nodes, GridWarp nodes.

You zoom in and move around your script, looking for nodes with the little red "A" in the upper right corner.

No, not that node. That one's for that other asset and it doesn't need to move.

Okay, got 'em all open? Now switch the the Dope Sheet, grab everything after frame 75 and slide it to the right a few frames. Done?

Let's watch the new timing.

Shit. Forgot one.

Which one?

Oh, here it is. Wait. How many frames did the other 6 nodes move?



Okay, are they all open this time? Good. Now slide them all together.

Done? Let's watch it.


10 Minutes And 20 Additional Nodes Later.

Well...now I need a little less time between frames 30 and 42.


Feature Request

This is the annoying scenario I found myself repeating about a dozen times on a recent project, so I sent an email to The Foundry's support team, requesting the addition of a feature I described as "Node Sets".

A Node Set is an arbitrary collection of nodes that can be opened all at once with a single command. New nodes can be added as the script grows, or removed if they're no longer needed.

Along with my feature request, I provided these two screenshots to help explain:

What I received back from Jake, my new best friend at The Foundry Support, was the following script:

# This function opens the control panels of
# all the nodes with "inNodeSet" on their label

def showOnlyChosenNodes():
  for node in nuke.allNodes():
    if "inNodeSet" in node['label'].value():
      print node.name()

# This function adds "inNodeSet" to a
# new line on the label of all the selected nodes

def labelNodes():
  for node in nuke.selectedNodes():
    label = node['label'].value()
    if 'inNodeSet' not in label:
      node['label'].setValue( label +  '\ninNodeSet')

# This function clears the label of
# all the selected nodes

def unLabelNodes():
  for node in nuke.selectedNodes():
    label = node['label'].value()
    if 'inNodeSet' in label:
      node['label'].setValue( label.replace('\ninNodeSet','') )

# These commands create a new menu item with
# entries for the functions above

nuke.menu('Nuke').addCommand('Node Sets/Show Nodes in Set', "showOnlyChosenNodes()")
nuke.menu('Nuke').addCommand('Node Sets/Add Selected Nodes to Set', "labelNodes()")
nuke.menu('Nuke').addCommand('Node Sets/Remove Selected Nodes from Set', "unLabelNodes()")

For those of you who don't speak Python, allow me explain what's happening here. Once added to your Menu.py file, the script creates 3 tools in a new menu within Nuke.

Just as I requested, I have the ability to add or remove selected nodes from the group, then, when I need to make a change, open all of those nodes with a single command.


Not Magic

What the script is actually doing is tagging the nodes. No, Nuke did not suddenly or secretly gain the ability to add tags to things, it's cleverly using the label section in the Node tab to hold the inNodeSet text. The Show Nodes in Set command simply scans all the nodes in your script for nodes with inNodeSet in their labels, and opens them. Simple. Smart.

As a result, yes, you can add the inNodeSet text to the label field manually, rather than using the new menu command, and the Show Nodes in Set command will find it, but who would want to do such a barbarous thing?


As with all commands in Nuke, a keyboard shortcut can be added to these commands to make the process even quicker. But, since I don't particularly enjoy cluttering up my menu bar with unnecessary menus, nor do I enjoy having more keyboard shortcuts than I can remember (I totally already do), I opted to move the commands into the Nodes menu. This is easily done by swapping the last 3 lines of Jake's script with these lines:

toolbar = nuke.menu("Nodes")
nsets = toolbar.addMenu("Node Sets")
nsets.addCommand('Show Nodes in Set', 'showOnlyChosenNodes()')
nsets.addCommand('Add Selected Nodes to Set', 'labelNodes()')
nsets.addCommand('Remove Selected Nodes from Set', 'unLabelNodes()')

Here's where my tools now live.

I do this for one major reason; having these tools available in the Tab + Search tool. For those unfamiliar, Nuke has a built in tool similar to Spotlight or LaunchBar that allows you to press Tab then type the name of the tool you're looking for, avoiding the need to have keyboard shortcuts for every type of node.

Current Limitations

This being a bit of a hack, there are naturally a few limitations. First and foremost, using this tool will delete anything you already had in the label field of a node. I doesn't support the ability to add a tag to the text in the label field. The tag has to be the only thing in the label field.

Secondly, once you realize how useful this is, you may want to have more than one Node Set at your disposal. The good news about this current limitation is that you can very easily create as many node sets as you want by duplicating the code and changing the inNodeSet tag to something like inNodeSet2.

Of course, with multiple node sets, it'd be ideal if you could include a given node in multiple sets at the same time, but like I mentioned, this is not a real tagging system. If real tagging ever makes its way into the application, I imagine such a thing will then be possible.

Update - 2014-06-25

I emailed my pal Jake again, telling him how much I appreciate his work on this script, and you'll never guess what he did. He sent me an updated version of the script that adds the tag to the node label without overwriting the current text in the field.

Not only is this great for general usability, it means we can add a node to multiple Node Sets at the same time. We now have a real tagging system built into Nuke. How great is Jake? Seriously.

One thing I will note; if you are planning on using multiple Node Sets, you'll want to change the default tag to inNodeSet1. If you leave it as inNodeSet, it will also show up in results for other tags, like inNodeSet2.


If it wasn't clear before, all credit for this script goes to The Foundry and their awesome support team. They continue to be one of my favorite companies, specifically because they offer great support in addition to their great products.

I'm incredibly happy to have this annoyance removed from my workflow, and I hope you are too.

Creating Unique Footnotes with MultiMarkdown Metadata

Footnotes. Writers love ’em. But if you’re not paying proper attention when creating them, you can quickly make a mess of your website or blog. In fact, until very recently, this site had broken footnote links all over the place. I’m going to pretend like none of you noticed, and tell you about how I fixed the problem, gently glossing over my past stupidity.

Each post on this site starts as a MultiMarkdown document in Sublime Text 2. When it’s complete, I preview it in Marked, then copy the HTML code and paste it into a new Squarespace post.

The Problem

Thing is, since I’m creating the post locally on my Mac, with no reference to the site as a whole, Marked has no way of knowing which footnote IDs have already been used, and which have not. Therefore each post labels its first footnote fn:1 and subsequent footnotes increase by 1, as you’d expect. The problem occurs when viewing the home page that shows 10 posts on a single page, each with their own fn:1. When you click on the [1] link in the body text, where do you think it’s going to take you? That’s right, to the first footnote it finds with the label fn:1, regardless of which post it was intended to link to [1].

Now, Marked has a setting in its preference pane called Use Random Footnote IDs which is used “to avoid conflicts when multiple documents are displayed on the web.” So this is already a solved problem, right? Probably, but there’s a part of my brain that feels uneasy about using randomly generated IDs. I’m sure using this feature would solve my problem and everything would be fine, but since I’m a nut, I want to control exactly how these unique footnotes are created.

Enter MultiMarkdown. MultiMarkdown includes a number of enhancements to the original Markdown syntax [2], including support for customizable metadata fields [3]. So, I created a custom metadata key called footnote:. Here’s what my boilerplate MultiMarkdown header looks like [4] :

Author:         Dan Sturm      
Date:           %snippet:ddate%  
Marked Style:   ds_doc  

Now, whatever keyword I choose to add after the footnote: label will show up in the HTML header as [5].

Make With The Magic

The next thing I needed was a script to scan the HTML for the metadata key, and add it to all the footnote IDs, turning fn:1 into fn:my-footnote-key1.

import sys  
import re  
import subprocess

#   Open the file and convert it to searchable text  

fileText = open (sys.argv[1], "r+")  
searchText = fileText.read()

#   Pull the MultiMarkdown metadata key from the header  

mmdkey = re.search("(?<=\"footnote\" content=\")(.*)(?=\"/>)", searchText, re   .I)  
mmdkey = mmdkey.group()

#   Create the new footnote IDs  

fnnew = ("fn:", mmdkey)  
fnrefnew = ("fnref:", mmdkey)  

fnnew = "".join(fnnew)  
fnrefnew = "".join(fnrefnew)

#   Swap the footnote IDs for the new ones  

fnfix = re.sub("(fn:)", fnnew, searchText)  
fnreffix = re.sub("(fnref:)", fnrefnew, fnfix)

#   Strip HTML Header and Body tags. Copy the result to Clipboard  

def setClipboardData(data):  
  p = subprocess.Popen(['pbcopy'], stdin=subprocess.PIPE)  
  retcode = p.wait()  

fixStripped = re.sub("(?s).*(\n)\n", "", fnreffix)  
fixStripped = re.sub("(?s)\n\n\n().*", "", fixStripped)  

#   Write the updated code to the same file  

# fileText.seek(0)  
# fileText.write(fnreffix)  
# fileText.truncate()  
# fileText.close()  

Click here to download the script.

Now that we have that out of the way, let’s talk about how to actually use this code. I’m using a Hazel [6] rule pointed at a folder called Create Unique Footnotes. It looks like this:

The Hazel Rule

Simply put, it watches the folder for a new file and, when it sees one, it runs the script, displays a confirmation message, then trashes the now-unnecessary file, leaving the cleaned up, new code on the clipboard for easy pasting into your CMS of choice. So, when I like what I see in Marked and I’m ready to post, I hit CMD+S and save the HTML file to my Create Unique Footnotes folder, head over to my site, and hit CMD+V into a new post.

A Small Rabbit Hole

There are a few specific things I want to point out, just to make sure we’re clear.

The new HTML code is copied to the clipboard by the Python script, not by the Hazel rule. My workflow involves pasting HTML code into Squarespace, not uploading an HTML file and, since my MultiMarkdown file is the master copy of the post, that’s why I’m deleting the HTML file after running the script.

The HTML file being used as input for the script is a complete HTML document with a header, body tags, the whole shebang. I don’t need those extra bits when I’m pasting the code into Squarespace, so the Python script removes them before placing the code on the clipboard. In fact, the code on the clipboard looks exactly like what you see when you toggle the Switch to HTML Source View button in Marked [7] while previewing your MultiMarkdown document.

Another important note; keen observers will notice the last four lines of the Python script are commented out. That code is there for people who actually want a fully processed HTML document with fixed footnote IDs. Un-commenting-out [8] those four lines will write the fixed code over the original HTML document, while maintaining the header, et cetera. If you plan on using this workflow, you’ll want to remove the step in the Hazel rule that throws away the HTML document. I’d suggest you change that part of the rule to move the new HTML file to the Desktop as a sort of visual confirmation that the file has been updated.

I Believe Some Recognition is in Order

When I initially conceived of this idea I hadn’t the slightest idea how to best go about tackling it. I am not a programmer in any sense of the word. A Twitter conversation with my pal Sid O’Neill revealed that REGEX is the method by which I could find and replace items in the code. I don’t know how to do that, so…

Patterns is a Mac app for creating Regular Expressions that I’ve heard a number of people compliment in the past. It lets you see a live preview of the current pattern matches and, when you’ve got the selection you want, will generate the appropriate code for you; Python in my case. Completely indispensable and only $2.99.

Next, of course I have to thank Stack Overflow from whence I acquired some REGEX knowledge and code. Patterns comes with a great Reference Sheet for REGEX commands, but some of the descriptions still left me befuddled. Stack Overflow also linked me to…

This article by Gabe at Macdrifter, where I got the code that places the HTML on the clipboard. It was exactly what I needed, so I took it. And I would have gotten away with it if it wasn’t for you pesky kids and…nevermind.

In any case, high-fives all around. Go team.

  1. Some of what I’m describing is obfuscated by the use of Bigfoot for my footnotes, specifically the numeral for each footnote, but the problem remains. Let’s move on.  ↩

  2. Like footnotes, for one.  ↩

  3. You can learn all about MultiMarkdown Metadata here.  ↩

  4. Always invoked via TextExpander.  ↩

  5. Obviously, I need to choose a unique key for each post or this whole exercise is pointless.  ↩

  6. You do use Hazel, don’t you? Good.  ↩

  7. It’s in the upper right corner of your document, next to the fullscreen button.  ↩

  8. That’s so not a word, is it?  ↩

Open Last QuickTime File Macro

Yesterday, Dr. Drang had a nice post about creating a keyboard shortcut for the Open Recent menu item in BBEdit using Keyboard Maestro. I purchased Keyboard Maestro a few months ago and have been meaning to find some time to play with it. I’ve also been meaning to find a way to open the most recently viewed video in QuickTime with a global keyboard shortcut. Let’s skip right to the punchline.


Throughout the course of a project, I spend a lot of time referring to the most recent cut of a video alongside notes from the client. Once I know the next shot or note I’m going to address, I close the cut, my notes, and get to it. Since my notes live in nvALT, they disappear and reappear with a quick ⌃Z. Now, no matter what I’m doing, I can quickly summon the video file with a keyboard shortcut as well.

A simple tool that removes way more friction that you’d probably guess. It’s a good thing.

Managing Disk Cache (with a Hammer)

Throughout the course of a given project, I use a handful of applications to complete my work. At the moment, I edit in Avid MediaComposer and Final Cut Pro 7. I do my VFX work in NukeX. I review shots and conform sequences in Hiero. And I do final color correction in AfterEffects with Red Giant Colorista II. There’s an obvious advantage to using the right tool for the task at hand, but there’s a caveat that I almost never remember until it smacks me right in the face: disk space.

I’m not talking about the space required for digital negatives, plates, renders, or project files. No, the piece I always manage to forget is the massive disk cache each application in my workflow creates on my startup disk [1]. With single frames of a sequence ranging between 5 and 30Mb, and individual shot versions reaching well into double digits, disk cache can take up a ton of space. And since cache files are created whenever an element is changed and viewed, it’s not an easy task to estimate how much space will be used by a project ahead of time.

Most applications, including every application I use, have built in preferences designed to limit the size of the disk cache. Most also feature a big button labeled “Clear Disk Cache”. These preferences are great if you spend all your time in a single application, but are of little consolation when you’re halfway through previewing a shot in Nuke and OS X pops up telling you your startup disk is full. Once you’re in that sad, embarrassing moment, good luck getting AfterEffects to open so you can hit that “Clear Cache” button.

“To the Finder,” you say? Even if the Finder were responsive when your startup disk had less than 50Mb of free space, are you the kind of person that keeps a sticky note on your monitor listing the paths to all the buried, hidden cache folders for each application? Neither am I.

Historically, I’ve gone straight to my project’s Renders folder and deleted my 2 oldest exports, giving me about 6Gb of breathing room to go hunt down the various disk hogs. Not a great solution. What would be ideal is the ability to hit one keyboard shortcut, see a list of which applications are taking up space and, more importantly, how much space, then quickly purging the unnecessary files.

Normally, the sizes for AfterEffects, Nuke, and Hiero are in the double digits of Gigabytes. This screenshot was taken after using the script as intended.

The Script



echo Current Cache Size:  
du -c -h -s "/Users/dansturm/Library/Preferences/Adobe/After Effects/11.0/Adobe After Effects Disk Cache - Dan’s MacBook Pro.noindex/" "/var/tmp/nuke-u501/" "/var/tmp/hiero/" "/Avid MediaFiles/MXF/" "/Users/dansturm/Documents/Final Cut Pro Documents"  

read -p "Purge Cache files?(y/n) " -n 1 -r  
if [[ $REPLY =~ ^[Yy]$ ]]  
    rm -r "/Users/dansturm/Library/Preferences/Adobe/After Effects/11.0/Adobe After Effects Disk Cache - Dan’s MacBook Pro.noindex/"*
    rm -r "/var/tmp/nuke-u501/"*
    rm -r "/var/tmp/hiero/"*
    echo Done!

The script displays the space taken up by each application, the path to that cache folder, and a total of space used. It then prompts for a y/n input to delete the cache files.

Since managing Avid and Final Cut Pro media requires a bit more attention and nuance than a dumb hammer like this can provide, their disk usage is listed, but their files are not removed. If you modify the script to delete Avid of FCP media, allow me to preemptively say “I told you so” when your project becomes corrupted.


I run the script with a FastScripts keyboard shortcut. I wanted to shortcut to open a new Terminal window to display the information, so the keybaord shortcut actually calls a second short script called cache.sh which takes care of that part:


chmod +x /Path/To/cache.command; open /Path/To/cache.command  

The paths for the cache folders are hard coded into the main script and, as I mentioned, not all items listed are deleted. I like to see as much information as possible, but manage the deletion list more carefully.

For me, the main offenders of disk cache consumption are AfterEffects and Nuke which, together, average nearly 200Gb of disk usage. Once I’ve dealt with those 2 applications, I don’t usually need to go hunting for more free space.

Next time I accidentally inevitably fill up my startup disk with cache files, it’ll take seconds to rectify, rather than a half hour of excruciatingly slow, manual effort.

Hooray for automation!

  1. While it’s true that, in almost every application, you can re-map the disk cache folder to any disk of your choice, the entire point of a disk cache is to have the fastest read/write speeds possible, and no disk I own is faster than my rMBP’s internal SSD.  ↩

r_ScreenComp ToolSet for Nuke

In my previous post, I said I created QuickGrade so I could quickly balance my Log footage and start compositing more quickly. Based on the footage in the accompanying screenshot, you could probably guess what came next; replacing the screen on the device.

Creating a successful screen comp isn’t rocket science, but since it’s a very (very) common compositing task and, in many cases, the entire focus of a commercial, any tool that helps you work more quickly, while maintaining quality, is worth it’s weight in met-deadlines.

In uncharacteristic fashion, I’ll turn this post over to myself in video form to explain further.

There’s no chance I could have finished the number of shots I was assigned, in the time I had allotted, if it weren’t for this ToolSet. If you do a lot of screen comps in your day-to-day, even if you don’t use my ToolSet [1], I cannot recommend highly enough that you automate as much of the process as possible.


  1. Installing a Nuke ToolSet is as easy as dropping the R_ScreenComp.nk file into \.nuke\ToolSets\  ↩

QuickGrade Tool For Nuke

Lately, I’ve been doing a lot of VFX work with Alexa Log-C footage. Compositing with Log footage generally requires a Viewer LUT so you can actually see what you’re doing. I don’t like using LUT files because they’re fixed color transformations and usually need to be supplemented with additional color tools on a per-shot basis. While I was working, I found myself repeatedly creating the same “custom viewer LUT” setup, so I decided to make it a dedicated tool called QuickGrade.

QuickGrade default parameters.

QuickGrade isn’t really intended to be a creative color tool, it’s built to quickly balance your footage and make it look “correct”. I decided which controls were relevant by noticing that nearly all Alexa Log-C footage I encountered required the same adjustments:

  • Contrast: Obviously. It’s built to be flat.
  • Exposure: After yanking on the contrast, it usually needs an exposure adjustment.
  • Saturation: It’s not inherently overly desaturated, but it benefits from a boost.
  • Green-cast: Alexa Log-C footage typically needs a healthy amount of “de-greening”.

For added flexibility, I also included controls for White Balance, Black Point, and White Point. The controls in the top half of the node are for luminance, and the bottom half for color. Quick and simple.


Typically, I drop this node into the Node Graph above the Read node, unconnected, and set it as the Viewer Input Process [1], but it works just as well when used like any other color correction tool.

QuickGrade used as an Input Process.

Not A Gizmo

QuickGrade is a ToolSet for Nuke, not a Gizmo. ToolSets are easier to install than Gizmos, they show up in your toolbar without needing to write any Python code, and they’re easier to modify later if you feel the need. Since the whole idea behind creating this tool was ease of use and speed, the easy, lazy, ToolSet won out over the less easy Gizmo.

To install a Toolset in Nuke, just navigate to your .nuke directory. In there will be a folder called ToolSets. Unzip the QuickGrade.nk file, drop it inside, and you’re done.

  1. Using a node (or group of nodes) as a Viewer Input Process is as easy as right-clicking on the node, selecting Edit\Node\Use as Input Process. Bam.  ↩

My Custom Nuke Defaults

After a few busy months of post work, I finally found a few days to reevaluate and improve my workflows and system preferences. Since I spend a majority of my time in NukeX, that’s where I decided to start.

I’ve got some new custom tools I built recently that I’ll share with you soon enough, but first things first, Nuke’s default state needed a little adjusting. Here are the items I added to my init.py [1] file that save me tons of time and headache.


# Project Settings > Default format: HD 1920x1080  
nuke.knobDefault("Root.format", "HD")  

# Viewer Settings > Optimize viewer during playback: on  
nuke.knobDefault("Viewer.freezeGuiWhenPlayBack", "1")  

# Write > Default for EXR files: 16bit Half, No Compression  

# Exposure Tool > Use stops instead of densities  
nuke.knobDefault("EXPTool.mode", "0")  

# Text > Default font: Helvetica Regular (in Dropbox folder)  
nuke.knobDefault("Text.font",   "/Path/to/Dropbox/fonts/HelveticaRegular.   ttf")  

# StickyNote > default text size: 40pt  
nuke.knobDefault("StickyNote.note_font_size", "40")  

# RotoPaint > Set default tool to brush, set default lifetime for brush and clone to "all frames"  
nuke.knobDefault("RotoPaint.toolbox", "brush {{brush ltt 0} {clone ltt 0}}")  

Explain Yourself

Since I don’t work in feature film VFX, the HD frame size is a no-brainer.

I do a fair amount of motion graphics animation in Nuke, so I often have the Curve Editor open. I’ve always been frustrated that Nuke never seems to be able to achieve realtime playback when looking at curves, so I ended up making adjustments, then switching back to the Node Graph to view my changes. Very annoying. The recently added “Optimize viewer during playback” button was the answer to my realtime problems [2]. Like all of these custom preferences, I use it so often, I want it to be on by default.

I comp almost exclusively in Open EXR image sequences. For me, 16bit Half Float with No Compression is the appropriate balance of file size and quality. By default, the Write node sets compression to Zip (1 scaneline) and it annoys the crap out of me to change it every time.

I love to use the Exposure tool, especially when color-correcting Log footage by hand [3]. But since I’m a filmmaker and a human being, I prefer to adjust exposure in Stops rather than Densities.

I set the Text node to use Helvetica by default and I keep the font in my Dropbox folder to make sure it’s always with me. Why? Because the default is normally Arial and seriously, are you kidding me?

I love using StickyNote nodes to write myself notes as I’m working. But because either my screen resolution is too high or I’m getting old and going blind [4], I always have to crank up the font size to read the damn things.

When I decide to use a RotoPaint node instead of a simple Roto node, it’s because I want to paint something. And more often than not, I want to paint or clone something for the entire duration of the shot, rather than just a single frame. Boom. Default.

What Else?

I would love to set the default feathering falloff in the Roto and RotoPaint nodes to smooth rather than linear, but I haven’t been able to figure out how to make that happen as of yet.

If you’d like to use these preferences in your Nuke setup, simply copy and paste the code into your init.py file in your .nuke directory. If you don’t have an init.py file in there, just open a text editor and make one.

Happy comping.

UPDATE – September 09, 2013, 04:55:04PM

As Joe Rosensteel pointed out on Twitter, another great tip is changing your 3D control type to Maya controls. I’m not a Maya user myself, but nearly all the 3D artists I work with are, and nothing makes them happier to help you out than saying, “Would you like to take stab at it? You know the 3D controls are the same as Maya’s”. And the 3D control type preference is super easy to adjust. It’s part of the GUI in the application preferences pane, under the Viewers tab.

  1. If you were unaware, you can modify Nuke’s default state by creating a file called init.py in your .nuke directory. The application loads your preferences on launch and it’s easy enough to add/remove settings without screwing up your install. More info on page 18 of the Nuke User Guide  ↩

  2. I don’t remember exactly which version introduced it, but it’s the button that looks like a snowflake to the left of the playback controls.  ↩

  3. Yes, I’m familiar with the concept of LUTs.  ↩

  4. Rhetroical.  ↩

Fountain Cheat Sheets Revisited

TL;DR: Click here for an online version of this Fountain Cheat Sheet

Thanks to recent releases of awesome apps like Highland and Slugline, Fountain, the plain text screenwritting syntax, has been getting a lot of attention. As Fountain newcomers are getting up to speed on the syntax, many have been searching for a Fountain cheat sheet for quick reference.

Highland and Slugline both include features that allow you to “just write” without having to think about syntax, but the promise of Fountain is its ability to be used in any application that takes text input. Thus, a quick reference guide may be of some use to recent plain text converts.

A little over a year ago I reproduced the Fountain syntax guide in a Cheaters page. And then I promptly forgot about it. It wasn’t until the release of Highland that I realized why I never used my own cheat sheet; it wasn’t a cheat sheet. It was a complete syntax reference manual; something that’s almost never useful when writing a screenplay.

Highland ships with a beautiful built in Fountain cheat sheet. It’s short, simple and easy to use at a glance. So, naturally, I ported it to Cheaters so I could have it available at all times.[1]

Left: Highland Cheat Sheet, Right: Cheaters Cheat Sheet

If you’d like to use it, here’s the new Fountain cheat sheet and the previously created CSS file. Toss those files into the Cheaters cheatsheets and css folders, respectively, and add the link to the Cheaters app in the index.html file with the line:

<li data-preserve-html-node="true"><a data-preserve-html-node="true" href="cheatsheets/fountain_h.html">Fountain</a></li>

For more information on customization, head over to the Cheaters page on Brett Terpstra’s site. Happy writing and welcome to Fountain!

  1. I even included the “Learn More” link to the full Fountain syntax guide, should the need arise.

Update - 09/05/14

The cheat sheats have been updated with a Forcing Elements section to match the Fountain 1.1 spec.

Intel Fabs Hit the (Really) Big Screen

Click to see full resolution version.

Click to see full resolution version.

The Show

Every year Intel® holds a conference for its Sales and Marketing Group known as ISMC. Over the course of several days, attendees get hands on with Intel’s latest products, meet with Engineers, take training classes, and attend keynotes from company executives.

Being the one major face-to-face event each year for the global sales force, the conference is a big to do. For ISMC 2012, Intel Studios [1] was asked to create a video unlike any we had produced before [2].

The Project

One of the recurring keynotes at ISMC is given by the head of the manufacturing division of the company; giving the audience a look at the innovation and engineering behind the products they sell, as well as a glimpse at the company’s roadmap for the coming years.

Presenting for ISMC 2012 was Executive Vice President and Chief Operating Officer Brian Krzanich; one of Intel Studios’ regular customers. Over the years we’ve created a number of products to accompany his presentations, both internally and externally.

For 2012, the project request was straightforward. Intel was in the process of building two identical manufacturing facilities in Arizona and Oregon, at a cost of around $5 Billion each. The factories represent the state of the art for semiconductor manufacturing [3], but more importantly they are two of the largest cleanroom facilities in the world.

Our job was to highlight the massive scale of these new factories, larger than any Intel has built before, required to make microprocessors at a scale smaller than ever before. The two factories being built were identical, so since our studio was located in Arizona, and production was to take place in December, the Arizona factory was chosen as our subject.

With little more direction than that, we began to develop a story for the video. During concept development we discussed a number of ideas for emphasizing the enormous size of the construction project with the appropriate amount of “wow factor”. Our answer came in the form of the video’s playback venue.

The Venue

The Anaheim Convention Center

The keynote presentations were set up with three projector screens above the stage that would be used together as one large, contiguous display. The combined screen measured nearly 160 feet wide, with a resolution of 7,360 x 1,080; more than twice the width of a standard cinema screen. With a display of such unique proportions, it was an easy decision to shoot panoramic video that would span all three screens, rather than create a collage of separate images to fill the space.

It was sure to be an incredible viewing experience, but within that opportunity was a major technical hurdle for the production team. At the time of production, no single camera existed that was capable of capturing an image of the required resolution. Still, we knew this was an avenue we wanted to pursue, and preproduction for a panoramic video began.

As we were discussing technical solutions to our resolution problem, it was suggested that we shoot with a single Red Epic camera, with a resolution of 5,120 x 2,700, and scale up the final image to fit the screen. While this would have been the easiest solution to implement both on set and in post, it failed the selection criteria for two reasons.

First, the image would be scaled to more than 140% of its original size, compromising the clarity of the final image. And even if a 140% blowup provided an acceptable level of quality, the math is not quite so simple. The Epic has a 5K Bayer pattern sensor that produces a measurable resolution closer to 4K. If we treat the Epic as a 4K camera, we’d be looking at a blowup closer to 180%. With a viewing distance between 30 and 200 feet in the auditorium, the quality loss may have been imperceptible to the audience, but the bigger issue was one of sensor size and optics.

To highlight the size of the factory and take full advantage of the massive screen size in the auditorium, we needed to shoot images with a large Field of View (FOV). The FOV of a given image is determined by a combination of the lens’ focal length and the size of the camera’s sensor [4]. Since there were practical limitations to the focal length of the lenses we would use (more on that in a moment), the only way to create an increased FOV was to increase the width of our sensor. Since we can’t change the actual sensor in the camera, we would need to find a way to combine multiple cameras, each with their own Super–35 sized sensor [5], to simulate a larger sensor camera.

Camera Selection

Now that we knew our solution would involve multiple cameras and wide angle lenses, we started crunching numbers to see which lenses we would use and how many cameras we would need. We could have easily satisfied the technical requirements for projection with two Epics, but we opted to use three cameras for a few reasons.

The first reason was this idea of a simulated large sensor camera. With a two camera solution, we’d need to use the widest possible lenses to properly capture the subject; the factory. The use of extreme wide angle lenses would give us a great deal of optical distortion around the edges of the frame and make postproduction very difficult when attempting to stitch the cameras together. Since we’d have essentially zero time to test just how much distortion would be too much, the safer choice was to use longer lenses on three cameras. Not to mention that using two cameras would place the stitch seam right in the middle of our final image. If there was any slop in the composite, there would be nowhere for our mistakes to hide. So, while we came prepared with a set of Tokina 11–16mm lenses, the widest focal length we used was around 25mm on two Red 18–50mm lenses and one Red 17–50mm.

On that note, we had initially hoped that postproduction would be as simple as hiding the seams of our final image in the small gaps between the three playback screens. However, during a preproduction meeting, we were informed that the center screen would be a good deal wider than the side screens, requiring us to deliver a seamlessly stitched image under the assumption that the seams would be on screen. Starting with a roughly 15K raw image gave us the ability to adjust the overlap between the three cameras based on the objects in the scene and the varying amount of parallax between the foreground and background objects; something that we would learn on set was extremely important for creating successful images.


After selecting the Epic as the camera for this job, we immediately requested three days of camera rental to test our yet-unproven design for the camera platform. Building an effective camera rig from scratch in under a week is a difficult task when it doesn’t involve multiple cameras.

As with most decisions involving money, it would take several days for us to receive an answer. With the start of production mere days away, there was no time to waste. Using what we had in the studio, we grabbed three Canon T3i DSLRs, some small tripod ball heads, and a cheese plate to create a proof of concept camera rig.

With no idea how best to align the three cameras, we created two proof of concept rigs; one to test correcting a vertical disparity between camera sensors and one to test a horizontal disparity. It was clear from the moment we turned on the cameras that the vertical rig was unusable, so on we went with our design of the horizontal rig.

Test rig with vertical disparity

Test rig with horizontal disparity

We set up the camera rig outside, near a corner of our office building, giving us a wide view of two sides of the building, the parking lot, and the street. Our primary concern for the stitching process was correcting the parallax discrepancies created by the physical separation of the cameras so, in the test footage, we had a person walk through all three frames, at a variety of distances from the cameras, to see how much error we would encounter in the stitching process. From there the footage was brought into Adobe AfterEffects, synced and aligned.

We determined we were able to stitch and sync the cameras to a relatively high level of success in just a few minutes but, as predicted, the camera separation caused serious parallax discrepancies that had to be corrected with shot-specific compositing. In our test footage, we got a successful panoramic image not by aligning the building that spanned all 3 cameras, but by ensuring that alignment was accurate at the object on which the viewer was focused. In this case, we had to ensure accurate alignment on the person crossing the screen and get creative with hiding misalignment in the background.

The aligning and stitching process felt surprisingly similar to Stereoscopic 3D postproduction we had completed for the 2011 ISMC Keynote [6] where we would ensure elements on the convergence plane were aligned perfectly, and would work around errors in the distant background or close foreground.

A major misstep in our testing process that would come back to bite us later was our failure to test camera movement. The final product was scripted to include pans, tilts, and jib moves, but we were in a hurry to report back to the production team as to the camera platform’s technical feasibility. We attempted to modify a tripod to accept our cheese plate camera platform, but it was clear from our lack of available hardware and materials that in order to test a moving shot we’d have to push back testing at least a day. After an hour of fruitless experimenting with the tripod, we gave up and decided to shoot the test static, propping up the rig on some apple boxes.

After shooting the tests, we spent the rest of the day trying to stitch the images, hiding seams and parallax errors. Just as we began to feel comfortable with the process that would be required, we received word that there was not enough money in the budget to test the real camera setup with Epics.

Building The Rig

By now it was Friday and production was set to begin on Monday. Two of our three rental Epics had arrived, along with a variety of cheese plates and assorted hardware. We spent the day gathering the rest of the production gear and laying out potential designs of the camera platform.

The first incarnation of our camera platform was built as small as possible to keep the cameras close together and minimize overall weight, but after seeing how much the metal flexed under the fully built rig, we realized larger and thicker cheese plates would be required. We also benefited from using larger plates in our ability to slide the cameras forward and backward on their dovetails, giving us greater balance control over the more minimalist rig.

Initial smaller camera platform design

Final camera platform with larger cheese plates

On Saturday the production team gathered in our studio to build what would hopefully be our final camera platform. We had our jib operator bring his gear so we could make sure our solution would mount properly to his equipment. The majority of the day was spent drilling into the cheese plates so we could countersink the large bolts that were necessary to hold the pieces together.

The addition of a small plate and some angle-iron on the far side of the platform allowed us to attach a support cable to the arm of the jib, taking the weight off of the delicate motors and reducing the amount of bounce to the system. We wouldn’t find out for another couple of days, but it sure looked like we had a camera rig that was going to work.

Here you can see the additional support cable connecting the far edge of the camera platform with the jib arm.

Just like every other step of the project, we documented the rig building process with our iPhones. When we had the cameras up and running, I posted two photos of our setup on Twitter.

The next day, I received a response from a gentleman names Zac Crosby that included a picture of a panoramic rig built with Epics that he had recently used for a project. His rig was different than ours, built in an almost cube shape with a larger angle between the cameras than we had chosen. It seemed as though Zac’s rig was built to serve a purpose different than ours, but our optimism was re-energized by the idea that we were not the first to attempt such a thing. Especially in light of the (completely unfounded) assumption that if his project had suffered some catastrophic failure, he would have cautioned us about shooting panoramic video.

Lens selection

Since we had to place our gear order before we had a rig design, we took our best guess at which lenses we would need. Being that our goal was to create a massive wide angle image, we ordered three Tokina 11–16mm PL mount lenses, as well as two Red Zoom 18–50mm lenses to supplement our own Red Pro Zoom 17–50mm lens.

To mitigate some of our risk, not every shot in the video was to be shot panoramic. There would also be instances of collages made up of multiple images, so we brought along our Red Pro Primes, as well as an Angenieux Optimo 24–290mm zoom.

When we finally got lenses on the cameras, we determined a focal length between 20mm and 40mm gave us the best balance of a wide FOV, minimal lens distortion, and enough overlap to properly stitch the shots.

For the majority of the shoot, all three cameras were sporting the Red Zoom lenses. Since we already owned a Red Pro Zoom 17–50mm lens, we only rented two more zooms. In our search for local rental gear, we were only able to find the older 18–50mm Red Zooms. Having never put the updated model side-by-side with its predecessor, we were unaware of the dramatic differences in optical distortion between the two.

The mismatched distortion turned out to not be a problem, but due to our inability to properly test the camera setup, it wasn’t discovered until we began to stitch dailies on set and found undistorting images was not producing expected results. A potential disaster, averted by sheer luck.

On Set

Monday morning started with a lengthy safety briefing from our site escorts before driving our grip truck, with DIT station inside, onto the heavily guarded construction site.

Once inside, we built our camera rig on the jib. We brought along a Fisher 10 dolly, but it was mostly used as a building and transportation platform for the camera rig before transferring it to the jib for shooting. The dolly was also used, to a lesser degree, for one-off static shots between setups. It was the last thing loaded onto the truck and the first thing off, so we occasionally rolled it to the edge of the lift-gate and picked off a few shots from an elevated position.

The cameras were set to record in 5KFF (to take full advantage of the sensor’s FOV) at 24fps and a compression of 6:1. As is often done on shoots involving multiple cameras, each camera, its associated accessories, and magazines were color coded to avoid confusion. A small effort that greatly helped speed up downloads and dailies.

Once we had the jib operating on a live set, we immediately noticed that any tilting of the camera platform caused the left and right cameras to dutch severely. Obvious in retrospect, as all three cameras were rotating on a different axis to their focal plane.

Since our time on the construction site was limited, redesigning the camera platform was not an option. Instead we had to limit our camera movement to booming up and down.

We discovered another limitation of the camera rig while attempting to swing the camera from left to right, following our talent, and booming up over a large mound of dirt to reveal the construction site. Since our talent and dirt hill were about 20 feet from the camera and the construction site was about 200 yards away, our parallax was irreconcilable and, due to the horizontal movement of the jib, there was nowhere to hide the seams should we try to hack the shots together.

After declaring the setup unusable, it was recommended that we either reshoot the scene, limiting the camera move to a simple boom-up, or we spend an unknown amount of time in post separating and completely rebuilding the shot in VFX, to an indeterminable level of success. As with production, our post timeline was extremely limited so we opted to reshoot the scene the next day.

Once we understood the rig’s limitations, the production proceeded relatively smoothly. The only hiccup occurred when one camera’s dovetail came loose in transit, causing the camera to do a backwards somersault off the jib onto the ground. Luckily the jib was only about 12 inches off the ground and the camera landed squarely on the Red Touch 5.0 LCD. The camera was unharmed, and the LCD was perfectly functional, but the metal swivel near the lemo connection snapped and the frame of the LCD was scuffed [7]. The Epic, though, is a tough camera and we were back up and running in a matter of minutes.

Since we knew we would need to undistort the images from each camera in order to stand a chance at stitching them together, we created several 24’’ x 36’’ checkerboard grids on foam boards that were recorded at the beginning of each setup.

Our inability to test the rig in preproduction also resulted in one of our more clever solutions for syncing the cameras. We had neither the cabling nor the knowledge to properly timecode sync three Epics. Our solution involved placing our 24’’ x 36’’ foam lens distortion grid about 4 inches away from the center camera so it was just barely visible on all three cameras at the same time. When the card was in place, someone would flash a DSLR flash against the white board, causing a flash-frame on all three images. It didn’t give us perfect results, and sometimes we had to flash the board twice since the shutters on each camera were not synced, but it was effective enough to give us a useful sync point.


DIT station in the back of the grip truck

I was acting as the production DIT and Visual Effects Supervisor. As such, I was responsible for not only backing up footage, but attempting to stitch as many shots as possible while we still had the opportunity to reshoot them should there be an issue with a given setup.

Since nearly all of our prep time went to assembling the camera rig, we didn’t have much of an opportunity to customize our DIT station. I was able to make sure the system arrived with a large e-sata raid, additional e-sata ports for the Red Stations, and a Red Rocket card for realtime processing. The only software I had an opportunity to load aside from AfterEffects was a tethering app for my iPhone, allowing me to download software in the field as needed [8].

This being essentially an “out of the box” Mac Pro, it was outside our firewall and unable to connect to our license server running Nuke. Our composites were to be finished in Nuke, but stitching on site was only possible with our local copy of AfterEffects, resulting in some rework for me later and a few inconsistencies between on-set results and the final composites.

All backups were performed with R3D Data Manager and all dailies were created with RedCine X. For the dailies, I selected the best take of a given setup, and created a full resolution, 5K JPEG image sequence from each camera.

The JPEG sequences were immediately imported into AfterEffects and undistored with the help of the lens grid charts. Since we used limited focal lengths during shooting, I was able to reuse lens distortion data to speed up the stitching process from shot to shot, getting the undistored plates “close-enough” for a quick and dirty composite. Imperfect lens correction was acceptable at this point because stitching on set was only for the purpose of checking parallax errors and determining if we would be able to hide issues in the final composite.

When I felt I had a composite that was good enough and would be easy to finalize in Nuke with a proper amount of attention, I rendered a 3,680 x 540 H264 file to watch (repeatedly) at full screen on the 30’’ Apple Cinema Display. When the Director, Producer, and DP had bought off on the successful stitch, I moved on to the next shot, while continuing to download, transfer, and render in the background. When our four day production ended, we had nearly 4Tb of data, consisting primarily of the raw camera backups.

The largest obstacle to overcome for the DIT work was my physical location. Since we were on a secure construction site with a minimal number of escorts, the most pragmatic location for the DIT station was in the back of the grip truck, traveling with the crew. Our grip truck is equipped with an on-board generator, but this meant I was unable to charge batteries or backup footage overnight [9], and since we had contractors working in our crew, we were held to a strict 10 hour day [10].

Another frustration for DIT work was the cold temperature in the back of the grip truck. If you’ve never been to a desert like Phoenix in the winter, you probably wouldn’t assume the temperature drops as low as it does. Construction shifts begin early and so did we. Our call time each day was pre-dawn and the temperature was in the 30s. The days warmed up around midday, but the shaded location for the metal Mac Pro typically stayed around 50 degrees Fahrenheit.

I bring up the cold mornings not as a complaint about uncomfortable conditions, but because extreme temperatures affect electronics. The DIT station was built into a rolling shipping container, designed specifically for working in the field. That was great for portability, but it made the swapping of components incredibly difficult, specifically the main surge protector that powered the system. Each day, the device that had worked perfectly in our warm office the week before, refused to power up on the first three attempts. On the fourth, the system would boot and remain on all day, but it was certainly a scare that we didn’t need each morning.

Along with the surge protector, the monitor occasionally obscured the images with a snowy noise not unlike an old analog television. My assumption at the time was the graphics card had come loose during travel and needed to be adjusted in its slot. A reboot and a jiggling of the DVI cable seemed to resolve the issue each time it occurred.

In the recent weeks, this system was still exhibiting some odd behavior. After the graphics card was swapped to no avail, the system was sent back to Apple for further investigation. They were able to determine the fault lied with the electronics in the 30’’ Cinema Display, not the graphics card. Additionally, they found a crack in the motherboard of the Mac Pro which occurred on the shoot, proving just how lucky we were to even finish the project.

Monitor problems

The Edit

At the time of production, Intel Studios’ primary NLE was Final Cut Pro 7. One limitation in FCP7 is its inability to edit projects with a resolution above 4K. We built a custom project template inside of Final Cut, allowing us to edit in 4K and transfer the project to AfterEffects for finishing at full resolution, but it was overly complicated and introduced many opportunities for failure.

As a result, we took this opportunity to audition Adobe Premiere Pro CS 5.0 as a replacement NLE [11]. Premiere offered us the ability to create a project at our full, final resolution of 7,360 x 1,080. With the aid of another Red Rocket card, the editor was able to assemble the project from the full resolution R3D files.

At the same time, I created EXR and JPEG sequences of the selected panoramic takes and created the final stitched composites in Nuke. Ninety percent of the compositing was done with the JPEG sequences to ease the load on the CPU and our network. This became especially important when we found the best results were generated by using camera re-projection in Nuke’s 3D environment, and photographing the 3D composite at the full 7K resolution. While this technique slowed the compositing process compared to a traditional 2D composite, the time was reclaimed when we were able to reuse the 3D camera re-projection rig, again thanks to our limited number of focal lengths used on set. Before rendering, the JPEG sequence was swapped for the EXR sequence and final color matching of the three cameras was adjusted.

When a shot was completed it was again rendered at 3,680 x 540, this time in ProRes HQ, and scrutinized on a 30’’ computer monitor. Once approved, a 7,360 x 1,080 TIFF sequence was sent to the editor for integration into the video.

How To Build A Better Rig

If we were to attempt such a project again (hopefully with a bit more time and money) I’d be very interested to test the potential use of a Stereo3D beam splitter camera rig.

While it’s certainly not designed for this purpose, using a stereo rig set to zero interaxial distance and adjusting convergence to pan the second camera, I think we could design a panoramic video rig that would be much more forgiving with parallax errors, and create better looking final images. Additionally, if we were able to remove the majority of the parallax errors by getting the sensors closer together, the use of two cameras instead of three might be feasible.

So, How Did It Look?

After all the production hurdles we encountered, I must admit, seeing 160 foot wide, 7K+ panoramic video was beautiful. More importantly, the crowd and the customer loved the video. It’s hard to ask for more than that.

The Crew

By now, one thing that should be patently obvious is that the success of this project was due entirely to our dedicated and talented crew. I would be remiss if I did not recognize them here:

Writer/Director: Roland Richards

Producer(s): Charlyn Villegas, Keith Bell

Director of Photography: Jeff Caroli

1st AC: Josh Miller

DIT/Compositor: Dan Sturm

Editor: AJ Von Wolfe

Music by: Karlton Coffin

And additional thanks are in order for Keith Bell who both commissioned this writeup and offered editorial guidance.

Photo Gallery

  1. Intel Studios is an internal media team within Intel® Corporation.  ↩

  2. In the name of disclosure, I must inform you that, as of March 2013, I am no longer an employee of Intel® Corporation.  ↩

  3. 14 nanometer process technology, to be more specific.  ↩

  4. For a practical demonstration of how sensor size affects Field of View, check out this awesome web app from AbleCine http://www.abelcine.com/fov/  ↩

  5. Technically the Red Epic sensor is slightly larger than Super–35, measuring 27.7mm (h) x 14.6mm (v) versus Super–35’s 24.9mm (h) x 14mm (v).  ↩

  6. A very long story for another time.  ↩

  7. We immediately purchased a replacement LCD for the rental house. Sorry Jason and Josh!  ↩

  8. I do not recommend this solution, even if you have an unlimited data plan. Talk about unreliable.  ↩

  9. The construction site, until completion, was the property of the construction company. Despite being an Intel facility, we were guests and required to abide by a great many rules regarding safety. Leaving an unattended generator running in a truck overnight was not allowed.  ↩

  10. When you factor in security briefings, the inability to leapfrog setups, and waiting for construction cranes that cannot be directed, 10 hours is much less time than you’d think.  ↩

  11. Since development of FCP7 had been abandoned by Apple in favor of the replacement product FCPX, we were already in the market for a new NLE.  ↩

"Send With Gmail" Service for OS X

Do you ever need to send an email, but hate the thought of opening Gmail and seeing an inbox full of expectations?

On this week’s episode of Systematic, Merlin told Brett how much he enjoys using Drafts on iOS to quickly send an emails to solve exactly that problem. He also mentioned there isn’t an easy way to achieve the same thing on the Mac. Since I wanted such a tool to exist, I decided to take a whack at it and see what I could come up with.

I thought the best fit for such a tool would be a system service. As much as I still enjoy using TextExpander to process text, copying the email content to the clipboard and typing a snippet is inelegant and leaves room for error. A system service can be called from pretty much any application with a quick keyboard shortcut of my choosing. Besides, I’ve never created a system service before and where’s the challenge if I don’t try something new?

How Does it Work

Like Drafts, it uses the first line of input as the subject of the email and lines three through the end for the body, assuming you’ll leave a blank line between the subject and body. Optionally, you can launch an empty Gmail message by using your key command with an empty selection [1].

The service uses Gmail’s URL syntax which allows fields to be prepopulated in the address bar. It’s the same idea behind the YouTube URL scheme that allows you to do things like link to a specific time in a video. For my purposes I would need the syntax for subject, body and opening the compose window in full screen [2]. As it happens, those URL parameters are as follows:

subject: su=
body: body=
full screen compose: fs=1

Just like YouTube, these parameters are concatenated with an ampersand, creating a URL that looks like this:


When using the service, you can compose your message in any application, then, when you’re ready to send it, select the text and hit your keyboard shortcut. As long as you’ve previously logged into Gmail in your browser, you’ll be taken directly to a full-screen compose window awaiting your recipient’s email address. And even better, after you hit send, you won’t be taken back to your inbox.


This being the complete hack that it is, there are some limitations to the service.

First, it’s plain text only. Since the content of the message passes through the location bar of your browser, there’s no way (that I can tell) to pass rich text. My hope was to be able to write emails in Markdown and process the text before sending, but as of yet, I haven’t been able to figure out how to make that happen.

EDIT 2013-03-11: As luck would have it, it seems our friend Brett Terpstra, with the help of Tobias O'Leary, has solved this particular problem for us.

Second, and this is a big one, there is a limit on the length of the email. It may sound like a deal breaker, but in practice it’s not as inconvenient as you might imagine. Because this hack uses a URL to pass the email information, we’re limited by the maximum URL length supported by the browser. Yes, there is a maximum URL length.

In my testing, I found the maximum length of a working URL was 1465 characters. The result was the same for both Chrome and Safari. Since the service is adding extra characters to the email content in order to create a functioning URL, the length of the actual email content is limited to around 1350 characters.

It’s a bummer that this limitation exists, but if you’re writing a longer email and you’d still like to avoid your inbox, I suggest launching a blank Gmail message (as mentioned above) and composing your message in the browswer or using the service with only the subject line selected and pasting in the body text manually [3].


Download: Send With Gmail service for OS X

The Code:

If you’d like to tweak the code or use it in another way, here it is.


import sys
import re
import subprocess
import urllib
from sys import stdin, stdout

tinput = stdin.read()

def subject_sel(s):
    line_list = re.split('\n', s)
    sub_final = line_list[0]
    return sub_final

def body_sel(b):
    line_list = re.split('\n', b)
    body_final = "\n".join(line_list[2:])
    return body_final

full_url = "open https://mail.google.com/mail/?view=cm&ui=1&fs=1&tf=1&su=" + urllib.quote(subject_sel(tinput)) + "&body=" + urllib.quote(body_sel(tinput))

process = subprocess.Popen(full_url.split(), stdout=subprocess.PIPE)
output = process.communicate()[0]

  1. You will need to be in a text field of some sort for the command to work. This can be in any location of any application that accepts text.  ↩

  2. It appears the full screen parameter is added automatically when creating an email with a prepopulated subject and body.  ↩

  3. Like an animal!  ↩

CMMA - A Panel Discussion on Stereography

Back in April of this year, I was asked to speak on a panel about Stereoscopic 3D production at the Communications Media Management Association's Spring Conference in Redmond, Washington.

The panel consisted of Adam Green from Avid Technology, Keith Vidger from Sony, Amir Stone from the Adobe AfterEffects development team, and myself.

The audience, as you can see from the live polls at the beginning of the video, was essentially brand new to the topic of S3D, so the discussion ranged from a basic introduction to stereo nomenclature and workflow, to on-set learnings and insight (primarily my focus).

I think it turned out pretty well, and now it's online, so check it out.

Experiments in iSight Scripting

A week or two ago, a conversation with my girlfriend reminded me of this old video from the Defcon 18 Conference, in which a hacker by the name of Zoz recounts the tale of how he located and recovered his recently-stolen computer by way of some fancy Internet skills. In addition to being a great reminder about data safety and security, it’s a pretty damn funny story.

Re-watching the video reminded me I’ve always wanted to experiment with scripting the iSight camera on my MacBook Pro. Not necessarily for the purpose of having photo evidence in the event of a theft, but more as a fun exercise in scripting and automation. Maybe I’m easily entertained (rhetorical), but I found the process and results throughly enjoyable.

Command Line Tools

The first thing I needed was a command line interface to the iSight camera. Despite my best Googling efforts, I wasn’t able to find any native OS tools to fire the camera (I’m still not sure if there is one). But lucky for me, nearly every search I did pointed me to a free, no-longer-supported-but-still-functional CLI tool called iSightCapture. Installation is as simple as tossing it into /usr/local/bin.

Regarding syntax, here’s the pertinent information from the iSightCapture readme file:

isightcapture [-v] [-d] [-n frame-no] [-w width] [-h height] [-t jpg|png|tiff|bmp] output-filename

-v output version information and exit
-d enable debugging messages. Off by default
-n capture nth-frame
-w output file pixel width. Defaults to 640 pixels.
-h output file pixel height. Defaults to 480 pixels.
-t output format - one of jpg, png, tiff or bmp. Defaults to JPEG.

$ ./isightcapture image.jpg
will output a 640x480 image in JPEG format

$ ./isightcapture -w 320 -h 240 -t png image.png
will output a scaled 320x240 image in PNG format


I wanted the ability to remotely trigger the iSight camera from my phone, and have it run for a predefined interval of time. To do this, I’d use a watch folder and a trigger file, uploaded from my phone, to initiate the script. This would theoretically be the method I’d use to “gather photographic evidence” in the event my laptop is stolen.

As usual, to set this up, I turned to my trusty friend Dropbox. To keep things tidy, I needed a couple of folders. The directory structure looks like this:

  • iSight_backup
    • scripts
    • trigger

The photos taken by the script will be placed in the top level directory, iSight_backup. The script itself would be placed in the scripts folder, and the trigger folder remains empty, awaiting a text file to be uploaded via Dropbox on my phone.

The Script

Here’s the script, called isbackup_t.bash, and saved into my iSight_backup/scripts/ folder:


#   path to iSightCapture CLI tool  

#   path to Dropbox folder to receive photos  

#   path to trigger file  

#   select photo filetype; jpg, png, tiff, or bmp  

#   number of photos to take  

#   interval between photos (seconds)  

for i in `seq 1 $PNUM`;  
        DTS=$(date -u +"%F--%H-%M-%S")  
        $APPP "$FPATH$DTS$XTN"  
        sleep $PINT  

rm $TPATH*  

The Details

Each photo gets a date and time stamp added to the file name for easy sorting. Since the FPATH destination is set to a folder within my Dropbox, and each file is a 640x480 jpeg, approximately 25kb in size, I can see the resulting photos on my phone just seconds after their taken.

By setting PNUM to 24, and PINT to 300, the script will take a photo every 5 minutes, for the next 2 hours, then stop until I upload another trigger file. However, since the script itself lives in Dropbox, I can change the interval or duration variables from my iOS text editor at any time.

Tying The Room Together

All that’s left to complete our little project is to create a launchd task to keep an eye on our trigger folder, and fire up the script if anything lands inside. Since creating, modifying, or using launchd tasks via any method other than a GUI is currently beyond me, I turned to Lingon.

Here’s the resulting launchd task:

<?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">
    <string>isbackup triggered</string>

And just like that, we’ve got a setup that will monitor our trigger folder, fire up our script when it sees anything inside, and save each file to our Dropbox.

Extra Credit

During my research for this project, I found a number of people using iSightCapture for things other than a makeshift security tool. Some, for example, used it to take a self portrait at login every day and auto-upload it to an online photo diary.

I thought that was a fun idea, so I wrote a second, shorter version of my script to automatically take a shot every 2 hours without the need for a trigger. For my version, however, I was most definitely not interested in auto-uploading the photos.

The script:


DTS=$(date -u +"%F--%H-%M-%S")


And the launchd task:

<?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">
    <string>IS Secuirty</string>

Since I typically use a multiple monitor setup when working, I almost never see the green light come on when the script runs and when I check the photo directory, usually the beginning of the next day, I’m treated to at least a couple hilarious images. Like these, for example:

Hi Merlin!

I may be asleep in this photo. I can't tell.

No, that's not my poster. My girlfriend got to decorate that side of the room.

Yes, It makes Skype calls awkward. Then again, so does that hair.


Despite the photos being almost inconsequentially small in file size, I really don’t need to be keeping a long-running historical record of my disheveled appearance. To keep things from getting unwieldy, I created a Hazel rule that deletes files older than 2 weeks. I see no reason I’d need to keep them any longer than that.


I don’t know if it’s because this little project was so different from my day to day work, or I thought it would be a genuinely useful security tool, or I’m a narcissist that loves seeing pictures of himself (again, rhetorical), but I had a blast playing around with this little project.

As with nearly everything on this blog, I learned some things, failed a few times, and came out the other side with a fun little script I can demo to people, making it absolutely certain they’ll never ask me anything about computers again.

Converting MultiMarkdown to HTML with TextExpander

If you’re here, reading this site, chances are pretty good that you use and love MultiMarkdown as much as I do. That, or you’re at least fairly curious and have a plenty of free time.

With more and more applications supporting Markdown natively, the need to convert the text to HTML is decreasing in frequency. However, the need isn’t completely gone. Sometimes you just need some good old fashioned HTML.

A Hammer For Every Season

(Or Some Other Metaphor That Actually Makes Sense)

There are almost as many ways to get your MultiMarkdown into HTML as there are applications that support Markdown.

I’ve created build systems for Sublime Text to convert MultiMarkdown documents to HTML files. I’ve got a build system that lets Marked do the heavy lifting for me. For the times I don’t need a full MultiMarkdown document, just a small snippet of text, I’ve got Brett Terpstra’s killer MultiMarkdown Service Tools.

It’s probably due to the myriad of tools at my disposal that I only recently discovered I’m unable to use Brett’s OS X Services in Sublime Text 2. I’ll admit, I didn’t try very hard, but after Control + Clicking, trying my keyboard shortcuts, and doing a bit of searching online, I quickly gave up and decided to build a tool I knew would work.

To TextExpander We Go!

When I need a system-wide tool that works in any application, activated by a few quick keys, the answer is almost always TextExpander. With its ability to act as an intermediary between text and scripts, TextExpander is the hammer that always gets the job done [1].

The snippet:

pbpaste | /usr/local/bin/mmd

Just like my other text processing scripts, proper use involves selecting the text to be processed, copying it to the clipboard, and invoking the snippet, which I’ve bound to the command ;mmd. Now, any time I need to convert MultiMarkdown text into HTML, without the hassle of saving files and opening specific applications, I’ve got a quick, universal keyboard command I can use. Bringing me one step closer to an application agnostic workflow.


  1. Yes, I’m sticking with the hammer metaphor. I’m in too deep to turn back now.  ↩

Running Scripts with TextExpander

I love that the Internet is full of smart people making and sharing awesome things. Like Dr. Drang and his Tidying Markdown Reference Links script. Seth Brown’s formd is another great tool I don’t know how I ever lived without. But, being the amateur that I am, I always struggle to figure out just how to use the scripts these amazing programmers have been kind enough to provide.

Lucky for me (and you), I’m able to play along with the help of everyone’s favorite writing tool, TextExpander. In the documentation for formd, Seth was gracious enough to spell it out for us laypersons[1].

To run formd with TextExpander, simply place the Markdown text to convert onto the clipboard and issue the appropriate TextExpander shortcut (I use fr or fi for referenced or inline, respectively).

It took longer than I’d like to admit, but eventually I realized this snippet could be tweaked to run any script I happen to download from a coder more skilled than myself. Additionally, since most of the scripts I want to use are built for processing text, the copy/paste activation generally works great.

pbpaste | python /Path/To/Your/Script/script.py

With this short snippet, I can copy my text to be processed, invoke the script snippet of my choosing, and have the results immediately pasted back into my text editor, email, or wherever.

This particular snippet assumes you’re running a python script, but you can just as easily swap python for ruby or perl. Or you can omit the python call if you’re just running a standard Bash command. As long as it’s a valid command that would run in the Terminal[2], you can automate it this way. And, just as with formd, to use the snippet, you simply Copy the text to be processed, and invoke the snippet.

Boom. Done. Life is grand.

While none of this is new or revolutionary, connecting the dots between TextExpander and the Terminal is something I wish I’d have discovered long ago and, therefore, may be of interest to you.

Of course none of this would be possible without the amazing minds that write the scripts in the first place. So, along with this post, I offer a sincere Thank You to Dr. Drang and his site And now it’s all this, as well as Seth Brown and his site Dr. Bunsen.

  1. Layfolk? Laypeople? Missing the point?  ↩

  2. And frankly, I just start trying things in the Terminal until I find the correct command.  ↩

Fountain for Sublime Text

Jonathan Poritsky has created a great Fountain package for Sublime Text. It supports almost everything outlined in the Fountain syntax guide but, most importantly, gives us syntax highlighting.

While not everyone likes the idea of using colors to highlight elements in their screenplay, I most definitely do. For me, syntax highlighting is equivalent to the red squiggly line underneath a misspelled word. At a glance, I can see if I've made any errors and, to a lesser degree, I can recognize patterns of highlighted elements to quickly understand where I am in the overall document.

Another reason I want syntax highlighting is to ease my recent transition to full-time use of Fountain for screenwriting writing projects, replacing my roll-your-own MultiMarkdown screenplay syntax.

The Part Where I Ruin Everything

Hands down, my favorite part of Jonathan's Fountain package is its ability to be customized, like all Sublime Text packages. The default package theme does a good job of emulating the look of a screenplay, using layout settings like 15pt black Courier on a white background and centering the text within the document window, etc.

While I enjoy reading screenplays in their correct format, I really dislike that layout during the writing process. I much prefer to look at white text on a black document. More specifically, I use the Sunburst theme in Sublime Text while writing in MultiMarkdown. Since Fountain is designed specifically to be platform and application agnostic, I'm free to be as picky as I want about my writing environment.

So, I tweaked the theme that came with the Fountain package. The biggest thing I wanted to add was background highlighting for Scene Headings. It helps me quickly scan the document to find the beginning of a given scene.

I made all Scene Headings, Action, Character, and Dialogue elements white(ish), and Parentheticals, Sections, Synopses a dimmer grey color to help them fade into the background a bit. The only elements that use colored text are Transitions, Notes, and the Title Page, which uses the same color scheme as MultiMarkdown metadata in the Sunburst theme.

In Fountain.sublime-settings I removed the additional line padding, changed the font to Monaco 11, turned on line numbering, and turned off "draw_centered". What I'm left with is a document that looks nothing like a screenplay, just the way I like it.

Personally, I don't want to feel like I'm writing a screenplay. Writing a screenplay is hard and stressful. Conversely, writing words into a text editor is something I can do all day long. Maybe some day I won't be so particular or need to psych myself out in order to write, but for now, this feels right to me and I'm sticking with it.

If for some reason you would like to use my theme, download this file and drop it into the Fountain folder in your Sublime Text package directory. Once you've done that, open up Fountain.sublime-settings and make yours match mine:

    "font_face": "Monaco",  
    // "font_face": "Courier Screenplay",  
    // "font_face": "Courier Final Draft",  
    "font_size": 11,  
    "color_scheme": "Packages/Fountain/Fountain Dan.tmTheme",  
    "word_wrap": true,  
    "wrap_width": 78,  
    // "line_padding_top": 5,  
    "draw_centered": false,  
    "spell_check": true,  
    "indent_subsequent_lines": false,  
    "trim_automatic_white_space": true,  
    "line_numbers": true,  
    "translate_tabs_to_spaces": true,  
    "auto_complete_commit_on_tab": true,  
    "auto_complete_with_fields": true