Converting 96kHz 24-bit FLAC to OGG with ffmpeg

Lately my son Robin asked for Peter Gabriel’s song The Tower That Ate People in a car. I like OGGs, although recently it may have been pointless with MP3 patents being expired. But 15+ years ago it was an obvious choice for me, especially because most encoded MP3 files had also clearly cut out high frequencies and generally lower quality at the same bitrate. Again – not a problem I encountered with newer MP3s. But I stayed true to OGG and I honestly don’t need anything better than its Q7 level.

The song is on Peter’s OVO album but the version Robin likes is from Back to Front show in London. So I browsed it, played it and – all the songs were skipped. Darn! I knew it must be because of the quality being very high because the digital download, companion to the Blu-ray Deluxe Book Edition (yeah, I’m a fan), was in 96kHz for both FLAC and OGG. So I had to recode the OGG, or better FLAC to OGG in normal sample rate (44.1kHz).

FFmpeg for the rescue!

I previously transcoded OGGs to MP3 for a little radio that didn’t support OGGs (I never understand why this happens) and I was very satisfied with FFmpeg because when I can do something from a command line I prefer that. So today I downloaded Windows build of FFmpeg and tried to figure out the switches.

After some Googling I tried -codec:a libvorbis and it told me there is no such a codec. So I tried ffmpeg -codecs to find out what (and if) there is any OGG support. There was just vorbis decoder, so I tried that one. Then ffmpeg told me that it’s just experimental and I must add -strict -2 switch to enable it. It worked afterwards but the warning was strange so I investigated further.

The trouble was that the build from FFmpeg site did not have libvorbis compiled in. Every time you run ffmpeg it prints the configuration it was compiled with and mine didn’t show –enable-libvorbis in the output. It was by an accident I found out I’ve got ffmpeg also on my PATH – which was strange considered I didn’t put the downloaded version there. It was part of ImageMagick which I was pretty sure was installed using Chocolatey (most recommended!), I don’t even remember why. But now it came handy, because, behold, this one had libvorbis with it!

If you have Chocolatey already, just cinst -y imagemagick and then start a new console to find ffmpeg on your path. Or do it the hard way.

Those damn spaces!

I use spaces in the filenames, replacing them with underscores or something does not make much sense, not in 21st century I believe. I respect bash (and prefer it in Windows as well, as delivered by Git) and I consider myself more or less a power-user (more less than more I guess). I understand that long time ago text was the thing and objects were not. But all this white-space escaping is sometimes killing me. Just look at all the effort that went into escaping white-spaces – IFS, quoting, print0, etc.

Actually, using NUL character (print0) as a separator seems most logical but obviously it’s difficult to put it into plain text then. But plain text is so awkward to represent anything anyway (except for the actual text). I believe some richer environment where lists are true lists is the logical thing to have. I’m not hinting on PowerShell necessarily, not sure they have it right, but they tried to be progressive for sure.

When I quote the name containing spaces on the input it’s a single argument (let’s say $1). But when I use ffmpeg -i “$1″… in the script the program complains that the first word from the filename is not a valid name. I encountered this problem many times before, passing the arguments from a command line to the script and there to other commands. Today I learned that “${1}” is different from “$1”. I always used curlies only to separate name of a variable from potentially colliding surrounding. But the first one keeps $1 as a single parameter even for another executable called from a script. Handy. Not intuitive. And definitely not something you learn in this section, for instance.

If this was all more “object-oriented” (broader meaning) it would be a filename, String or even File object from the start all the way to where it should be used. Spaces would not matter.

Sample rate and unexpected “video” stream

Because the source flac file had sampling rate of 96kHz – and I suspected this was the main reason the car audio system didn’t play it – I wanted to resample the audio to more traditional CD quality. That’s what option -ar 44100 does. Because OGG seems to have a single sample format, I didn’t have to care about bringing 24bits down to 16.

But I was surprised that my OGG didn’t play in foobar2000 and loading it actually created two entries in a playlist. I checked the output of a command more carefully and noticed it also converted some JPEG image embedded in that FLAC to a “video” stream. Not interested, thank you, said I – and that’s what -vn (no video) switch does.

And the script is…

Add setting the quality of the output OGG and -y to overwrite the output (I experimented repeatedly, you may not want it, of course) and you get a script like this:

#!/bin/sh

