Audio Linkbloggingby Jon Udell
In my first column on this topic, I showed how little-known features of the HTTP protocol, the MP3 file format, and certain media players conspire to enable random access to MP3 files hosted on standard web servers. And I described a rudimentary service that combines these features to enable you to quote from a web-hosted MP3 file by forming a URL that includes its web address, its duration, and the desired start and stop times.
Back then, in September 2004, podcasting was just starting to take off, and in fact the term "podcast" appears nowhere in that article. Today, in July 2005, the recent addition of podcatching support to iTunes is exposing millions of people to an explosion of new audio content, much of it in spoken-word form and open to fair use.
Over the same period of time, we've seen a surge of interest in social bookmarking services such as del.icio.us. I've been using it for all kinds of things, but what's relevant here is the tag del.icio.us/judell/soundbite, where I've been collecting interesting quotes from shows appearing (mostly) on ITConversations. The RSS feed for that tag, del.icio.us/rss/judell/soundbite, is, in effect, an audio linkblog, albeit one that's a hybrid of a textual wrapper with pointers to audio segments. But it is also implicitly a podcast, and I decided to make it one explicitly.
While I was at it, I decided to clean up the syntax used by the original version of my MP3 clipping service, which used this awkward pattern:
There were two nasty bits here. First, splitting the URL into site and path components was awkward. Second, you had get your player to tell you the duration of the file and plug that into the URL as well--even more awkward. So here's the new pattern:
To get rid of the duration parameter, I needed a way to find the duration of a remote MP3 file from a small sample of that file. I used a Python module called MP3Info for this purpose. It was last seen at http://shell.lab49.com/~vivake/python/MP3Info.py, but the site seems to have gone dark, so I wound up using the copy in Google's cache.
For future archaeologists, I made two slight modifications that are both evident in this diff:
< if ( self.version == 1 ): < fudgeFactor = 1 < else: < fudgeFactor = 2 < < self.length = int(round(( self.content_length / self.framelength) * < (self.samplesperframe / self.samplerate))) / fudgeFactor --- > self.length = int(round((self.filesize / self.framelength) * > (self.samplesperframe / self.samplerate)))
Pages: 1, 2