I have spent a lot of time looking at FLV players custom built from scratch, since my students have been designing and coding them.
One problem that keeps popping up is the play/pause button not showing the right icon at the right time. I looked at my latest version and found that my code was slightly different. Here it is in case you want to try it.
This replaces the play button code in the flv player described back in August:
//Alternative play button code
video_ns.onStatus = function() {
if (video_ns.time >= duration-1) {
playstatus = 3;
_root.pause_mc.gotoAndStop("pauseoff");
} else {
playstatus = 1;
_root.pause_mc.gotoAndStop("pauseon");
}
};
_root.pause_mc.onRelease = function() {
if (playstatus == 1) {
video_ns.pause();
playstatus = 2;
_root.pause_mc.gotoAndStop("pauseoff");
} else if (playstatus == 2) {
video_ns.pause();
_root.pause_mc.gotoAndStop("pauseon");
playstatus = 1;
} else if (playstatus == 3) {
video_ns.play(currentvid);
_root.pause_mc.gotoAndStop("pauseon");
playstatus = 1; }
};
For users doing the Flashvars or Query String method the only other thing you have to change is the value of the playstatus variable at the top of your code as follows:
playstatus = 3;
See how you get on. The biggest difference is that I now have 3 playstatuses, not 2.
Showing posts with label flv. Show all posts
Showing posts with label flv. Show all posts
Friday, 27 February 2009
Thursday, 26 February 2009
An alternative to Flashvars: a Query String
One thing I did not expect when using Flashvars was that one of my students would experience what appears in all ways to be the browser caching the swf with the Flashvars. (Caching means that the browser saves the file and gets it from the temporary internet files instead of checking for changed files from the server.) I did expect the swf to cache, but not the Flashvars. After all the whole reason for the invention of Flashvars was to allow the passing of variables to a swf from the HTML without the swf having to be re-downloaded every time.
I suspect that this is something to do with the students computer and testing from the local machine rather than a server.
However, to solve my student's problem, the good news is that Flashvars is not the only way to pass variables to a swf from the HTML. Last time I mentioned 3 options, hard coding, XML or Flashvars. But I missed one: the Query String.
The Query String
This is really well explained in this website here (click).
But to quickly sum it up, one way we can pass variables to flash from the HTML page in which the flash is Objected and Embedded is by tagging them on to the end of the swf location path.
Normally the swf location path might appear something like this:
For Object:
PARAM NAME=movie VALUE="flaMovie.swf"
For Embed:
src="flaMovie.swf"
We pass the variables to the swf by tagging them onto the end of the swf location path as follows:
For Object:
PARAM NAME=movie VALUE="flaMovie.swf?currentvid=videoname.flv&duration=999"
For Embed:
src="flaMovie.swf?currentvid=videoname.flv&duration=999"
I suspect that this is something to do with the students computer and testing from the local machine rather than a server.
However, to solve my student's problem, the good news is that Flashvars is not the only way to pass variables to a swf from the HTML. Last time I mentioned 3 options, hard coding, XML or Flashvars. But I missed one: the Query String.
The Query String
This is really well explained in this website here (click).
But to quickly sum it up, one way we can pass variables to flash from the HTML page in which the flash is Objected and Embedded is by tagging them on to the end of the swf location path.
Normally the swf location path might appear something like this:
For Object:
PARAM NAME=movie VALUE="flaMovie.swf"
For Embed:
src="flaMovie.swf"
We pass the variables to the swf by tagging them onto the end of the swf location path as follows:
For Object:
PARAM NAME=movie VALUE="flaMovie.swf?currentvid=videoname.flv&duration=999"
For Embed:
src="flaMovie.swf?currentvid=videoname.flv&duration=999"
Monday, 23 February 2009
Flash Projects - #6 - Slim Custom Video Player with Flashvars
Well, we have come a long way since the swf video player and the flv video player. Both versions of the player had a menu built in to the flash movie for selecting which video you want to play. But not all applications of a video player require a built in menu, what if you only want to play one video?
Let's go further. What if you want to play one video on one web page, but another video on another web page?
Do we have to produce a whole video player flash movie for each video we want to show?
The good news is NO. The other good news is that building a custom flv player in flash that we can re-use for different videos is a great excuse to learn some more ActionScript.
Ready? Then let's begin.
Defining the problem
So we want to produce a video player in Flash that knows which video to play, when we press play, without having to "hard code" this knowledge into the video player.
How does Flashvars work?
Adobe sum it up on their website, but if that looks hard don't worry, I am about to talk you through it.
Take a look at the example on this page (click). As you can see it looks pretty much like any Object and Embed tag but this time with the addition of the Flashvars parameters.
Within Flashvars we can define any variable with any value. These variables and their values are then passed to the flash movie we are Objecting and Embeding and created within the movie before the first frame of the movie. If we were "hard coding" the variables and their values into the video player we would expect to do it in the first few lines of the first frame in the timeline. That Flashvars creates the variables before the first frame is just as good from our point of view.
This means we can include the same video player in every page of our website, but get each one to play a different flv file by simply changing the values of the Flashvars parameters in the HTML Object and Embed tags.
A quick recap (before we make changes)
The original code had the name of the flv file "hard coded" for the menu button as follows:
_root.m1_btn.onRelease = function () {
video_ns.play("video1.flv");
currentvid = "video1.flv";
}
The code above does two things when the button is released. First, it tells the NetStream object called "video_ns" to play a specified FLV file. Secondly it sets the value of a variable called currentvid to be the same as the name of the FLV file - this helps us later on when we are programming the playback controls.
Now making the changes
Basically, instead of having the menu button, you just include the following variable and value in the Flashvars.
Within Object:
param name="FlashVars" value="currentvid=video1.flv"
Within Embed:
flashvars="currentvid=video1.flv"
And it is that simple.
All your existing code should still work.
Taking it further
If you feel like getting more advanced (and if you are not using flv 1.1 files) you could even include the length of the flv video (in seconds) as a Flashvar too. If you remember, only flv 1.1 or later includes the duration of the flv in meta data, and our progress bar relies on knowing the duration of the video. Using Flashvars as follows you can tell the video player the duration without needing meta data:
Within Object:
param name="FlashVars" value="currentvid=video1.flv&duration=999"
Within Embed:
flashvars="currentvid=video1.flv&duration=999"
Then you can delete (or comment out) the code that tries to get the duration of the flv from the metadata, you know, this bit:
NetStream.prototype.onMetaData = function(obj){
var duration = obj.duration;
}
You can delete the above and your play, pause, and progress bar will still work, because instead of getting the duration from metadata it will now be getting it from Flashvars.
Voila!
Oops, nearly forgot...
Oh, one last thing, make sure you add the following code to the first line on your first frame:
var playstatus = 2;
This is needed because in the original player, as soon as you selected the video it begins to play, the play/pause system then worked on the assumption that the video is already playing. The code was as follows:
video_ns.onStatus = function() {
if (video_ns.time >= duration-1){
playstatus = 2;
_root.pause_mc.gotoAndStop("pauseon");
}
else {
playstatus = 1;
_root.pause_mc.gotoAndStop("pauseoff");
}
}
_root.pause_mc.onRelease = function () {
if (playstatus == 1){
video_ns.pause();
_root.pause_mc.gotoAndStop("pauseoff");
}
else if (playstatus == 2){
video_ns.play(currentvid);
}
}
Read the code and you will see that you can only play the video if playstatus = 2. But because we now get the video info from Flashvars the video is not already playing so we need to set the playstatus to 2 manually or you can never play the movie. Hence make sure you add the following code to the first line on your first frame:
var playstatus = 2;
What fun.
Let's go further. What if you want to play one video on one web page, but another video on another web page?
Do we have to produce a whole video player flash movie for each video we want to show?
The good news is NO. The other good news is that building a custom flv player in flash that we can re-use for different videos is a great excuse to learn some more ActionScript.
Ready? Then let's begin.
Defining the problem
So we want to produce a video player in Flash that knows which video to play, when we press play, without having to "hard code" this knowledge into the video player.
Consider solutions
There are several ways we can tackle this problem, such as:
- We "hard code" the video player to look for a video of a pre-determined name and pre-determined relative location. But that means having multiple copies of the same video player in different folders. Saves us some ActionScripting, but means that the user has to download the video player every time from a new location.
- We use an XML file external to the video player to tell it what video it needs to play. Not a bad idea but some relatively complex ActionScript for a relatively simple thing. No, there is a simpler way.
- We use the obscure but very handy Flashvars capability to tell the videoplayer what to play by including the information within the Object and Embed tags in the HTML.
How does Flashvars work?
Adobe sum it up on their website, but if that looks hard don't worry, I am about to talk you through it.
Take a look at the example on this page (click). As you can see it looks pretty much like any Object and Embed tag but this time with the addition of the Flashvars parameters.
Within Flashvars we can define any variable with any value. These variables and their values are then passed to the flash movie we are Objecting and Embeding and created within the movie before the first frame of the movie. If we were "hard coding" the variables and their values into the video player we would expect to do it in the first few lines of the first frame in the timeline. That Flashvars creates the variables before the first frame is just as good from our point of view.
This means we can include the same video player in every page of our website, but get each one to play a different flv file by simply changing the values of the Flashvars parameters in the HTML Object and Embed tags.
A quick recap (before we make changes)
The original code had the name of the flv file "hard coded" for the menu button as follows:
_root.m1_btn.onRelease = function () {
video_ns.play("video1.flv");
currentvid = "video1.flv";
}
The code above does two things when the button is released. First, it tells the NetStream object called "video_ns" to play a specified FLV file. Secondly it sets the value of a variable called currentvid to be the same as the name of the FLV file - this helps us later on when we are programming the playback controls.
Now making the changes
Basically, instead of having the menu button, you just include the following variable and value in the Flashvars.
Within Object:
param name="FlashVars" value="currentvid=video1.flv"
Within Embed:
flashvars="currentvid=video1.flv"
And it is that simple.
All your existing code should still work.
Taking it further
If you feel like getting more advanced (and if you are not using flv 1.1 files) you could even include the length of the flv video (in seconds) as a Flashvar too. If you remember, only flv 1.1 or later includes the duration of the flv in meta data, and our progress bar relies on knowing the duration of the video. Using Flashvars as follows you can tell the video player the duration without needing meta data:
Within Object:
param name="FlashVars" value="currentvid=video1.flv&duration=999"
Within Embed:
flashvars="currentvid=video1.flv&duration=999"
Then you can delete (or comment out) the code that tries to get the duration of the flv from the metadata, you know, this bit:
NetStream.prototype.onMetaData = function(obj){
var duration = obj.duration;
}
You can delete the above and your play, pause, and progress bar will still work, because instead of getting the duration from metadata it will now be getting it from Flashvars.
Voila!
Oops, nearly forgot...
Oh, one last thing, make sure you add the following code to the first line on your first frame:
var playstatus = 2;
This is needed because in the original player, as soon as you selected the video it begins to play, the play/pause system then worked on the assumption that the video is already playing. The code was as follows:
video_ns.onStatus = function() {
if (video_ns.time >= duration-1){
playstatus = 2;
_root.pause_mc.gotoAndStop("pauseon");
}
else {
playstatus = 1;
_root.pause_mc.gotoAndStop("pauseoff");
}
}
_root.pause_mc.onRelease = function () {
if (playstatus == 1){
video_ns.pause();
_root.pause_mc.gotoAndStop("pauseoff");
}
else if (playstatus == 2){
video_ns.play(currentvid);
}
}
Read the code and you will see that you can only play the video if playstatus = 2. But because we now get the video info from Flashvars the video is not already playing so we need to set the playstatus to 2 manually or you can never play the movie. Hence make sure you add the following code to the first line on your first frame:
var playstatus = 2;
What fun.
Flash Projects - #5 - Custom Video Player Mute Control
Building further on the custom FLV player in previous posts, and definitely inspired by the BBC iPlayer, I decided to add further functionality, including a mute control to turn off the sound for a video currently playing.
The ActionScript is really very simple, and logical. Once you understand how to stream and attach video, attaching sound for control is very straight forward.
Quick recap
The original code required you to create a netConnection object and attach to that a netStream object:
//Net connection for video stream to video object
var myConnection_nc:NetConnection = new NetConnection();
myConnection_nc.connect(null);
var video_ns:NetStream = new NetStream(myConnection_nc);
Then you were instructed to attach the video stream to a video object on the stage:
this.vidHolder_mc.vid_video.attachVideo(video_ns);
Attaching audio
Setting up to control (or mute) the audio is not all that different. Use the following code:
//Attach audio of FLV for volume control
flv_mc.attachAudio(video_ns);
var audio_sound:Sound = new Sound(flv_mc);
Notice that the video and the audio both attach the same netStream object video_ns. While the audio will still be heard without attaching it separately, if we want to control it, we must attach it to a movie clip of its own as above. In this case a movie clip called flv_mc.
Controlling audio
Because we want a mute button that will change depending on the mute status (showing whether the sound is currently muted or not - visual feedback is such a wonderful thing), you need to create a variable to store the current mute status.
Insert the following code right at the top of your ActionScript:
//Mute control status, 0 = mute off sound on
var mutestatus = 0;
Then you need to create a movie clip to act as the mute button. This has just two frames, one containing an image of a speaker making noise, the other containing an image of a speaker not making noise (decide how to depict this however you like). Give the first frame the label muteon and the second frame the label muteoff. Don't forget to put a stop(); action on each of the frames or you will have an animated flickering button. Then drag an instance of the mute button onto the stage and give it the instance name mute_mc.
The following code will then allow you to mute and un-mute the sound, insert this at some point after the line you just inserted above:
//Mute control
_root.mute_mc.onRelease = function() {
if (mutestatus == 0) {
_root.mute_mc.gotoAndStop("muteon");
mutestatus = 1;
audio_sound.setVolume(0);
updateVolume();
} else if (mutestatus == 1) {
_root.mute_mc.gotoAndStop("muteoff");
mutestatus = 0;
audio_sound.setVolume(100);
updateVolume();
}
};
How does it work? Very simple. First it checks to see what the mute status is (whether it is muted yet or not). If it is not muted, it tells the button to look like it is muted (goes to the frame with the muted speaker picture), then sets the mute status to 1, then sets the volume to be 0, then updates the volume to make the 0 take effect. If, however, it is already muted, it tells the button to look like it is not muted (goes to the frame with the noisy speaker picture), then sets the mute status to 0, then sets the volume to be 100, then updates the volume to make the 100 take effect.
And that's a wrap.
The ActionScript is really very simple, and logical. Once you understand how to stream and attach video, attaching sound for control is very straight forward.
Quick recap
The original code required you to create a netConnection object and attach to that a netStream object:
//Net connection for video stream to video object
var myConnection_nc:NetConnection = new NetConnection();
myConnection_nc.connect(null);
var video_ns:NetStream = new NetStream(myConnection_nc);
Then you were instructed to attach the video stream to a video object on the stage:
this.vidHolder_mc.vid_video.attachVideo(video_ns);
Attaching audio
Setting up to control (or mute) the audio is not all that different. Use the following code:
//Attach audio of FLV for volume control
flv_mc.attachAudio(video_ns);
var audio_sound:Sound = new Sound(flv_mc);
Notice that the video and the audio both attach the same netStream object video_ns. While the audio will still be heard without attaching it separately, if we want to control it, we must attach it to a movie clip of its own as above. In this case a movie clip called flv_mc.
Controlling audio
Because we want a mute button that will change depending on the mute status (showing whether the sound is currently muted or not - visual feedback is such a wonderful thing), you need to create a variable to store the current mute status.
Insert the following code right at the top of your ActionScript:
//Mute control status, 0 = mute off sound on
var mutestatus = 0;
Then you need to create a movie clip to act as the mute button. This has just two frames, one containing an image of a speaker making noise, the other containing an image of a speaker not making noise (decide how to depict this however you like). Give the first frame the label muteon and the second frame the label muteoff. Don't forget to put a stop(); action on each of the frames or you will have an animated flickering button. Then drag an instance of the mute button onto the stage and give it the instance name mute_mc.
The following code will then allow you to mute and un-mute the sound, insert this at some point after the line you just inserted above:
//Mute control
_root.mute_mc.onRelease = function() {
if (mutestatus == 0) {
_root.mute_mc.gotoAndStop("muteon");
mutestatus = 1;
audio_sound.setVolume(0);
updateVolume();
} else if (mutestatus == 1) {
_root.mute_mc.gotoAndStop("muteoff");
mutestatus = 0;
audio_sound.setVolume(100);
updateVolume();
}
};
How does it work? Very simple. First it checks to see what the mute status is (whether it is muted yet or not). If it is not muted, it tells the button to look like it is muted (goes to the frame with the muted speaker picture), then sets the mute status to 1, then sets the volume to be 0, then updates the volume to make the 0 take effect. If, however, it is already muted, it tells the button to look like it is not muted (goes to the frame with the noisy speaker picture), then sets the mute status to 0, then sets the volume to be 100, then updates the volume to make the 100 take effect.
And that's a wrap.
Thursday, 14 August 2008
Flash Projects - #3 - Custom FLV Player
Back in February I posted a tutorial to make a video player in Flash that played external SWF files. I promised then to post another tutorial that showed how to make a video player in Flash that played external FLV files. I wrote the program ages ago but finally got round to writing it up for my blog.
Although both programs are fine, FLV is much the up-to-date way of showing video in Flash so I hope you find this useful. feel free to leave comments or questions.
Getting Started
To keep things organised I like wherever possible to keep all my code in one place. All the ActionScript in this tutorial should be attached to the first key frame in your movie.
Unlike the version of the video player that played SWF movies, we cannot use loadmovie to simply show a movie within a movie. FLV files require us to use NetConnection and then NetStream to stream the FLV file from its location.
First off then we need to create a new NetConnection called "myConnection_nc":
var myConnection_nc:NetConnection = new NetConnection();
myConnection_nc.connect(null);
Now we need to create a NetStream called "video_ns" that will stream through the NetConnection you made above:
var video_ns:NetStream = new NetStream(myConnection_nc);
Now we have created a NetConnection and a NetStream through which we will stream the FLV file, we need to create a video object on the stage through which the FLV will be displayed.
First, you need to create a new Embedded Video object in the library. To do this, click the little menu in the corner at the top of the Library and select the "New Video" option. It should appear in the Library as "Embedded Video 1". Then drag an instance of the Embedded Video 1 onto the stage and give it the instance name of "my_video".
Now we are ready to attach the NetStream created above to the video object you just placed on the stage called "my_video":
my_video.attachVideo(video_ns);
Now we need to do two things. First, we need to find out how long the FLV file is (its duration), second we need to set the value of the duration variable equal to the property of the duration object. This will allow us to control the playback of the FLV later on.
To do this we first use prototype.OnMetaData to find the duration of the video - this only works with FLV 1.1 files and later, earlier versions do not include duration in metadata.
Unfortunately there is no other way of finding the duration of an FLV file (you can't use the _totalframes method like you can in SWF files).
Then we can set the value of the duration variable to be equal to the duration property of the FLV file as defined in the FLV's MetaData. Here goes:
NetStream.prototype.onMetaData = function(obj){
var duration = obj.duration;
}
Video Selector
Now for the playback controls. The simplest control is the video selector. This allows the user to choose which video they want to watch.
First create a button in the Library, then drag two instances of the button onto the stage. Give the buttons the following instance names - "m1_btn" and "m2_btn".
Because we are playing FLV files and not SWF files, we cannot use the loadMovie method. Instead we need to tell the NetStream object we created earlier, to play and tell it which FLV file to play. We create code for each of the buttons we created earlier, so that when each is clicked, the NetStream object we created streams a different FLV file to the video object:
_root.m1_btn.onRelease = function () {
video_ns.play("video2.flv");
currentvid = "video2.flv";
}
_root.m2_btn.onRelease = function () {
video_ns.play("video1.flv");
currentvid = "video1.flv";
}
The code above does two things when the button is released. First, it tells the NetStream object called "video_ns" to play a specified FLV file. Secondly it sets the value of a variable called currentvid to be the same as the name of the FLV file - this helps us later on when we are programming the playback controls.
Rewind Button
Dead easy. Create a button in the Library that looks like a rewind icon. Drag an instance of the button onto the stage and give it the instance name of "rw_btn". Then add the following code to the first key frame with the rest:
_root.rw_btn.onRelease = function () {
playpos = video_ns.time;
if (playpos > 10)
{
video_ns.seek(playpos-10);
}
else
{
video_ns.seek(0);
}
}
The code above makes the video jump back 10 seconds when the rewind button is clicked. It might seem pretty complex considering that all we want to do is rewind a bit. What it actually does first is check how far into the video we have progressed and the reason for this is that we don't want to jump back to a point before the video starts, that would be impossible. Depending on how far the video has played the code then does one of two things. If the video has played more than 10 seconds, then it tells the NetStream object to jump back 10 seconds in the FLV, if the video has not yet been playing for more than 10 seconds it tells the NetStream object to go back to the beginning of the FLV.
I found that in practice, with large FLV files, the rewind is not always reliable, and can get "stuck" at points, refusing to rewind past them. I suspect this is something to do with the FLV itself, rather than the coding - however, I have also included the option of clicking on the progress bar to jump to any point in the video, which so far has proved very reliable - this is explained later in the tutorial.
NOTE: If you made the previous video player that used SWF instead of FLV files, you will notice that we are using a lot of different methods. Most significant is that with FLV we cannot gotoAndPlay specific frames as we can with SWF files. Instead we use the seek method, and it is the NetStream object called "video_ns" that we are instructing to seek, not the video instance on the stage.
Forward-wind
This is much more straightforward. As before, create a button in the Library that looks like a forward-wind icon. Drag an instance of the button onto the stage and give it the instance name of "fw_btn". Then add the following code to the first key frame with the rest:
_root.fw_btn.onRelease = function () {
playpos = video_ns.time;
video_ns.seek(playpos+10);
}
This isn't nearly as complex. When the forward-wind button is released the code sets the value of a variable playpos to the current time position of the movie using video_ns.time. It then simply uses the seek method to tell the NetStream object to jump forward 10 seconds from the current time position in the FLV.
Play and Pause Button
Now we get more complex. For my player I opted to have the Play and Pause buttons be the same button, but have the icon on the button change depending on whether the movie is playing or not. If the movie is playing, the pause icon is visible, telling the user they can click to pause. If the movie is paused, the play icon is visible, telling the user they can click to play.
To accomplish this the play/pause button is not a button at all - it is a movie clip. The movie clip has two frames, one frame with the play icon, the other with the pause icon. The frames are then given labels - "pauseon" and "pauseoff". This allows us to dynamically change which frame is currently visible, and therefore the appearance of the play/pause button. Create a movie clip that does all that, then drag an instance of it to the stage and give it the instance name of "pause_mc". Then add the following code to the first key frame in the root timeline with the rest:
video_ns.onStatus = function() {
if (video_ns.time >= duration-1){
playstatus = 2;
_root.pause_mc.gotoAndStop("pauseon");
}
else
{
playstatus = 1;
_root.pause_mc.gotoAndStop("pauseoff");
}
}
The code above uses a change in the NetStream status to trigger a check. The code checks whether the current position within the FLV file is greater than or equal to 1 second from the end of the file. If so it sets the value of the playstatus variable to "2" (we use this later), and tells the play/pause button to move to the frame labelled "pauseon", so the button shows the pause icon, telling the user they can click to pause.
If the current position within the FLV file shows there is more than 1 second of the movie left to play, then the code sets the value of the playstatus variable to "1", and tells the play/pause button to show the frame labelled "pauseoff", so the button shows the play icon, telling the user they can click to play.
the above code just sets the playstatus variable, and changes the visual appearance of the play/pause button. Now we need to enter the code that actually controls the playing and the pausing. Add the following code to the first key frame in the root timeline with the rest:
_root.pause_mc.onRelease = function () {
if (playstatus == 1)
{
video_ns.pause();
_root.pause_mc.gotoAndStop("pauseoff");
}
else if (playstatus == 2)
{
video_ns.play(currentvid);
}
}
This is where lots of the variables we have been setting earlier, with no visible purpose, suddenly become useful. The code above runs whenever the play/pause button is released.
First it checks the value of the playstatus variable. If the value of playstatus is "1" (which means the FLV file has more than 1 second left to play - see above), then it tells the NetStream object called "video_ns" to pause, and tells the play/pause button to show the frame labelled "pauseoff", so the button shows the play icon, telling the user they can click to play again.
If the value of playstatus is "2" (which means the FLV file is in its last second of playback - see above), then it tells the NetStream object called "video_ns" to play the FLV file again, and uses thevalue of the currentvid variable, which was set when the user click the button to select which video they wanted to see, to tell it which FLV file that was. This currentvid reminder is needed because we are playing FLV files and so must use NetStream and not loadmovie as we would if we were playing SWF files. With loadmovie the SWF file remains loaded into memory and so the program does not need reminding which movie to play because it still has it, with NetStream the file is streamed from its location and not kept in memory - this is why the currentvid variable was needed, to remind the program which FLV to play, without the user having to select it again using one of the video selector buttons we created right at the beginning. This is all about making it work more smoothly for the user - trying to make it work how they expect, rather than expecting them to learn the quirks of how your's works.
Progress Bar
No video player is complete without a progress bar telling the user how quickly the video is progressing, where they are in the video timewise, and how long is left.
To create the progress bar graphics, draw a rectangle on the stage to represent the video progress bar. Make sure the rectangle has a fill and a stroke. Then select the filled area only, press F8 and convert it into a movieclip called progbar. Make sure you set the registration point of the symbol to be top left. Then select the stroke that outlined the rectangle, again press F8 and convert it into a movieclip called progbarframe. Again make sure you set the registration point of the symbol to be top left. Give each an instance names "progbar_mc" and
"progbarframe_mc".
Add the following code to the first key frame in the root timeline with the rest:
onEnterFrame = function() {
comppc = video_ns.time / duration;
_root.progbar_mc._width = _root.progbarframe_mc._width*comppc;
}
The above code sets a variable called comppc with a value that comes out of dividing the current position of the FLV movie in seconds with the duration of the movie in seconds. This gives comppc a a value between 0 and 1. A value of 0.5 would mean the movie was half way through. We then multiply the maximum width of the progress bar (based on the width of the progbarframe_mc) by the value of comppc to set the current width of the progress bar. By using onEnterFrame the progress bar updates several times per second as the movie plays, thus giving an accurate graphical representation of how far the movie has to go.
Progress Bar Jumper
Now we want to make it so the user can click anywhere on the progress bar and jump to that part of the movie. Add the following code to the first key frame in the root timeline with the rest:
_root.progbarframe_MC.onRelease = function() {
barleft = _root.progbarframe_MC._x;
jumppos = (_xmouse-barleft)/_root.progbarframe_MC._width;
if (playstatus == 1)
{
video_ns.seek(Math.round(jumppos*duration));
}
else if (playstatus == 2)
{
video_ns.play(currentvid);
video_ns.seek(Math.round(jumppos*duration));
}
}
The above code is probably the most complex part of the whole program. Funny how the luxuries, the "optional extras", that provide the least functionality are often the most complicated parts of the program.
First we define a variable for the left side of theprogress bar called barleft. This gives us a zero point against which to measure the location of the user's click on the progress bar. Then we define a variable that represents the users click on the progress bar called jumppos.
The value of jumppos is defined by getting the X coordinate of the mouse when the bar is clicked and then subtracting from that the value of barleft (the X coordinate of the the start of the bar). This tells us how far along the bar the user clicked. This number is then divided by the total width of the bar to give a number that represents how far along the bar the user clicked as a value between 0 and 1. A result of 0.5 would mean the user clicked in the middle of the bar.
We then tell the NetStream object to seek to the point in the movie corresponding to where the user clicked on the bar. This is calculated by multiplying the value of jumppos (where on the bar the user clicked) by the value of the duration of the FLV file in seconds. However, I have also used Math.round to convert the result into an integer (by rounding up or down to the nearest whole number). This just helps keep things tidy and means the FLV will jump to a whole second, rather than a fraction of a second which may not exist.
If the value of playstatus is "1" then we just attempt to seek straight to the relevant point in the FLV file. However if the playstatus is "2" this means there is only 1 second or less of the movie to go, so to make sure it works and we get no glitches, we tell the NetStream object to play the currentvid from the beginning and then seek to the relevant point in the FLV file. We have to do this because, as mentioned before, with NetStream the video is not stored in memory, and so if there is less than 1 second left in the video, the streaming might be over before Flash has a chance to seek to another part of the movie. By telling the video to start again using the currentvid variable to remind it which video, and then seek to the relevant point, we can get a smoother operation.
Converting Video to FLV Format
Of course, for this player to be any use, you need to be able to convert your video to FLV format.
One programme that has worked for me without trouble is Free Video to Flash Converter.
It is completely freeware and can convert video into SWF or FLV. You can even export video with its own player interface - and, while this defeats the object for my use of it, since I wanted a custom interface of my own design, some people may find this feature helpful.
The program is pretty self explanatory, all you need to do is remember to export the movie as a FLV and save it with the name you programmed into your player and in the same directory as the player.
The End
And there we have it. Export your player as a SWF into the same directory as the FLV files you linked to and it should just work. Any problems, leave a comment and I will try to help.
Although both programs are fine, FLV is much the up-to-date way of showing video in Flash so I hope you find this useful. feel free to leave comments or questions.
Getting Started
To keep things organised I like wherever possible to keep all my code in one place. All the ActionScript in this tutorial should be attached to the first key frame in your movie.
Unlike the version of the video player that played SWF movies, we cannot use loadmovie to simply show a movie within a movie. FLV files require us to use NetConnection and then NetStream to stream the FLV file from its location.
First off then we need to create a new NetConnection called "myConnection_nc":
var myConnection_nc:NetConnection = new NetConnection();
myConnection_nc.connect(null);
Now we need to create a NetStream called "video_ns" that will stream through the NetConnection you made above:
var video_ns:NetStream = new NetStream(myConnection_nc);
Now we have created a NetConnection and a NetStream through which we will stream the FLV file, we need to create a video object on the stage through which the FLV will be displayed.
First, you need to create a new Embedded Video object in the library. To do this, click the little menu in the corner at the top of the Library and select the "New Video" option. It should appear in the Library as "Embedded Video 1". Then drag an instance of the Embedded Video 1 onto the stage and give it the instance name of "my_video".
Now we are ready to attach the NetStream created above to the video object you just placed on the stage called "my_video":
my_video.attachVideo(video_ns);
Now we need to do two things. First, we need to find out how long the FLV file is (its duration), second we need to set the value of the duration variable equal to the property of the duration object. This will allow us to control the playback of the FLV later on.
To do this we first use prototype.OnMetaData to find the duration of the video - this only works with FLV 1.1 files and later, earlier versions do not include duration in metadata.
Unfortunately there is no other way of finding the duration of an FLV file (you can't use the _totalframes method like you can in SWF files).
Then we can set the value of the duration variable to be equal to the duration property of the FLV file as defined in the FLV's MetaData. Here goes:
NetStream.prototype.onMetaData = function(obj){
var duration = obj.duration;
}
Video Selector
Now for the playback controls. The simplest control is the video selector. This allows the user to choose which video they want to watch.
First create a button in the Library, then drag two instances of the button onto the stage. Give the buttons the following instance names - "m1_btn" and "m2_btn".
Because we are playing FLV files and not SWF files, we cannot use the loadMovie method. Instead we need to tell the NetStream object we created earlier, to play and tell it which FLV file to play. We create code for each of the buttons we created earlier, so that when each is clicked, the NetStream object we created streams a different FLV file to the video object:
_root.m1_btn.onRelease = function () {
video_ns.play("video2.flv");
currentvid = "video2.flv";
}
_root.m2_btn.onRelease = function () {
video_ns.play("video1.flv");
currentvid = "video1.flv";
}
The code above does two things when the button is released. First, it tells the NetStream object called "video_ns" to play a specified FLV file. Secondly it sets the value of a variable called currentvid to be the same as the name of the FLV file - this helps us later on when we are programming the playback controls.
Rewind Button
Dead easy. Create a button in the Library that looks like a rewind icon. Drag an instance of the button onto the stage and give it the instance name of "rw_btn". Then add the following code to the first key frame with the rest:
_root.rw_btn.onRelease = function () {
playpos = video_ns.time;
if (playpos > 10)
{
video_ns.seek(playpos-10);
}
else
{
video_ns.seek(0);
}
}
The code above makes the video jump back 10 seconds when the rewind button is clicked. It might seem pretty complex considering that all we want to do is rewind a bit. What it actually does first is check how far into the video we have progressed and the reason for this is that we don't want to jump back to a point before the video starts, that would be impossible. Depending on how far the video has played the code then does one of two things. If the video has played more than 10 seconds, then it tells the NetStream object to jump back 10 seconds in the FLV, if the video has not yet been playing for more than 10 seconds it tells the NetStream object to go back to the beginning of the FLV.
I found that in practice, with large FLV files, the rewind is not always reliable, and can get "stuck" at points, refusing to rewind past them. I suspect this is something to do with the FLV itself, rather than the coding - however, I have also included the option of clicking on the progress bar to jump to any point in the video, which so far has proved very reliable - this is explained later in the tutorial.
NOTE: If you made the previous video player that used SWF instead of FLV files, you will notice that we are using a lot of different methods. Most significant is that with FLV we cannot gotoAndPlay specific frames as we can with SWF files. Instead we use the seek method, and it is the NetStream object called "video_ns" that we are instructing to seek, not the video instance on the stage.
Forward-wind
This is much more straightforward. As before, create a button in the Library that looks like a forward-wind icon. Drag an instance of the button onto the stage and give it the instance name of "fw_btn". Then add the following code to the first key frame with the rest:
_root.fw_btn.onRelease = function () {
playpos = video_ns.time;
video_ns.seek(playpos+10);
}
This isn't nearly as complex. When the forward-wind button is released the code sets the value of a variable playpos to the current time position of the movie using video_ns.time. It then simply uses the seek method to tell the NetStream object to jump forward 10 seconds from the current time position in the FLV.
Play and Pause Button
Now we get more complex. For my player I opted to have the Play and Pause buttons be the same button, but have the icon on the button change depending on whether the movie is playing or not. If the movie is playing, the pause icon is visible, telling the user they can click to pause. If the movie is paused, the play icon is visible, telling the user they can click to play.
To accomplish this the play/pause button is not a button at all - it is a movie clip. The movie clip has two frames, one frame with the play icon, the other with the pause icon. The frames are then given labels - "pauseon" and "pauseoff". This allows us to dynamically change which frame is currently visible, and therefore the appearance of the play/pause button. Create a movie clip that does all that, then drag an instance of it to the stage and give it the instance name of "pause_mc". Then add the following code to the first key frame in the root timeline with the rest:
video_ns.onStatus = function() {
if (video_ns.time >= duration-1){
playstatus = 2;
_root.pause_mc.gotoAndStop("pauseon");
}
else
{
playstatus = 1;
_root.pause_mc.gotoAndStop("pauseoff");
}
}
The code above uses a change in the NetStream status to trigger a check. The code checks whether the current position within the FLV file is greater than or equal to 1 second from the end of the file. If so it sets the value of the playstatus variable to "2" (we use this later), and tells the play/pause button to move to the frame labelled "pauseon", so the button shows the pause icon, telling the user they can click to pause.
If the current position within the FLV file shows there is more than 1 second of the movie left to play, then the code sets the value of the playstatus variable to "1", and tells the play/pause button to show the frame labelled "pauseoff", so the button shows the play icon, telling the user they can click to play.
the above code just sets the playstatus variable, and changes the visual appearance of the play/pause button. Now we need to enter the code that actually controls the playing and the pausing. Add the following code to the first key frame in the root timeline with the rest:
_root.pause_mc.onRelease = function () {
if (playstatus == 1)
{
video_ns.pause();
_root.pause_mc.gotoAndStop("pauseoff");
}
else if (playstatus == 2)
{
video_ns.play(currentvid);
}
}
This is where lots of the variables we have been setting earlier, with no visible purpose, suddenly become useful. The code above runs whenever the play/pause button is released.
First it checks the value of the playstatus variable. If the value of playstatus is "1" (which means the FLV file has more than 1 second left to play - see above), then it tells the NetStream object called "video_ns" to pause, and tells the play/pause button to show the frame labelled "pauseoff", so the button shows the play icon, telling the user they can click to play again.
If the value of playstatus is "2" (which means the FLV file is in its last second of playback - see above), then it tells the NetStream object called "video_ns" to play the FLV file again, and uses thevalue of the currentvid variable, which was set when the user click the button to select which video they wanted to see, to tell it which FLV file that was. This currentvid reminder is needed because we are playing FLV files and so must use NetStream and not loadmovie as we would if we were playing SWF files. With loadmovie the SWF file remains loaded into memory and so the program does not need reminding which movie to play because it still has it, with NetStream the file is streamed from its location and not kept in memory - this is why the currentvid variable was needed, to remind the program which FLV to play, without the user having to select it again using one of the video selector buttons we created right at the beginning. This is all about making it work more smoothly for the user - trying to make it work how they expect, rather than expecting them to learn the quirks of how your's works.
Progress Bar
No video player is complete without a progress bar telling the user how quickly the video is progressing, where they are in the video timewise, and how long is left.
To create the progress bar graphics, draw a rectangle on the stage to represent the video progress bar. Make sure the rectangle has a fill and a stroke. Then select the filled area only, press F8 and convert it into a movieclip called progbar. Make sure you set the registration point of the symbol to be top left. Then select the stroke that outlined the rectangle, again press F8 and convert it into a movieclip called progbarframe. Again make sure you set the registration point of the symbol to be top left. Give each an instance names "progbar_mc" and
"progbarframe_mc".
Add the following code to the first key frame in the root timeline with the rest:
onEnterFrame = function() {
comppc = video_ns.time / duration;
_root.progbar_mc._width = _root.progbarframe_mc._width*comppc;
}
The above code sets a variable called comppc with a value that comes out of dividing the current position of the FLV movie in seconds with the duration of the movie in seconds. This gives comppc a a value between 0 and 1. A value of 0.5 would mean the movie was half way through. We then multiply the maximum width of the progress bar (based on the width of the progbarframe_mc) by the value of comppc to set the current width of the progress bar. By using onEnterFrame the progress bar updates several times per second as the movie plays, thus giving an accurate graphical representation of how far the movie has to go.
Progress Bar Jumper
Now we want to make it so the user can click anywhere on the progress bar and jump to that part of the movie. Add the following code to the first key frame in the root timeline with the rest:
_root.progbarframe_MC.onRelease = function() {
barleft = _root.progbarframe_MC._x;
jumppos = (_xmouse-barleft)/_root.progbarframe_MC._width;
if (playstatus == 1)
{
video_ns.seek(Math.round(jumppos*duration));
}
else if (playstatus == 2)
{
video_ns.play(currentvid);
video_ns.seek(Math.round(jumppos*duration));
}
}
The above code is probably the most complex part of the whole program. Funny how the luxuries, the "optional extras", that provide the least functionality are often the most complicated parts of the program.
First we define a variable for the left side of theprogress bar called barleft. This gives us a zero point against which to measure the location of the user's click on the progress bar. Then we define a variable that represents the users click on the progress bar called jumppos.
The value of jumppos is defined by getting the X coordinate of the mouse when the bar is clicked and then subtracting from that the value of barleft (the X coordinate of the the start of the bar). This tells us how far along the bar the user clicked. This number is then divided by the total width of the bar to give a number that represents how far along the bar the user clicked as a value between 0 and 1. A result of 0.5 would mean the user clicked in the middle of the bar.
We then tell the NetStream object to seek to the point in the movie corresponding to where the user clicked on the bar. This is calculated by multiplying the value of jumppos (where on the bar the user clicked) by the value of the duration of the FLV file in seconds. However, I have also used Math.round to convert the result into an integer (by rounding up or down to the nearest whole number). This just helps keep things tidy and means the FLV will jump to a whole second, rather than a fraction of a second which may not exist.
If the value of playstatus is "1" then we just attempt to seek straight to the relevant point in the FLV file. However if the playstatus is "2" this means there is only 1 second or less of the movie to go, so to make sure it works and we get no glitches, we tell the NetStream object to play the currentvid from the beginning and then seek to the relevant point in the FLV file. We have to do this because, as mentioned before, with NetStream the video is not stored in memory, and so if there is less than 1 second left in the video, the streaming might be over before Flash has a chance to seek to another part of the movie. By telling the video to start again using the currentvid variable to remind it which video, and then seek to the relevant point, we can get a smoother operation.
Converting Video to FLV Format
Of course, for this player to be any use, you need to be able to convert your video to FLV format.
One programme that has worked for me without trouble is Free Video to Flash Converter.
It is completely freeware and can convert video into SWF or FLV. You can even export video with its own player interface - and, while this defeats the object for my use of it, since I wanted a custom interface of my own design, some people may find this feature helpful.
The program is pretty self explanatory, all you need to do is remember to export the movie as a FLV and save it with the name you programmed into your player and in the same directory as the player.
The End
And there we have it. Export your player as a SWF into the same directory as the FLV files you linked to and it should just work. Any problems, leave a comment and I will try to help.
Labels:
actionscript,
as2,
Flash,
flv,
interactive media,
movieclip,
player,
progress bar,
video
Saturday, 16 February 2008
Flash Projects - #2 - Converting Video to SWF
The video player you created in the last tutorial allows the user to select and control the playback of video files in SWF format (not FLV format).
The reason for this, as I mentioned at the introduction of the last tutorial, was because I wanted to have a video player that worked with the features of Flash MX 2004 standard (which lacks the additional video capability of MX 2004 Professional).
One of the limitations with the standard version of Flash was that it could only encode video to be embedded in the timeline; this would then be exported in SWF format (not FLV).
Note: Freeware applications for converting video to FLV however have become more commonplace, so I have already begun work on a player that uses the netconnect and netstream capabilities of Flash to play FLV videos instead. Look out for this tutorial in a few weeks. Meanwhile...
So how do you encode video to SWF?
You can use Flash to encode video to SWF or some available freeware.
The Flash method
If you have Flash you can do it very easily by choosing File > Import > Import Video.
Flash MX 2004 standard will only encode video to be emdedded into the timeline, Professional and later versions give more options - make sure you select the option that embeds video into the timeline.
Work your way through the wizard and when the video has encoded, make sure the document size (and the video) are the right size for your player (see previous tutorial).
Then export the movie as a SWF and save it with the name you programmed into your player and in the same directory as the player.
All done. However I tend to find that Flash takes an excessively long time over encoding video, and sometimes prefer to use a freeware programe that seems a bit quicker.
The freeware method
One programme that has worked for me without trouble is Free Video to Flash Converter.
It is completely freeware and can convert video into SWF or FLV. You can even export video with its own player interface - and, while this defeats the object for my use of it, since I wanted a custom interface of my own design, some people may find this feature helpful.
The program is pretty self explanatory, all you need to do is remember to export the movie as a SWF and save it with the name you programmed into your player and in the same directory as the player.
And thats it. Again any problems just leave a comment and I will try to help.
The reason for this, as I mentioned at the introduction of the last tutorial, was because I wanted to have a video player that worked with the features of Flash MX 2004 standard (which lacks the additional video capability of MX 2004 Professional).
One of the limitations with the standard version of Flash was that it could only encode video to be embedded in the timeline; this would then be exported in SWF format (not FLV).
Note: Freeware applications for converting video to FLV however have become more commonplace, so I have already begun work on a player that uses the netconnect and netstream capabilities of Flash to play FLV videos instead. Look out for this tutorial in a few weeks. Meanwhile...
So how do you encode video to SWF?
You can use Flash to encode video to SWF or some available freeware.
The Flash method
If you have Flash you can do it very easily by choosing File > Import > Import Video.
Flash MX 2004 standard will only encode video to be emdedded into the timeline, Professional and later versions give more options - make sure you select the option that embeds video into the timeline.
Work your way through the wizard and when the video has encoded, make sure the document size (and the video) are the right size for your player (see previous tutorial).
Then export the movie as a SWF and save it with the name you programmed into your player and in the same directory as the player.
All done. However I tend to find that Flash takes an excessively long time over encoding video, and sometimes prefer to use a freeware programe that seems a bit quicker.
The freeware method
One programme that has worked for me without trouble is Free Video to Flash Converter.
It is completely freeware and can convert video into SWF or FLV. You can even export video with its own player interface - and, while this defeats the object for my use of it, since I wanted a custom interface of my own design, some people may find this feature helpful.
The program is pretty self explanatory, all you need to do is remember to export the movie as a SWF and save it with the name you programmed into your player and in the same directory as the player.
And thats it. Again any problems just leave a comment and I will try to help.
Subscribe to:
Posts (Atom)
