Run ffmpeg On a Folder of Videos

The Problem:

I had roughly fifty video files across four different folders that I wanted to extract the audio from. You can use ffmpeg to pull the audio out of a single video file, but I didn’t want to type in a slightly different ffmpeg command fifty times.

The Solution:

Write a Node.js script that loops over all the files in a directory and runs the correct ffmpeg command to attempt to extract the audio from each file. And, of course, spend more time writing the script than it would have taken to just manually run the command dozens of times.

You can grab the script from GitHub. It was a fun learning experience. When you run the ffmpeg command, you need to make sure that the file extension for the audio file matches the format that’s actually in the movie file. This is kind of a drag. It would be nice if ffmpeg was smart enough to extract whatever audio was in the video, in whatever format it was in. It’s entirely possible it is that smart, I’m just not smart enough to know how to make it do what I want. At any rate, my script allows you to pass in an argument to set what format the audio is in.

Oh, all you care about is the ffmpeg command that’ll pull the existing audio out of a video file? No problem: ffmpeg -i input-video.avi -vn -acodec copy output-audio.mp3

Rails 5 Installation Woes

I ran into issues installing Rails 5 today. It was blowing up trying to install the Nokogiri gem. The full error message is at the bottom of this post, if you’re curious (and for the benefit of SEO).

The fix was to install the Xcode Command Line tools. This, despite the fact that I have the latest version of Xcode installed. So after running:

$ xcode-select --install

I could run gem install rails without issue. Weird.

FWIW, I’m running OS X 10.11.5 and Ruby 2.3.1 installed via rbenv.

Full output of the errors thrown when trying to install Nokogiri:

$ gem install nokogiri
Building native extensions.  This could take a while...
ERROR:  Error installing nokogiri:
    ERROR: Failed to build gem native extension.

    current directory: /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/nokogiri-1.6.8/ext/nokogiri
/Users/erikhansen/.rbenv/versions/2.3.1/bin/ruby -r ./siteconf20160703-99836-186h6s0.rb extconf.rb
Using pkg-config version 1.1.7
checking if the C compiler accepts ... yes
checking if the C compiler accepts -Wno-error=unused-command-line-argument-hard-error-in-future... no
Building nokogiri using packaged libraries.
Using mini_portile version 2.1.0
checking for iconv.h... yes
checking for gzdopen() in -lz... yes
checking for iconv... yes
************************************************************************
IMPORTANT NOTICE:

Building Nokogiri with a packaged version of libxml2-2.9.4.

Team Nokogiri will keep on doing their best to provide security
updates in a timely manner, but if this is a concern for you and want
to use the system library instead; abort this installation process and
reinstall nokogiri as follows:

    gem install nokogiri -- --use-system-libraries
        [--with-xml2-config=/path/to/xml2-config]
        [--with-xslt-config=/path/to/xslt-config]

If you are using Bundler, tell it to use the option:

    bundle config build.nokogiri --use-system-libraries
    bundle install

Note, however, that nokogiri is not fully compatible with arbitrary
versions of libxml2 provided by OS/package vendors.
************************************************************************
Extracting libxml2-2.9.4.tar.gz into tmp/x86_64-apple-darwin15.5.0/ports/libxml2/2.9.4... OK
Running 'configure' for libxml2 2.9.4... OK
Running 'compile' for libxml2 2.9.4... ERROR, review '/Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/nokogiri-1.6.8/ext/nokogiri/tmp/x86_64-apple-darwin15.5.0/ports/libxml2/2.9.4/compile.log' to see what happened. Last lines are:
========================================================================
    unsigned short* in = (unsigned short*) inb;
                         ^~~~~~~~~~~~~~~~~~~~~
encoding.c:815:27: warning: cast from 'unsigned char *' to 'unsigned short *' increases required alignment from 1 to 2 [-Wcast-align]
    unsigned short* out = (unsigned short*) outb;
                          ^~~~~~~~~~~~~~~~~~~~~~
