PDA

View Full Version : Display an estimated "position" of an MP3 while streaming.



audiotheory
January 19th, 2007, 02:36 PM
One of the problems I've noticed with a lot of Flash based MP3 players is displaying/changing the position while the file is still loading. The reason for this of course is that the 'duration' property Flash gives you is based on how much of the file is currently loaded. The solution used in every player I have seen is either to show the position based on the duration which is wrong because the duration changes as the file loads or simply not to show or allow control of the position at all. The other possibility is to read the MP3s ID tags, this however can be error-prone using Flash's ID methods so can not be relied on.

I came up with a solution to this a year ago and since I'm still seeing people having trouble with this I figured I'd post it here.

If you take a look at my MP3 player at http://www.audiotheory.co.uk (http://www.audiotheory.co.uk/) you will notice that my position indicator (the yellow bar) behaves as it should with no relation to the loading indicator (the red bar) and you can in fact change the position even while the file is still loading.

The trick is to throw accuracy out the window (accuracy? I don't need no stinkin' accuracy!) and estimate the position using the file size and the current duration. Since MP3s are compressed (and one of those compression options is Variable Bitrate) this is an estimate, however I've thrown many files at it varying in compression method and size (check the last file in the playlist on my site - it's over an hour long!) and it works very well.

Display Current Position
To display the position I have an UpdateMP3Info method that is called on a timer. You can of course use onEnterFrame, I simply use a timer as I'm happy to only update the MP3's info a couple of times a second and conserve those precious CPU cycles for things that require smoother animation. Inside UpdateMP3Info among other things I do the following.

First update the streaming bars _xscale to reflect the percentage of file loaded:

mcMP3.mcStreamBar._xscale = (myTunes.getBytesLoaded() / myTunes.getBytesTotal()) * 100;

Then calculate the position as a percentage of the current duration and multiply by 1% of the streaming bars _width to get the _width of the position bar:

mcMP3.mcPositionBar._width = ((myTunes.position / myTunes.duration) * 100) * (mcMP3.mcStreamBar._width / 100);

Set New Position
To set the position based on where the user clicks you need the _xmouse value converted into a percentage so I use the following code in the onRelease handler of an invisible MovieClip called mcPositionBarHL that sits above the Position/Streaming bars.
This MovieClip is the red highlight you see when you rollover the Position/Streaming bars. When a MovieClip has it's _alpha property set to 0 it can not be clicked on so as soon as the user moves the mouse off the Position/Streaming bar mcPositionBarHL disappears and the position can no longer be changed. This is good since you don't want the user to change the position to a part of the file that hasn't yet loaded!

First I set the Position bars _xscale so that it reaches where the user clicked by converting the _xmouse property of the mcPositionBarHL into a percentage:

mcMP3.mcPositionBar._xscale = (mcMP3.mcPositionBarHL._xmouse / mcMP3.mcPositionBarHL._width) * 100;

Then I simply use the same position estimate equation but in reverse to set the Sound objects new position. The Sound objects start method uses seconds while the estimate is in milliseconds so it must be divided by 1000:

myTunes.start( ( ( mcMP3.mcPositionBar._width * ( 100/mcMP3.mcStreamBar._width)) * (myTunes.duration / 100)) / 1000);


And that's it!
The only visible sign that it's an estimate is certain files cause the position bar to move a pixel or two back once the file has completely loaded but this only happens once and IMHO is a huge improvement on the shrinking position bar seen in players that simply use the duration property.
It's not a perfect solution but with the methods available in AS2 it's the best you're going to get without delving into some Flash to PHP MP3 library communication.

I hope this has been of help, feel free to shoot any questions my way. :beam:


:theory

evildrummer
January 19th, 2007, 04:50 PM
Thats a good idea, ill have to try it out, but I always thought there was another work-around but I cant remember it.

gvozden
January 19th, 2007, 05:46 PM
well, you have bytesTotal :) so making progress bar and clicking thing isn't really that hard
but cool for people that can't calculate 2 + 2

audiotheory
January 19th, 2007, 07:11 PM
well, you have bytesTotal :) so making progress bar and clicking thing isn't really that hard
but cool for people that can't calculate 2 + 2
A quick "search for all posts by user" made me realise I shouldn't be surprised by your waste of Kirupas server space.
A tip for you, if you're going to post snide sarcastic responses to people - make sure you know WTF you're talking about and actually read the original post.

1) This is how to get the current play position in an MP3 that hasn't completely loaded
2) Considering that nearly every Flash based MP3 player I've seen either doesn't show the play position or shows it wrong, I'd say there are a lot of "people that can't calculate 2 + 2".

