[Fair warning: this was all done on an Ubuntu Linux system. It may work on other configurations, but YMMV]
Earlier this year, I bought myself a new phone, the Samsung Nexus S.
The Nexus S has the advantage of being what they call a “reference device”, that is, it’s one of the preferred devices used in the development of Android, which means that it is one of the first to be updated when new Android versions come out. It’s also light, thin, fast, and looks cool.
It has a downside, however — it doesn’t have a slot for an external memory card. The device itself comes with 16GB of internal memory, which should be enough for most needs, and in fact it is, except for one particular use-case: listening to music.
The problem is that I’d really like to be able to carry my complete music library with me at all times. While it’s true that a few GB worth of music should be more than enough for most occasions, I find that I’m too lazy to refresh the phone’s library regularly. Besides, if I find myself in the mood for a specific track, chances are, it won’t be preloaded on my device.
Even though I usually try to prune my music library of music I don’t really listen to anymore, over the years my library has grown to around 13GB in size. While that would still theoretically fit on my device, it wouldn’t leave much space left for other things, like offline maps, videos, and such.
Downsampling the Files
One solution to that problem is to simply “resample”, or “downsample” the MP3 files. That is, re-encode the file with lower quality settings, trading some of the sound quality for disk space.
There are many solutions for that on the Internet, but most depend on using LAME. The problem with those solutions is that LAME doesn’t preserve the metadata inside the MP3 file. Things like artist, album, song title and album cover (important for me, since it looks cool when playing in my car).
Enter GStreamer. Essentially GStreamer is a multimedia manager which combines various smaller tools to achieve it’s full functionality. Strangely, GStreamer seems to use LAME for it’s MP3 encoding, but somehow the output files preserve their metadata, including the album covers.
A few searches on the Internet led me to this page, where I learned the command line to convert a single file:
gst-launch filesrc location=input.mp3 ! decodebin2 ! audioconvert ! lamemp3enc target=bitrate cbr=true bitrate=128 ! id3v2mux ! filesink location=output.mp3
Converting the Entire Library
Obviously it’d be too boring to convert 13GB of MP3 files one-by-one. A few more searches led me to this page, which features a script that does exactly that, though that script was meant for converting FLAC files into the MP3 format.
No big deal, a few simple changes to the script, and it’s working perfectly with our GStreamer command:
#!/usr/bin/env bash # resamples all .mp3 files and saves them to the OUT directory. LAMEOPTS="-V0 --quiet" if [ "$#" -ne 2 ] then echo "usage: $0 MUSIC_DIR OUTPUT_DIR" exit 1 fi IN=$1 if [ ! -d "$IN" ] then echo "$IN is not a directory" exit 1 fi OUT=$2 if [ ! -d "$OUT" ] then mkdir "$OUT" fi # find all .mp3 and resample them find "$IN" -iname "*.mp3" | sort | while read mp3; do OF=`echo "$mp3" | sed s,"$IN","$OUT\/",g` dir=`dirname "$OF"` if [ ! -d "$dir" ] then mkdir -p "$dir" fi # resample the MP3 files, preserving ID3 tags echo "$mp3" gst-launch filesrc location="$mp3" ! \ decodebin2 ! audioconvert ! \ lamemp3enc target=bitrate cbr=true bitrate=128 ! \ id3v2mux ! filesink location="$OF" > /dev/null done
Past that script onto a text file named resample_mp3.sh and mark it executable (chmod +x resample_mp3.sh).
You might also want to drop it on your /usr/bin, so it’s easily accessible when you need it.
Now, on a terminal simply go to the parent directory of your music folder, and type the following command:
resample_mp3.sh Music AndroidMusic
The “AndroidMusic” folder will be automatically created, and your music library will be completely mirrored there with the resampled MP3 files.
Beware that the conversion is very CPU intensive and will take a long time. You should probably schedule it accordingly.
Once you have your full library converted, you’ll want to copy it to your mobile phone / MP3 player.
When it comes the time to refresh my music library, I’ve found it quicker and easier to use RSync for Android. It works over the network so I don’t have to worry about plugging in, and it only copies the files which have changed, saving me from the headache of copying the entire folder again and again.
As for sound quality, sure, you trade a bit of it for disk space, but in my view it’s worth it, particularly since I usually won’t be plugging my mobile phone into high-end sound gear. In the car, and using cheap headphones, I’ve never been able to tell the difference.
It took my laptop (Intel Core i5 @ 2.4GH) around 6 hours to complete the procedure. In the end, my ~13GB library was reduced to ~8.7GB.
Now I won’t have to pick which music I bring with me anymore — I’ll just bring all of it.
[Edit: Increased the quality in the script, since the original (9) was too low and resulted in terrible sounding MP3 files. I also removed some redundant information]
[Edit 2: Changed the quality setting from VBR to fixed bit rate, as the previous setting was confusing the Android media player which was reporting much longer song times than normal.
Also removed the check for duplicate files. The script now overwrites any files already in the output folder. Be careful.
Finally, the files are sorted before resampling. The output order makes more sense, and this way it's possible to have an idea of how far along the process is just by looking at the current workload.]