2008-06-16

My M4A2MP3 script

I have a Sandisk Sansa MP3 player that I picked up on Woot.com for a song. It's a refurbished unit that has a couple little quirks, but for the most part, I love it. My primary praise for the thing is how easy it is to transfer files to. It identifies itself as a simple mass storage device, so all I have to do is drag and drop my music files to it. And I'm done. Contrast this with the iPod my mother got for Christmas, who after hours of frustration had to call her sister's son-in-law over for help in installing the iTunes software (which has been known to install other software behind your back; but we won't get into that here). Yes, the Sansa can be used in an alternate mode that does an auto-sync thing with Windows Media Player, but I chose not to go with that more confusing route. The Sansa does have a converter that you must use in order to do video, but when it comes down to it, I just don't find video on a 2" screen worth the hassle anyway.

One thing I do wish it had was a bookmarking function, as I like to listen to audiobooks; and if you lose your place in a 40-hour audio file, trying to find it again is frustrating. But since I've taken to using Goldwave to splitting my audiobooks into 1-hour files before transfer (and since playlists are in a standard, text-based format and very easy to create to "bind" the parts together), it's much less of an issue.

Anyway, the purpose of this post isn't so much to praise the Sansa, but to describe one workaround for a common trend. I've noticed a start of a shift from MP3s to M4As in audio, especially in podcasts. Xbox Live's Major Nelson did it for one episode (although he went back to MP3s afterward), and only the first GeezerGamers.com podcast was available in MP3. The Sansa, unfortunately, does not natively support M4A, just MP3 and WMA. Since I'm not yet ready to install Rockbox on it, I had to find another way.

I did some searching on converting M4A to MP3, and I found a pretty simple script here that does the conversion. It does, however, presuppose install paths for your programs (it launches two command-line utilities, FAAD and LAME, to convert to WAV and MP3, respectively). I decided I wanted to put it in a folder on my Sansa (since it's just a USB storage device, it can hold anything) and make it available no matter how it was assigned when it got plugged into a machine.

I have a folder, called M4A2MP3, that contains faad.exe, lame.exe, lame_enc.dll, and m4a2mp3.bat. The contents of the batch file are as follows:

echo off
REM Simple script to convert m4a to mp3, got it from http://pieter.wigleven.com/it/archives/3
REM With edits by Yakko Warner, http://yakkowarner.blogspot.com/2008/06/my-m4a2mp3-script.html
if /I "%~x1" NEQ ".m4a" (
    echo Warning, file doesn't look like an m4a: %~nx1
    pause
)
cls
echo.
echo Converting %1 to MP3
"%~dp0\faad.exe" -o "%TEMP%\%~nx1.wav" %1
"%~dp0\lame.exe" --preset standard "%TEMP%\%~nx1.wav" "%~dpn1.mp3"
del "%TEMP%\%~nx1.wav"

Being a simple script, it does require you have enough space wherever %TEMP% lives, but it does have several advantages over the original script. It uses %TEMP% as the location of the .wav file, which is typically faster, local storage; it replaces the .m4a extension with .mp3 instead of appending it; it allows the executables and script to travel together in a single folder; and no paths are hard-coded. It also, if you give it a file that doesn't have an .m4a extension, alerts you of this fact and presents you an opportunity to ^C and cancel the script.

To execute, it's as easy as dragging an .m4a file onto the batch file and watching it work. Note that it is possible to install this to your hard drive and add to Explorer's right-click menu for M4A files to run this script. I've set that up once, but considering how infrequently I have to convert M4As in general (usually just once a week), it hasn't quite been worth doing that on a regular basis.

4 comments:

Pieter said...

Nice to see you improved my simple batch file, it's way better like this!
Ill update my blog and link to your page so visitors can find the improved version!

Cheers!
-- Pieter

Brian said...

Thanks for posting this script. This doesn't appear to transfer the tag info. Have you found any options for this?

Yakko Warner said...

The script just automates two separate tools: FAAD, that converts the M4A to generic uncompressed WAV; and LAME, that encodes the WAV to MP3. Since WAV doesn't support tag information (as far as I know; in any case, the tools don't have any support for embedding tags in a WAV), that information is lost in that intermediate step.

I did find a utility here that can copy tags from one file to another, but unfortunately it doesn't support M4As. And then I found a forum thread here about a tool that deals with M4A tags. And then I had to go back to work. ;)

It would seem like it shouldn't take much to combine the two programs into something that could read and write both MP3s and M4As. If I come across something where someone's done that, I'll add it to this script. Unless I manage to get my hands on a C++ compiler and some free time...

Alexey said...

Greetings,

I needed this for use in a C#/.NET program, and ended up writing a wrapper. The code (for anyone who finds this) is as follows:

public static void Convert(string fromPath, string toPath)
{
int lastIndex = fromPath.Contains("\\") ? fromPath.Substring(fromPath.LastIndexOf('\\') + 1) : 0;
string tempFileName = Environment.CurrentDirectory + "\\temp\\" + fromPath.Substring(lastIndex);

if(File.Exists(tempFileName))
{
File.Delete(tempFileName);
}
if(!Directory.GetParent(tempFileName).Exists)
{
Directory.GetParent(tempFileName).Create();
}

Interaction.Shell(String.Format("faad.exe -o {0} {1}",
InQuotes(tempFileName),
InQuotes(fromPath)),
AppWinStyle.Hide, true, -1);
Interaction.Shell(String.Format("lame.exe --preset standard {0} {1}",
InQuotes(tempFileName),
InQuotes(toPath)),
AppWinStyle.Hide, true, -1);

File.Delete(tempFileName);
}

private static string InQuotes(string withoutQuotes)
{
return "\"" + withoutQuotes + "\"";
}