Using HandBrake on a list of files
I download a lot of videos on the web, and most of the time, they don’t come wrapped up as an iTunes-friendly m4v file. Even when they do, they may not necessarily be encoded in a way that plays nicely with all of my iOS devices (AppleTV, iPhone, iPad, etc.). So, for a long time, my download process has gone like this before loading into iTunes:
- Download
- Transcode
- Tag
The tools I use for the first and third steps have not changed for a long time, but there has been a lot of movement in the Mac video transcoding space. What do I mean by transcoding? I take video that arrives in a particular format (let’s say Ogg Theora) and convert it into a format my devices accept (typically some flavor of MPEG-4 my Apple devices).

For years, I used an awesome tool named VisualHub, and it did everything I wanted. I dragged in a list of files, told it which device I wanted to play them on, and let it rip. It even made use of OS X’s Xgrid infrastructure to encode multiple files simultaneously, distributed among my Mac Pro’s 8 cores, as well as any other networked machines I cared to use. But VisualHub died (so to speak).
It was reborn as an open source project named (poorly, in my opinion) FilmRedux. I tried using it, and found it lacking in various regards. Another project forked the code base and went in its own direction, calling itself VideoMonkey. I used it for a while, dealing with its superficial bugs and slow rate of development, simply because I couldn’t find another tool that would (usually) work the way I desired.
Of course, this all applies to lists of files. If I had a single file to transcode, I used HandBrake as soon as it began accepting arbitrary files for input (it originated as a tool for ripping DVDs, for which it still excels). I love HandBrake, and would use it for all my transcoding needs, if only I could use it for a list of files. The interface has been written with ripping DVDs in mind, however, and so you can only select one file at a time. So I set out to fix that, with my tool of choice: automation!
The Solution
I wanted a way to give HandBrake a list of files, and have it transcode all of them to a particular folder, using a particular settings preset. I realized this seems to be an idea ready-made for an OS X Service, and luckily, Automator (bundled with the OS) allows you to easily make Services. But, HandBrake doesn’t support AppleScript and doesn’t export any Automator Actions, so I needed to figure out another way to automate it. Luckily, HandBrake provides a CLI (command line interface) executable for the Mac.
First, you need to install the Satimage AppleScript extension. Follow the link, download the Satimage___.pkg installer, and run it. If you’re on Mountain Lion (with default Gatekeeper settings), you will need to right-click the file and click Open1, since it hasn’t been signed by the developer, but other than that, it works 100% in Mountain Lion. The installer is very basic, only copying the Satimage.osax extension into your /Library/ScriptingAdditions/ folder.
To create your own service, follow these steps:
Launch
Automator.appClick File > New (
Cmd+N)Select Service

Click the Choose button
Set the following two dropdowns at the top of the service’s definition: Service receives selected
files or foldersinFinder
Drag in the Action named Run AppleScript (you can search to find it quickly)

Copy and paste the script below as the script’s text
Click the Compile button to make sure the AppleScript pasted is valid

Click File > Save (
Cmd+S), and enter a name (I chose “Encode With HandBrake”), which will show up in the Services menu
on run {input, parameters}
set handbrakeCli to "/Applications/HandBrakeCLI"
set defaultPreset to 7
-- Make sure HandBrakeCLI is installed
set handbrakeInstalled to false
tell application "Finder" to if exists handbrakeCli as POSIX file then set handbrakeInstalled to true
if not handbrakeInstalled then
display alert "Install HandBrake CLI" message "Please install HandBrakeCLI into the /Applications directory
The HandBrake CLI can be downloaded at http://handbrake.fr/downloads2.php" as critical
return
end if
set the destination to POSIX path of (choose folder with prompt "Select the conversion destination")
set the presetList to do shell script handbrakeCli & " -z"
set eachPreset to every paragraph of presetList
set groupEx to re_compile "<[ ]*(.+)"
set presetEx to re_compile "[ ]*\\+[ ]*([^:]*):"
set displayNames to {}
set presetNames to {}
set group to ""
repeat with preset in eachPreset
if length of preset > 0 then
if preset starts with "<" then
-- Pull out the group's name
set group to find text groupEx in preset using "\\1" with regexp and string result
else if preset contains "+" then
set presetName to find text presetEx in preset using "\\1" with regexp and string result
copy presetName to end of presetNames
copy group & " > " & presetName to end of displayNames
end if
end if
end repeat
set chosenDisplayPreset to choose from list displayNames with title "HandBrake preset" with prompt "Choose a HandBrake preset" default items {item defaultPreset of displayNames}
if chosenDisplayPreset = false then
return
end if
set chosenDisplayPreset to chosenDisplayPreset as text
set presetIndex to 1
repeat with i from 1 to (count of items in displayNames)
if item i of displayNames is equal to chosenDisplayPreset then
set presetIndex to i
exit repeat
end if
end repeat
set chosenPreset to item presetIndex of presetNames
repeat with inputFile in input
-- Get original file's name
set thePath to POSIX path of inputFile
set prevTIDs to AppleScript's text item delimiters
set AppleScript's text item delimiters to "/"
-- Get the file name
set inputFileName to (item -1 of (every text item of thePath)) as text
-- Get the file name without an extension
set AppleScript's text item delimiters to "."
set inputFileNoExtension to items 1 through -2 of (every text item of inputFileName)
set AppleScript's text item delimiters to prevTIDs
-- Put back together if file name included periods
set outputFileName to ""
repeat with fileNamePart in inputFileNoExtension
set outputFileName to outputFileName & fileNamePart & "."
end repeat
-- Put on the preferred extension
set outputFileName to outputFileName & "m4v"
set handbrakeCommand to "nice " & handbrakeCli & " -i " & quoted form of (POSIX path of inputFile) & " -o " & quoted form of (destination & outputFileName) & " --preset='" & chosenPreset & "'"
--return handbrakeCommand
do shell script handbrakeCommand
end repeat
return input
end run
To use the service:
- Select the files you wish to convert in Finder
- Right click (or Control-click) on the selection
- Click Services > Encode With HandBrake (or whatever you named your Service in Step 10 above)
- The Service will prompt you for an output folder for the conversion. Select the folder you want your converted files to land in
- The Service will also prompt you for a HandBrake preset to encode with2. Select the one you wish to use. Unfortunately, the CLI doesn’t support custom presets defined in the GUI app
- A spinning gear icon will show up on the Menu Bar at the top of your screen until the job finishes
This script has worked solidly for me for a long time, and I hope you enjoy it. As always, you can let me know if you have any problems or feature requests.
Update
I’ve gotten feedback that the re_compile command is not working for some (all?) of you. D’oh! I forgot to mention you need to install the Satimage.osax AppleScript extension. I’ve had it for a while and forgot that this script uses Regular Expressions. I’ve updated the post to include those instructions.
-
This is described on the Gatekeeper support page, under the “How to open an app from a unidentified developer and exempt it from Gatekeeper” heading ↩
-
I have it defaulting to the Apple > AppleTV 2 preset, which you can change in the following line of AppleScript:
set defaultPreset to 7↩





