<< Flash Trivia
 

Synchronize animation and sound

Apr 27, 2008 - 6:33pm by earl223

Most of you may have experienced this problem: When making a presentation or animation you add background music and effects to play alongside your movie. It works great during testing... but once you play the actual movie (on different computers) the sounds and animation are not longer in sync. Why?



Flash is memory intensive; a movie requires more than it's fair share of processor resources in order to perform well. This means that flash movies play at different speeds depending on the processing power of the computer where the movie is played. Now sounds and music are independent of the flash timeline and is not restricted by processing speed. So a two minute mp3 file will still require 2 minutes to play... while a two minute flash movie will vary.



This is the disadvantage of having frame-based animations; you allow flash to dictate the speed in which your movie plays (via FPS). As pointed out, doing so is not accurate because of the different processing powers of the users' computers. To solve this, we need to do time-based animations instead.



For all computers, time happens at the speed as it's supposed to happen. Meaning, whether you have a really old PC or one of those high-performance ones, one second is still one second. Knowing this, we must tell our movie to play based on actual time.. and not on the FPS.



To apply this method, you will need to add some actionscript into your movie. Actionscript is a scripting language used to control your movie, if you have worked with flash buttons then you will have an idea of how actionscript would look like. If not, then don't worry, i'll try to explain everything as we go along.



First thing to do of course is your movie with all the animations, background music, and stuff. Once you have your movie, and it's playing the way you want it to play, it's time to add our script.



