Reading .mp3 ID3 tags in JavaScript
For a recent project, I needed to read an .mp3’s ID3 metadata (song title, artist, year, album) in pure JS. The idea was to have the user select a song file, and boom!, its info would display to the user. Good news…totally easy with the FileReader
API and JS typed arrays.
Initially, I did a quick search to find some examples, but all of the examples I found used older techniques like manipulating a binary string. Ugh! We have better tools now for working with binary data in JS. Typed arrays to the rescue, specifically DataView
.
DataView
is a cousin to ArrayBufferView
, which is a “view” of a portion of an ArrayBuffer
. Array buffers represent chunks of bytes in memory. Multiple views can be created from a single ArrayBuffer
. For example, one could create a Int8Array
and a Float32Array
from the same underlying data. Hence, “views”. This property makes them extremely versatile for binary data.
For my purposes, DataView
turned out to be a perfect container for pulling sections of bytes as a string. However, I found the API to be a bit unintuitive in practice. Fortunately, I stumbled upon Christopher Chedeau’s jDataView a while back and things started making sense. jDataView is an excellent wrapper for DataView
, improving much of its jankiness and adding a few extra utility methods for things like seeking and getting at data (e.g. getString()
, getChar()
).
Here’s all the code that I needed:
document.querySelector('input[type="file"]').onchange = function(e) {
var reader = new FileReader();
reader.onload = function(e) {
var dv = new jDataView(this.result);
// "TAG" starts at byte -128 from EOF.
// See <a href="http://en.wikipedia.org/wiki/ID3" target="_blank">http://en.wikipedia.org/wiki/ID3</a>
if (dv.getString(3, dv.byteLength - 128) == 'TAG') {
var title = dv.getString(30, dv.tell());
var artist = dv.getString(30, dv.tell());
var album = dv.getString(30, dv.tell());
var year = dv.getString(4, dv.tell());
} else {
// no ID3v1 data found.
}
};
reader.readAsArrayBuffer(this.files[0]);
};
Pretty slick.
DataView
is implemented in Chrome 9+ and Webkit nightlies. However, jDataView provides the DataView
API for all the browsers using the best available option between Strings, JS typed arrays, and DataView
.