ffmpeg.exe -i "${1}" -ar 44100 -vn -codec:a libvorbis -qscale:a 7 -y "${1%flac}ogg"

It only encodes one file. Last thing I wanted is to treat input arguments for a for loop, although I guess I could have used shift too. Anyway, the command is easy:

find . -name \*.flac -exec ./anything-to-ogg-44k1-q7.sh {} \;

I guess it doesn’t care about the input format as long as it recognizes it, hence the “anything”. Of course, ffmpeg can do much more – I just wanted to show one recipe, that’s all.

Advertisements

Building Windows VirtualBox machines

I started this post in January originally, but after a couple of paragraphs I realized I’m writing a more generic post – Believe in build automation. Now you know why I believe in automation and we can get straight to it. I’m a Linux guy, I’d rather work with Linux, I always prefer UNIX/Linux on servers, but I run Windows desktop to be conformant. After all I can run anything in VirtualBox when I need it.

And sometimes what I need is just another Windows. But I don’t want to manually prepare the box all over again after it expires (evaluation), not to mention I want a repeatable process (because I believe in it :-)). You may snapshot your virtual machines, but you cannot avoid eventual end of evaluation period.

State of affairs in Windows automation

Couple of years ago I got a new computer with Windows and I wanted to put all my favourite tools on it. Of course I didn’t have a list. But I had a feeling I’m repeating myself. I also wanted to disable some Windows features. I had experimented with PowerShell before, so I turned to it with faith. I found out that there are some PowerShell modules that allow to add/remove features or applications, but they are limited only to Windows Server. Couple of ugly words ran through my head and I postponed my dream.

Now I know this was a hasty decision, because Microsoft does not offer just one good standard way how to do it. As explained here, you can use one of two PowerShell modules. ServerManager module was the one that made a bit angry because of its restrictions to server versions of Windows, but there is also Dism module available on any recent platform, not to mention dism.exe itself, that works for older Windows incarnations as well.

While this all is just a minor episode, it documents how difficult it may be to find the right way how to perform various tasks on the command line (and preferably PowerShell) for a newcomer. And I wasn’t even that new on Windows.

But after this it was easier and easier to use the right words and ask the right questions the right way to get my answers. Most of them were on StackOverflow, but I have to praise Microsoft’s sites too. Sure, sometimes you have to go over couple of Microsoft pages, but in overall you can find the answers.

Back to Windows virtual machine creation

Here you go, I nearly did it again! Wrote a different post than I wanted, that is. So back to the topic. Of course, you need to know your options for automation, so learning more about PowerShell and about ways how to (un)install various Windows features is still important. But we also need to know the general workflow how to bring Windows virtual machine to life. I decided to use Vagrant because it aims for developers and is praised by them.

When it comes to Windows there is one big trouble – because Windows is big. The same trouble exists for Linux too, but is smaller. We’re talking about automated installation. Good news is that both systems can be installed automatically. It comes as no surprise for Linux, but Windows also features so-called “unattended installation” which aims for corporate world where admins don’t want to sit through installations for all the computers in a big company.

It works in a simple way – you provide an XML file with this unattended configuration for the computer and Windows finds it during installation. It can be found on a floppy or USB drive.

I don’t know all the options how to install Windows in an automatic fashion, but this one is good for virtual machines. All you need to do is provide the booting virtual machine DVD with Windows ISO image and Autounattend.xml file on a virtual floppy disk.

Can Vagrant do it? Ok, now you got me. 🙂 Probably it can, but a brief investigation on the Internet revealed that instead of doing this installation with Vagrant I should first use Packer. And – what a surprise – both tools are developed by the very same company/guy (HashiCorp/Mitchell Hashimoto, sorry for leaving out any other participants from the company). I was not the only one confused about the differences between Vagrant and Packer.

Shortly (and maybe not 100% precise), Packer is good in creating virtual machine base images and Vagrant is good to use them in your development process. Base image is not installation ISO, it’s rather a snapshot of a virtual machine after installation with everything you want to have there for the start. Not with everything possible though, that’s why it’s called base image. Packer can build base images for various virtualization platforms, but we will focus on VirtualBox only.

My idol Matt Wrock

I decided to install the Windows somehow automatically using Vagrant and prefer PowerShell as much as possible. Searching for a solution I somehow found the post called In search of a light weight windows vagrant box by Matt Wrock. I read a bit of it but I was also intrigued by the link to the updated version using Packer and Boxstarter. Already by this time I was overflowed by new terms, but it was worth it, I promise!