At the bottom part of the Flash window, you should see a panel called Actions just above the Properties panel; click on it to open the panel. (If you don't see the Actions panel, you can go to Windows Menu (in Flash UI) and click on Actions.)



With the actions panel open, go to the timeline and click on frame1. This is where we will add our actionscript that will instruct flash to play our movie based on time. With frame 1 selected, enter the following script in the Actions panel:



Note: The following script assumes that you have Flash Professional 8. If you have Flash CS, we need to do a few adjustments in order for it to work.



//-----------------------------

stop();

if (intID == undefined) {

intID = setInterval(this, "playMovie", your_Interval);

}


function playMovie() {

if (_currentframe == _totalframes) {

clearInterval(intID);

} else {

gotoAndStop(_currentframe+1);

}


}

//-----------------------------



That's it. Now let's go over the script to see what it does.



stop();



This command simply tells our movie to stop on frame 1. When we play our movie, it automatically does so... moving from frame to frame. Putting a stop() action on the first frame prevents flash from doing that since we don't want a "frame-based" animation. We tell it to stop() because we want to control the movie our way.



if (intID == undefined) {

intID = setInterval(this, "playMovie", your_Interval);

}



This script was placed for a reason which i'll be explaining more about later (especially the if part) but right now i want to focus on:



setInterval(this, "playMovie", your_Interval);



setInterval is a built-in action in Flash... like a command, telling it to do something. More specifically, it's telling Flash to do something based on an interval (time). More like... "do this every second..." or "do this every five seconds.." or even "do this every 1/10 of a second."



the setInteval command answers 3 questions: Where will i do it? What will i do? And How often will i do it? So we could say that it would look something like this:



setInterval(Where, What, How);



In the script we have, this is how we answered those questions:



Where will i do it? this



The word "this" just refers to your movie, so Flash will know that you want to do something with it.



What will i do? "playMovie"



playMovie, as we'll learn later on, is just a "to-do" list. All the things you would ever want to happen every so often should be included in this list.



How often will i do it? your_interval



Now here's the part where you have to decide... how often do you want to do it? your_interval will be replaced with a number representing the amount of time you want to pass before the "to-do" list is done again. Do you want to do it every second? Every 5 seconds? Every hour?



The answer is pretty simple actually; all you have to do is look at your FPS settings. Flash defaults the FPS to 12 but of course you may have changed this to a different rate. The formula for your_interval is 1000 divided by FPS. If you didn't change the default FPS setting then the value of your_interval is 83 (1000/12 = 83.333), making your setInterval look like this:



setInterval(this, "playMovie", 83);



if you changed you FPS to 30 for example then you will have 33 (1000/30 = 33.333), so...



setInterval(this, "playMovie", 33);



In the end, this is telling Flash to do the "to-do" list every 1/33 of a second (for 30FPS) or 1/83 of a second (for 12 FPS). This will cause your 5 minute movie to play and finish in exactly 5 minutes regardless of the processing power of the hosting computer.



Now looking at that complete line of script, we actually assign the setInterval command into intID:



intID = setInterval(this, "playMovie", 33);



We do this because we need a way to control the movie playback. Using setInterval will cause our movie to play continueosly... and we won't be able to stop it. But by assigning the action to intID, we can now stop movie playback anytime we want, by simply saying:



clearInterval(intID);



Right now, we don't need to stop our movie so we're gonna use clearInterval later when our movie has reached the last frame on the timeline.



Moving on... we come to our "to-do" list:



function playMovie() {

if (_currentframe == _totalframes) {

clearInterval(intID);

} else {

gotoAndStop(_currentframe+1);

}


}



playMovie is a function... or a group of instructions which we can do over and over again by calling the function name playMovie. In the setInterval command, we used this function to represent our "to-do" list... so this is what setInterval will do everytime our interval is met.



function playMovie() {

// instructions...

// instructions...

}



Above shows you how the playMovie function is made up. Everytime this function is called all instructions inside it are performed. Looking at the instructions, we have:



if (_currentframe == _totalframes) {

clearInterval(intID);

} else {

gotoAndStop(_currentframe+1);

}



I'll try not to go into the more technical details of this... but to put it plainly, the above instructions can be interpreted as:



if we have reached the end of the movie

stop movie playback

if not

show the next frame



Everytime Flash does the "to-do" list, it first asks itself... have i reached the end of the movie? If yes, then we stop the movie by using clearInterval(intID). If not, then just continue playing the movie with gotoAndStop(_currentframe+1). As _currentframe implies, it just checks the frame which the playhead is currently on and then adds a value of 1 to it. So if the movie is currently on frame 6, Flash will go to frame 7, then frame 8, and so on.



if we have reached the end of the movie

clearInterval(intID);

if not

gotoAndStop(_currentframe+1);



Converting back to the original set of instructions, we will finally have:



stop();

if (intID == undefined) {

intID = setInterval(this, "playMovie", 33);

}


function playMovie() {

if (_currentframe == _totalframes) {

clearInterval(intID);

} else {

gotoAndStop(_currentframe+1);

}


}



All in all, this script will play your movie (based on a 30 FPS rate) then stop once it reaches the end of your movie. And the movie will play as it's supposed to play regardless of platform. Note again that your_interval should be computed correctly based on your current FPS rate.



Now some tweaks... what if you don't want your movie to stop? What if you want it to loop and play again? Like after it reaches the last frame, just go back to frame number 1 and continue playing? To do this all you have to do is remove clearInterval and replace it with gotoAndStop(1);



if (_currentframe == _totalframes) {

gotoAndStop(1);

} else {

gotoAndStop(_currentframe+1);

}



And that's it.. you are done. Having sounds in your movie will now be of no problem since we are now playing our movie based on time.



Now as i noted earlier, the script above was made for Flash professional 8. If you are using Flash CS, we need to do something first. In Flash CS, click on the File menu, then select Publish Settings. Click on the Flash tab, and you will see settings for Flash Player version and Actionscrip version. Just make sure that they are set to Flash 8 and Actioscript 2 respectively.



As a final note: The script given here is as basic as it can get. It will work only on movies that play sequentially and directly on the main timeline. If you have complex movieclips and buttons, then a bit more tweaking to the script may be required.



There are two more options for synchronizing sound with your movie though they take a bit more work...one entails "cutting" your sound file into multiple pieces and placing them on the timeline when they're supposed to play, while the other needs cue points to be set, which also requires a bit more actionscripting to perfect it.



 



 

2 Comments

Add Comment
  • white_noise

    wow! thank you for this!

    April 28, 2008 at 1:18 am
  • earl223

    Thanks. If you have other tutorial requests, sabihin nyo lang and we'll see what we can come up with. :)

    April 28, 2008 at 2:42 pm
You must be logged in to post a comment
ADVERTISEMENTS