play audiobooks on crappy mp3 players

May 30th, 2007

Portable music players are to me a very welcome addition to our lives. A lot of time that was previously completely wasted can now be exploited. All the waiting is so much better, waiting for the bus, waiting at the post office, waiting to cross the street. Oh sure, we had portable players the last ~25 years, but the reason they've become so universal lately is how convenient it's become to use them. Yes, for something to be practical matters a great deal, there's hardly a better example.

And yes, mp3 players are great... for music. Just like pens are great for writing letters. But that's not all you can do with them. Hey, after all it's an audio player, not a music-only player. And hey, music is great when you're on the road. But when you're out there a long time, no matter how much music you have, it does get a little boring. So how do you pick up that slack? Why not try an audiobook.

I actually don't play much music on my player anymore, anytime I'm outdoors I use it for spoken audio. Unfortunately, portable players generally suck for this. It's as if noone thought of it, gee what if someone wanted to listen to something longer than 5 minutes?

Obviously, audiobooks tend to be longer than songs. Depending on how it's divided up into tracks, it's sometimes very inconvenient to play them. If you miss 30 seconds of a song, it doesn't really matter. But if you're listening to prose and you get interrupted, you want to seek back those 30 seconds to hear what you missed. For audiobooks, easy seeking in tracks is pretty important.

My old iRiver ifp series used to choke on tracks longer than about 30 minutes in length. It would play the track, and go past this limit, but the duration on the display was now out of sync with the audio. For these long tracks seeking was completely broken past this limit. Unless there's been a firmware upgrade in the last 6 months, this is still the case for everyone. Not only that, the seeking function was pretty much the weakest part of the interface, it was very impractical and very often I would accidentally skip to the next track instead of seeking forward (holding the button vs pressing). Incredibly annoying.

This seems to be the trend in general, seeking is a marginal thing, no one is making it easy to use on their portable player. Another inconvenience is that some players have displays so small that long artist/title/album names are a pain to check, it takes forever to scroll them.

So what to do? Well, you can hack around it. It's not an elegant solution, but it's a solution. Divide all these long tracks into short tracks, so your player won't choke on them, and so that you only go 5 minutes back if seeking isn't reliable.

tracksplit.rb will do just that. Run it in the directory where you have your longish tracks (it accepts mp3/ogg) and it will chop each one into pieces for you. It also renames them sequentially (so I assume you know what tracks you have), so the order in which they were alphabetically is preserved. The originals are deleted (after all, this is just a copy for your portable player, right?).

The actual heavy lifting is done with mp3splt, which cuts tracks into pieces without re-encoding. :cap:

#!/usr/bin/env ruby
#
# Author: Martin Matusiak <numerodix@gmail.com>
# Licensed under the GNU Public License, version 2.
#
# Note: this script uses mp3splt to split mp3/ogg files at a set length.


# set the length in minutes for each track, eg. 5.0 = 5 minutes
$track_length = 5.0


if ARGV[0].nil?
	$duration = $track_length
	puts "Track length not given, using standard track length of #{$track_length}"
else
	$duration = ARGV[0].to_f
end

if not system "which mp3splt &> /dev/null"
	puts "Erratum: mp3splt not found on system"
	exit 1
end

$pattern = "*.{mp3,ogg}"
files = Dir[$pattern]

if files.empty?
	puts "No files named \"#{$pattern}\" found, exiting"
	exit 0
end

w = (files.length / 10) + 1
files.each do |file| 
	i = files.index(file)
	newfile = "%0#{w}d_@n" % i
	cmd = "mp3splt -t #{$duration} -o \"#{newfile}\" \"#{file}\""
	puts cmd
	if system cmd
		File.delete(file)
	end
end

Ps. This happens to be my first adventure with ruby, so report breakage please ;)

:: random entries in this category ::