Calculating duration on mp3s in AS3
When you play an mp3 file from the web via the Sound class in AS3, the length property increases as the mp3 downloads, which causes headaches when creating scrub bars for audio.
The solution is simple. Estimate the duration by calculating the bytes per second (sound.bytesLoaded / sound.length) and divide sound.bytesTotal by that number. That gives you an estimated duration. Just call this script repeatedly until the sound is finished loading, such as a 10ms timer.
This equation divides by 1000 to return duration in seconds, but you could remove the / 1000 if you want it in milliseconds.
if (sound && sound.length > 0)
{
var duration:Number = (sound.bytesTotal / (sound.bytesLoaded / sound.length)) / 1000;
}
Posted in Actionscript, Flash, Tips/Tricks
December 2nd, 2008 at 2:29 pm
Steven,
Without having tried this myself, how accurate is it when compared to what you get when the sound is actually loaded?
December 2nd, 2008 at 10:14 pm
My brain is hurting thinking about whether your way really works. Seems like if you know the bitrate of the mp3 and it's CBR (not VBR) then you could just divide the bytes total by the bitrate to get a good duration.
I'll probably wake up in the middle of the night have an epiphany… what the heck is Flash's duration reporting anyway? I wonder if the correct info is in the file's header.
December 2nd, 2008 at 11:13 pm
@Matt – It's accurate to within a few seconds before 5 seconds, and by 5-7 seconds it's within a second. After 10 seconds, you're within a few hundred milliseconds. Suffice to say, it's accurate enough to be fractions of pixels on scrub bars from the start. You won't be able to see it. If you have a duration field, it might jump a little at the beginning, but it's not too noticable and it's over quickly enough.
@Phillip – My way really works, but as you mentioned, it only works with CBR, and might only work with 16/44 but non 16/44 have issues anyway. VBRs have never really worked with Flash anyway. They either work just fine, or they end up triggering SoundComplete before they're actually complete, or just stopping during playback altogether. FP10 allows you bring in the mp3 as a byte stream, so theoretically (I haven't tested it), you can finally play VBRs in Flash with some reliability.
December 9th, 2008 at 9:47 pm
There are some id3 editors that will automatically add a length property to the id3 tag. Then you can get that value from the id3 event dispatched by the sound object.
December 9th, 2008 at 10:06 pm
Unfortunately, as I found out from the Flash player team at MAX, iTunes uses its own version of ID3v2 that Flash cannot detect so it never fires an ID3 event nor can it be read via the ID3 class.
So, for reliable ID3 access, you should use metaphile.
However, not all mp3s have useful ID3 data, so when you're loading mp3s that are not in your control, this estimation is as good as it gets, and it's pretty damn good. I've tested it on a bunch of mp3s from Seeqpod and it works great.
February 27th, 2009 at 3:00 am
This code works nicely, cheers!
I found it a bit fiddly trying to work out the track time correctly, so here it is for anybody else:
var Milliseconds:Number = (music.bytesTotal / (music.bytesLoaded / music.length));
var Minutes:uint = Math.floor(Milliseconds/60000);
var Seconds:uint = (Milliseconds%60000);
var SecondsTens:uint = Math.floor(Seconds/10000);
Seconds = Math.ceil(Seconds%10000)
Seconds /= 1000;
trace(Minutes + ":" + SecondsTens + "" + Seconds);
dudan
March 25th, 2009 at 9:28 pm
thanks steven & dudan, perfect!
March 26th, 2009 at 11:33 pm
its work on localy but not in server
June 16th, 2009 at 6:33 am
Amazing, working so nicely!
Thanks so much Steven!
January 17th, 2010 at 1:03 pm
Hi! The code works, but not when I load a MP3. If a trace the sound.length it's display an increasing value of the length until the sound finished loading.
I want to start playing the sound while its's loading and show the position of the sound in a mc.
Is it possible?
April 16th, 2010 at 1:42 pm
@rob: The code gives you an estimated value, not accurate, but it works fine
April 16th, 2010 at 3:27 pm
It's plenty accurate, it just takes a few seconds to calibrate.
April 25th, 2010 at 4:10 am
sweet piece of 1 liner code. works perfect!