cheers.
http://www.audiotheory.co.uk/test/WinterToSummer.swf

:theory

gvozden
January 20th, 2007, 03:31 AM
I didn't want to offend you, sorry if you felt hit I was being sarcastic beause people mainly do copy paste code and only then you can experience problem with progress bar and things like that
and basiclly that was a joke not that pointing at someone

this is good tutorial and it will help many people
but to explain what I meant for 2 and 2 is basiclly like I said people don't explore and they would rather search a web for solution, if they don't find it they will just leave things out

your sentence that I am "wasting space" here is very low blow thing and very few on kirupa so you can think what you want and if other people do too I can always head out my way out, thanks

rmo518
February 12th, 2007, 02:33 PM
I'm trying to find a work around for a slightly different application, but this seems to be the solution I'm looking for. Here's the problem I've run into - the estimated time is 6 to 8 seconds short (depending on the MP3) up until the moment when the entire MP3 is loaded. I assume that this is because the data is not evenly distributed across the length of the file.

I'm trying to get an (almost) instantaneous estimate of a song's length dynamically. This is very cose to doing what I need, but the descrepancy is just large enough to concern me.

Here's the code I'm using:
function musicTimeCheck(mySong) {
s = new Sound();
this.onEnterFrame = function() {
if (s.getBytesLoaded()>0) {
TIME_EST = (s.duration/1000)*(s.getBytesTotal()/s.getBytesLoaded());
if (s.getBytesLoaded()>=s.getBytesTotal()) {
delete (this.onEnterFrame);
}
}
trace(TIME_EST);
};
s.loadSound(mySong, true);
s.stop();
}
musicTimeCheck("mySongURL.MP3");

Anyone have any ideas on how to get around this?

rmo518
February 12th, 2007, 04:39 PM
While the method above is probably close enough for an MP3 player progress bar, I was looking for something a little more precise. I found this PHP approach:

http://www.sourcerally.net/Scripts/20-PHP-MP3-Class

Using the sample included in the comments I was able to get the length of my MP3 files.


//Extract the exact length of time
$path = 'mySong.mp3';
$mp3 = new mp3($path);
$mp3->setFileInfoExact();
echo $mp3->time;
//note that this is the exact length!

(For some reason I had to comment out the function called mergeBehind and mergeInfront to get the script to run on my server. I'm not very strong with PHP, so maybe there's a simple reason for that.)

But if there is an AS solution I'd love to know about it.

dogandking
February 18th, 2007, 06:12 PM
Hi Audiotheory.

I've been getting into Actionscript for a little while now.
I'm learning fast. Mostly from cats like you.
The player you made is sick.
Simple, to the point, with good style.
It's actually exactly what I've been looking to do, but don't have the knowledge yet.
So far, every player I've made has been a hybrid of someone elses.

Soon. Anyways, I'm trying to make a player somewhat along the lines of the way yours functions.
Whenever I manage to put it together, I'd like to send it to you for your feedback if you don't mind.
*Promise not to laugh.

Take care.

dogandking

YoungNastyMan
March 11th, 2007, 04:38 AM
audiotheory, this is exactly what I've been searching for!! I have a few concerns, however. I tried your code above with very odd results. mcPositionBar seems to follow my mouse cursor all over the swf. I'm not entirely sure that setting the alpha value of mcPositionBarHL to 0 causes it to react exactly the way you explained it above. Obviously, I must be doing something wrong. Maybe, I'm just using an older version of flash (mx 04).

Would it be possible for you to post a zipped fla please?

Thanks

YoungNastyMan
March 13th, 2007, 04:33 PM
Okay, I figured it out! (I just had a few dumb misspellings in my code, but I finally got it). audiotheory's code works really well and is a sweet and simple solution to an awesome MP3 player. Here's an attachment of a working example I made using audiotheory's code. Just add your own mp3.

rille31
April 11th, 2007, 09:32 AM
This code was great,simple and effective

will post a link when a project is finished that uses a modified version of this.

lorren.biffin
July 28th, 2007, 04:19 PM
So, I hate to bring up an old thread, but has anybody found out a good way to grab the duration of an mp3 with PHP?

I've used the class rmo518 is using, but it has a major bug that returns a "Divide by Zero" error on half of the files you throw at it.

If anybody has a good server side(PHP) solution for grabbing the duration of an mp3 file I'd ver much appreciate the help. Thanks!

lorren.biffin
July 29th, 2007, 06:02 PM
UPDATE: This one seems to be pretty damned precise and consistent:

http://getid3.sourceforge.net/