Tuesday, August 19, 2008

Comments 24 comments

Read ID3 tags with JavaScript

A small JavaScript library capable of reading ID3 (v1) tags from MP3 files.

I figured I'd try to put the binary Ajax code to some other use than the EXIF data library, and a simple project seemed to be the ID3 tags used to store artist, title, etc. in MP3's. For now, it's only capable of reading (the rather lacking) ID3v1 tags since these are very simple compared to the more fleshed out and robust ID3v2 tags. Maybe I'll try to add support for the v2 tags later.

The script tries to only requesting partial data by using the Range request header if ranges are supported. This means we only have to download the actual tag data but also that we have to make a HEAD request first to get the file size and to ensure ranges are actually supported.

It's rather simple to use:

Two JS files are needed:
<script type="text/javascript" src="../binaryajax/binaryajax.js" ></script>
<script type="text/javascript" src="id3.js" ></script>

And a bit of JavaScript:
// URL of the mp3 file (must be on the same domain!)
var file = "mymusicfile.mp3";

// define your own callback function
function mycallback() {
 // either call the ID3.getAllTags([file]) function which returns an object holding all the tags
 alert(
  "All tags in this file: " + ID3.getAllTags(file).toSource()
 );

 // or call ID3.getTag([file], [tag]) to get a specific tag
 alert(
  "Title: " + ID3.getTag(file, "title") + " by artist: " + ID3.getTag(file, "artist")
 );
}

ID3.loadTags(file, mycallback);


Tags available are: artist, title, album, year, album, comment, genre

As with the EXIF reader, it does not work with Opera since I still haven't found a way to access binary data with that browser.

Check out a demo here: http://www.nihilogic.dk/labs/id3/

Download the source code here: id3.zip [3.17 KB]

24 comments:

Nice work, Jacob.

Pity about Opera though. I bumped into the same can't-read-binary-data issue when i was writing my SCUMM interpreter. The only solution was to decompose the file into a JavaScript array of bytes. Annoying to say the least. :(

Songbird implements things like that too in it's JavaScript API.

Hi Jacob,

I think you will have your share of luck with Opera just because Opera is pushing towards web 3.0 This means that they filed a proposal for browser content to access file system data this means also binary data.

I don't think you do need to download the whole file. Don't ID3v1 tags always start a set amount of bytes in to the end of the file? Can't we do a HEAD request on the file to get it's size, then a 'Range' request to download just the ID3 part of it?

If my understanding of ID3v1 is up to scratch, we shouldn't really have to download more than a couple kilobytes per file.

It might even be possible to do a 'Range' request with a negative number

@blueberry: You're absolutely right and I should look into that.

@james, johnny: Yea, hopefully there will be some way to get binary data in Opera in the future.

I think i am gonna blog about this. This is a nice topic to blog about

Jacob, as blueberry said, the biggest limit I can spot is that you need to load an entire MP3 to get a maximum amount of 227 bytes ( ID3V1 with fixed length ).

Unfortunately, I could not find a way to get received length with IE, using both JS and/or VBScript, always an error when you try to access into responseBody, or responseStream, during interation and state 3.

On the other hand, with FireFox you could simply start a timer when ready state is 3 and timer has not been started before.

Accordingly, when the binary length will be equal or more than 227 bytes you can save the value, abort the operation, and parse saved value with your methods (why did you choose privileged?)

IE? ... as usual, who still prefer that browser, will wait the entire file, while when we will be able to get downloaded data with IE too, things will change a lot, making Ajax more close to AS than before in every platform ;)

Jacob, something like that:


var timer = 0;
oHTTP.onreadystatechange = function() {
if(oHTTP.readyState == 3 && timer == 0){
var self = this;
timer = setInterval(function(){
if(227 < oHTTP.responseBody.length){
clearInterval(timer);
self.binaryResponse = new BinaryFile(oHTTP.responseBody);
oHTTP.abort();
oHTTP = null;
fncCallback(self);
}
}, 20);
}
};

@andrea: Thanks for the feedback, but I'm not quite sure what you're suggesting. The way I read you're code snippet, that would only work if the data you need is at the beginning of the file, no? And the ID3 tags are at the end.

Anyway, I've tried out the approach blueberry suggested and it seems to work fine in both FF, IE and Safari. I'm not a big HTTP or web server nerd and I'm not sure how well supported Range requests are, but since I'm already doing a HEAD request to get the file size, the server also tells us if it supports ranges, so I think it's all good.

The example page has been updated with the new code.

yeah that id3v2 is teh real evils =O

Jacob, you are right. I though they were at the beginning, so blueberry suggestion seems to be the best one for me as well.
Anyway, as last optimization, have you tried to set the range in this way?

bytes=-128

Regards

Can anyone tell me one reason why to do such a thing in AJAX ? Thank you.

anonymous, you are right, basically, the simplest way is to let server reply with a json object populated with every information, and in a simple / fast way.

Now, try to think that this blog is about experiments, and that read binary files via javascript is one of them, and that using the server, without a server side language, is another good experiment as well :D

As Andrea points out, this is about experimenting and making JavaScript do unusual things.

If your demand for usefulness and reason should be met, this blog would be a sad and empty place.

And timesize? have a request method?

Thanks a lot.

The example page has been updated with the new code.

doesn't work in internet explorer 6 btw.. which is still unfortunately 25% of the market.

how do we get the length of the media?

muito loko

i am necessited of the help, 1 site exemply for the ID3, peoples me help.
do when used the id3 is necessary more what?
thank you very much

I'm in need of help, 1 sample site to use ID3, please help me
I can not make it work. what does the id3 on one site? more than I need to use the id3?
thank you very much

i think this owner smart ... ugh!!!

So how hard is it to get it to work for ID3v2? Gona look into this myself as I need it.

Post a Comment

 
Copyright 2008-2009 Jacob Seidelin - Privacy Policy - Some icons by Bruno Maia, IconTexto