Matt definitely knows his stuff, his Windows and automation experience is extensive and he can explain it properly as well. Just a day before that I wasn’t ready to add Packer to my arsenal, not to mention Boxstarter – and soon I learned about Chocolatey as well. Now, honestly, I still don’t get Boxstarter, so for me it’s just “some extension for PowerShell” (disregard at will), but I absolutely fell in love with Chocolatey, because with it the management of programs feels like on Linux.

Matt’s instructions how to use Packer and Boxstarter were pretty cool, he provides Packer files (configurations, or sort of recipes, for Packer, written in JSON format) for Windows Server 2012, Windows Nano (very interesting addition to Microsoft’s arsenal) and Windows 7 (here you need license key, as there is no evaluation ISO, shame). I definitely utilized Windows Server 2012R2, as the server edition always comes handy during development when you want to experiment with a domain controller, etc. But I also wanted packer template for Windows 10 – and I had to create the one myself.

Windows 10 experiments

Actually, the biggest problem with Windows 10 wasn’t the Packer template, but with the Autounattend.xml file. I found some generator, but it didn’t deliver without some errors. I’m still pretty sure that XML is far from flawless, it’s not cleaned up properly and so on – but it works. Diving into every detail in a field that is mostly new for me (the whole world of Windows automation) would probably stop me before I got to the result, so take it as it is, or make it better if you can.

I highly recommend to read that Matt’s article Creating windows base images using Packer and Boxstarter as it is a very good introduction into the whole pipeline. His packer templates also provided a great starting point for more experiments. I also liked the way how he minimized the images by removing many Windows components, defragging the disk, zeroing empty space, etc.

I summed up my experiments in a markdown file and looking at it, it definitely is not perfect and finished. But does it have to be? In a week I played with it I probably installed Windows 10 forty times. Most of these test I commented out the slow parts that were mere optimization steps mentioned above (minimizing the size of the image). I played a lot with some preinstalled software (using Chocolatey, of course) and tried to pre-configure it using registry changes where necessary. This is, however, in vain, as the sysprep.exe step wipes registry changes for vagrant user. Talking about vagrant user, be extra careful to spell it everywhere the same way. Once I messed it up, had vagrant in Autounattend.xml and Vagrant in postunattend.xml (which is used as C:\Windows\Panther\Unattend\unattend.xml by sysprep.exe) and had two Vagrant accounts – you don’t want that. 🙂

I tried hard to perform some installation and configuration steps after sysprep, I tried to change it from Packer’s shutdown_command to windows-restart provisioner step but I wasn’t able to overcome some errors. After a while I settled with a script I just copied to my Vagrant working environment directory and then ran it from initialized box where it appeared in c:\vagrant directory.

Sure I could do even better with full automation, but when things resist too much sometimes it’s good to step back, rethink the strategy and focus on quick wins.

Other options?

There are definitely more ways how to prepare Windows 10 box, or any Windows for that matter, with or without Packer, but even when we focus on Packer solutions there’s a wide spectrum of approaches. Some don’t bother to use sysprep.exe to generalize their installation – after all if it’s only for personal needs it really is not needed. People on GitHub seem to agree on using PowerShell as a Packer provider, but one of the solutions used no provider at all (all part of the build section). Also widen the search for other Windows versions and you’ll see much more variability.

Conclusion

Using Packer as a first step in the pipeline is very practical. You can prepare base image once and save a couple of hours any time you need a fresh environment (partially you can do the same with snapshots in VirtualBox, but it’s not the same).

I use Boxstarter in the process as recommended (although I’m not able to appreciate it fully) and Chocolatey to install/remove programs – during Packer steps and also anytime later. When my evaluation Windows runs out I simply refresh the packer image from ISO and I’m done for the next 90 or 180 days (depending on the OS version).

Following the installation enthusiasm I went on to install SQL Server 2014 Express from Chocolatey package, configure it using PowerShell bits and pieces found across many blogs and stackoverflow questions and wrote it down on GitHub. I actually got used to writing technical notes I may need later into these markdown files and it works very well for me. Now I have automation hiatus, but I’m sure I’ll get back to it and it’s good to find all the notes at hand, including unresolved problems and ideas.

Good luck with Windows automation!