4 warnings generated.
  CC       error.lo
  CC       parserInternals.lo
  CC       parser.lo
  CC       tree.lo
  CC       hash.lo
  CC       list.lo
  CC       xmlIO.lo
xmlIO.c:1450:52: error: use of undeclared identifier 'LZMA_OK'
    ret =  (__libxml2_xzclose((xzFile) context) == LZMA_OK ) ? 0 : -1;
                                                   ^
1 error generated.
make[2]: *** [xmlIO.lo] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2
========================================================================
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/Users/erikhansen/.rbenv/versions/2.3.1/bin/$(RUBY_BASE_NAME)
    --help
    --clean
    --use-system-libraries
    --enable-static
    --disable-static
    --with-zlib-dir
    --without-zlib-dir
    --with-zlib-include
    --without-zlib-include=${zlib-dir}/include
    --with-zlib-lib
    --without-zlib-lib=${zlib-dir}/lib
    --enable-cross-build
    --disable-cross-build
/Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/mini_portile2-2.1.0/lib/mini_portile2/mini_portile.rb:366:in `block in execute': Failed to complete compile task (RuntimeError)
    from /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/mini_portile2-2.1.0/lib/mini_portile2/mini_portile.rb:337:in `chdir'
    from /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/mini_portile2-2.1.0/lib/mini_portile2/mini_portile.rb:337:in `execute'
    from /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/mini_portile2-2.1.0/lib/mini_portile2/mini_portile.rb:111:in `compile'
    from /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/mini_portile2-2.1.0/lib/mini_portile2/mini_portile.rb:150:in `cook'
    from extconf.rb:364:in `block (2 levels) in process_recipe'
    from extconf.rb:257:in `block in chdir_for_build'
    from extconf.rb:256:in `chdir'
    from extconf.rb:256:in `chdir_for_build'
    from extconf.rb:363:in `block in process_recipe'
    from extconf.rb:262:in `tap'
    from extconf.rb:262:in `process_recipe'
    from extconf.rb:555:in `<main>'

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/nokogiri-1.6.8/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/nokogiri-1.6.8 for inspection.
Results logged to /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/nokogiri-1.6.8/gem_make.out

Better LaunchBar Arrow Keys

launchbar-alternative-arrow-keys

I like the “Vim Mode” option in LaunchBar that allows you to use the H-J-K-L keys as arrows keys if you hold down CONTROL. But, on a MacBook keyboard at least, I still find it a little awkward to press the CONTROL key. It’s not the worst thing in the world, but I figured there’s a key I can remap to CONTROL using our good friend Karabiner. Here are the things I tried, from worst to best.

The Bad Ideas

First, I tried remapping my Hyper Key to CONTROL when LaunchBar is active. It’s much easier to reach over and hold down the CAPS LOCK key with my left pinky than it is to reach down for the CONTROL key with my left pinky. I used this for a day or two but got annoyed because I found that it was pretty common for me to want to use app launching shortcuts while LaunchBar was active. But if LaunchBar was active I couldn’t use HYPER-A to switch to iTerm or HYPER-E to switch to my editor.

So I realized that simply holding down the A key could be remapped to holding down CONTROL.

<item>
  <name>Hold A to Control in LaunchBar</name>
  <appendix>Tap to enter an A character</appendix>
  <identifier>private.a_control_launchbar</identifier>
  <only>LAUNCHBAR</only>
  <autogen>
    --KeyOverlaidModifier--
    KeyCode::A,
    KeyCode::CONTROL_L,
    KeyCode::A,
  </autogen>
</item>

That’s actually easier than reaching all the way over to the CAPS LOCK key with my pinky. The problem is that I found that if I was typing fast enough LaunchBar would lose keystrokes. For example, if I typed “kar” to launch Karabiner, the only thing that would get entered into LaunchBar was a single K.

The Good Idea

How about if I have to hold down two characters at once to simulate CONTROL? Sounds great! If I hold down D and F together, that will act like I’m holding down CONTROL:

<item>
  <name>D+F together to Control in LaunchBar</name>
  <identifier>private.df_together_to_control_launchbar</identifier>
  <only>LAUNCHBAR</only>
  <autogen>
    __SimultaneousKeyPresses__
    @begin
    KeyCode::D, KeyCode::F,
    @end

    @begin
    KeyCode::CONTROL_L | ModifierFlag::NONE,
    @end
  </autogen>
</item>

This seems to work great. I can’t find a problem with it. But there’s an even better way.

The Best Solution

There’s a built-in Karabiner option called Simultaneous Vi Mode.

karabiner-vi-mode

When you turn it on, you can hold down S and D together so that you can use the H-J-K-L keys as arrows keys anywhere in the system. Brilliant. I’ve had this turned on for a few minutes and have already found it useful.1 I also like that with this option, Karabiner pops up a little notification-style HUD in the bottom-right corner of the screen to let you know that this mode is active.

Karabiner HUD
Karabiner HUD


  1. I did notice that very rarely I’d type an “s” and “d” fast enough that Karabiner would turn on Vi Mode and my keystrokes didn’t register. To fix this I adjusted the Simultaneous Key Presses > Delay Threshold of Key in the Parameters tab. Its default value is 50ms. Turning it down to 40ms seems to prevent the accidental triggering. 

iTerm2 v3 and LaunchBar

If you are running the iTerm2 v3 beta and have iTerm set as your preferred terminal application in LaunchBar’s preferences, you may have noticed that LaunchBar’s terminal commands will not work. For example, selecting a path in LaunchBar and then choosing the Open Terminal Here command (or simply hitting ⌘T), fails silently. Read more here or check out this Twitter conversation.

I came up with two different ways to deal with this.

First, here are two LaunchBar actions you can install. One is used to open a path in a new iTerm tab and the other is to open a path in a new iTerm window.

Second, if you really want LaunchBar’s ⌘T shortcut to open the selected directory in iTerm2 v3, I put together a hack that will do just that. Getting that all set up is more involved than just installing a LaunchBar action but it’s not that bad.

The LaunchBar team has known about this issue for some time now. I suspect that they haven’t changed things on their end because iTerm2 v3 has been in beta. Looks like iTerm2 v3 will be “official” very soon and when that happens, I suspect that LaunchBar with be updated. At that point, these actions and hacks won’t be needed. Until then, they should fill the gap for you well enough.

Karabiner + LaunchBar

I’ve been digging into Karabiner over the past couple of days. It’s been bending my mind a little bit. One thing I wanted to do was assign a key-for-key remap, but only when LaunchBar has focus. This was problematic because LAUNCHBAR never became the active app as far as Karabiner was concerned.1 So any <item> that you create that contains <only>LAUNCHBAR</only> will never fire because Karabiner never knows that LaunchBar is active. Then I stumbled across the built-in options for LaunchBar in Karabiner’s Change Key pane. If you check the Open LaunchBar by command-space option, Karabiner will recognize when LaunchBar is active so you can write remaps that work only with LaunchBar.2 Sweet. That’s exactly what I’m looking for.3 The trick seems to be explicitly opening LaunchBar with KeyCode::VK_OPEN_URL_APP_Launchbar.

karabiner-launchbar

As an added note, there’s a built in rule you can turn on that’ll remap hitting F and J together to invoke LaunchBar. Or, more specifically, it just remaps a simultaneous press of the F and J keys to ⌘-SPACE. But this will invoke LaunchBar without Karabiner knowing that it’s active. So here’s a rule you can add to your custom.xml that’ll activate LaunchBar and work with Karabiner remaps that target LaunchBar.

<item>
  <name>Press F+J Together to Invoke LaunchBar</name>
  <appendix>Invoke LaunchBar and make it the active app</appendix>
  <appendix>so that Karabiner remaps that target LB work</appendix>
  <identifier>private.f_j_together_to_launchbar</identifier>
  <autogen>
    __SimultaneousKeyPresses__
    KeyCode::F, KeyCode::J,

    KeyCode::SPACE, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_COMMAND | ModifierFlag::NONE,
    Option::KEYTOKEY_AFTER_KEYUP,
    KeyCode::VK_OPEN_URL_APP_Launchbar,
  </autogen>
</item>

  1. You can observe this by opening the Karabiner EventViewer from the menubar item and switching to the App tab. 
  2. By the way, choosing the option to map the semicolon key to return when LaunchBar is active might be something that I can really get used to. 
  3. Okay, maybe this isn’t exactly what I want. I’ve noticed that with this option enabled, it takes an extra tap of the space bar to activate LaunchBar’s app switcher. Normally, you could invoke LaunchBar, hit space, and you’d be at the previously used app. It’s pretty quick. But now you need to invoke LaunchBar and hit the space bar TWO times to get back to the previous app. Kind of a pain in the ass, but it’s really one of my own creation since I’ve temporarily disabled the built-in ⌘-Tab app switcher

Disabling Command-Tab on Mac OS X

I’m trying an experiment. I’ve disabled ⌘-Tab on my computer. I wanted to try using LaunchBar’s app switcher in place of it, but there’s no way that I can override nearly twenty-five years worth of muscle memory1 without a little brute force. Karabiner to the rescue. Here is my entry in custom.xml to make it happen:

<item>
  <name>Disable Command-Tab</name>
  <identifier>private.disable_command_tab</identifier>
  <autogen>
    --KeyToKey--
    KeyCode::TAB, VK_COMMAND | ModifierFlag::NONE,
    KeyCode::VK_NONE
  </autogen>
  <autogen>
    --KeyToKey--
    KeyCode::TAB, VK_COMMAND | VK_SHIFT | ModifierFlag::NONE,
    KeyCode::VK_NONE
  </autogen>
</item>

If you wanted to remap ⌘-Tab to actually do something, such as Escape, this would do the job:

<item>
  <name>Remap Command-Tab to Escape</name>
  <identifier>private.command_tab_to_escape</identifier>
  <autogen>
    --KeyToKey--
    KeyCode::TAB, VK_COMMAND | ModifierFlag::NONE,
    KeyCode::ESCAPE
  </autogen>
</item>

I’m not sure if this will stick. Giving up ⌘-Tab in favor of the LaunchBar way, I mean. ⌘-Tab and ⌘-Space are probably the two key-combos I hit more than any on my computer. Day in and day out I’m living in LaunchBar and switching between apps. I figure if I can just use ⌘-Space for both things, it will eventually be a net win. Also, in the few minutes I’ve had this set up, I can already feel things happening to my brain. ⌘-Tab is something I trigger without thinking. And I truly mean that it can be mindless in the worst way. Sometimes it makes me feel like a rat in a cage, hitting the lever to get a drug hit.2 The fact that my old ⌘-Tab habit no longer has any effect is making me act in a more mindful manner. Before I leave the current app to move to a new app, I have to think for a split second about where I want to go and what I want to do. It’s a subtle change that makes me feel more focused. The downside is that occasionally it adds friction that wasn’t there before.


  1. I started using Alt-Tab way back with Windows 3.1 in the early/mid 1990’s! 😱 
  2. But I don’t blame the poor rats for getting addicted to drugs while they were forced to live alone in miserable conditions. 

Open Tweet in TweetBot 1.0.1

I updated my Open Tweet in Tweetbot action for LaunchBar. You can download it from GitHub.

The previous version didn’t work properly if you triggered it and TweetBot for Mac wasn’t already running. Now that I’m using Marco Arment’s Quitter and TweetBot is being killed all the time, I was running into this bug a lot. The new update to the action fixes it.

Nerdy Details

Making this fix required doing a check to see if TweetBot was already running and, if not, to launch the app. I wrote the original script in JavaScript. As far as I can tell, there isn’t a way to use JavaScript to see if an app is running or not. But you can do that with AppleScript. And you can call out to an AppleScript from JavaScript. Here is the AppleScript that I’m using:

if application "Tweetbot" is not running then
    tell application "Tweetbot" to launch
    return false
else
    return true
end if

And here’s a line in the action’s main script that calls out to it:

var tweetbotIsOpen = LaunchBar.executeAppleScriptFile("open-tweetbot.scpt")

So the JavaScript calls out to the AppleScript which will launch TweetBot if it’s not already running. That AppleScript will also tell the caller if TweetBot was already running or not. In this case, I store the result of that call in the tweetIsOpen var. If you look at the full code, you’ll see that I’m not actually doing anything with the tweetIsOpen var. The reason for this is that I thought I might have to wait a second after opening TweetBot before sending it a URL to open. Turns out that isn’t necessary. 👍

Making Animated GIFs of Code

This is my process for creating animated GIFs of coding examples, like the one below. It’s changed over time and is my assimilation of posts from InVision and Wes Bos on the subject. You should read those. Wes made a nice video where he walks through his process. Know up front that I’m focusing on quality first, minimizing file size second, and workflow speed last. I’m also use ScreenFlow and the Gifify NPM module. Gifify might take a little time to get up and running, but the list of requirements is clear.1

operator-mono-powerline

Capture

I capture and edit in ScreenFlow. The editing is important. This is where you can remove typos and “dead air,” speed things up or slow things down, and generally get your clip polished to your taste. Previously I did this in Photoshop’s animation palette, which, in hindsight, was just plain insanity. Learn from my mistakes and use ScreenFlow’s editing tools.

Export

screenflow-export-losslessUsing ScreenFlow, I export as Lossless. Yes, lossless. This is key as it gives you the highest quality video to convert to an animated GIF. Exporting to some kind of compressed video format will introduce artifacts that can not only make your final GIF look worse, they could make the final file size larger. Going lossless also gives you a huge file: 158MB for 19 seconds of video! Final note: I export the recording of my Retina screen at 1× rather than scaling it down to 0.5× so that I end up with the nicest looking GIF possible. Converting beautiful, high-res text to nasty, low-res text makes me sad.

Conversion

Finally, use gifify to convert the MOV to a GIF. These are the settings I used:

$ gifify --colors 255 --compress 0 --fps 30 -o operator-mono-powerline.gif operator-mono-powerline.mov

Max colors. No compression. High frame rate.

Are those settings a little aggressive? Nope. The final product is a whopping 70KB. Surely I could squash that down some more, but this resulted in a final product that’s big and beautiful and certainly lightweight enough, IMHO2.


  1. I’m assuming you’re comfortable with the command line since you’re reading about how to make an animated GIF of code. If you don’t know what Homebrew or NPM are, this might not be the workflow for you. 
  2. The conversion did take a while on a 2013 quad-core MacBook. Maybe a minute. Long enough that I was concerned that something was wrong. It just took some horsepower to squash 158MB of video down to a 70KB GIF and, frankly, Gifify doesn’t do a good job of using all available CPU cores. 

Quick Tip: Operator Mono and Powerline

Love Operator Mono for coding but also love having a Powerline font for your terminal work? Did you know that you can have both? At least you can with iTerm. Here are the settings I use to do just that:

iterm2-font-settings

The trick is enabling the Use a different font for non-ASCII text option and then choosing a Powerline-compatible font. You’ll also have to strike a balance between the font sizes for Operator Mono and your Powerline font to make everything look nice. Getting the Powerline arrow characters to vertically align properly is the key issue here. The result of the settings I’m using can be seen below.

operator-mono-powerline-solarized-dark-eph

LaunchBar Action Development Tip

folder-in-actions-folderAfter writing my first custom LaunchBar action the other day, I’ve been pondering the best way to work on LaunchBar actions in the future. The biggest problem was that if you simply have your .lbaction sitting in the ~/Library/Application Support/LaunchBar/Actions/ folder, you can’t keep that action in a GitHub-friendly repo. Turns out that the solution to that problem is dead simple.

You can put folders inside of the LaunchBar/Actions/ folder and LaunchBar will find the .lbactions in those folders, too.

Problem solved! Never mind that I didn’t discover this until after I wrote a Node.js script that keeps two (or more) folders on your computer in sync in real-time. Sigh. It’s a long story.