Friday 27 February 2009

Dodgy play/pause button? Try this...

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.

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"

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.

Consider solutions

There are several ways we can tackle this problem, such as:

  1. 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.
  2. 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.
  3. 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.
We do the last option.

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.

Wednesday 18 February 2009

Being inspired by historical art and design...

(I have published this article on another of my blogs, so sorry if you have seen it before.)

Too often I hear students moaning that historical sources are boring, uninspiring, and in some cases irrelevant to the world of contemporary graphics. More often than I am comfortable with students would rather study their peers on Deviant Art than their superiors in an art gallery.

While I do understand what my students are saying, from their point of view, I suggest that the problem is not with the historical art, but in our misconceptions about how we think other people's artwork should influence or inspire us.

Take the video for Coldplay's Viva La Vida for example. A fantastic piece of contemporary art & design, packed with modern digital effects, almost totally inspired visually by 19th Century oil paintings.

See if you agree...





Take a close look. You will see animated painterly effects, cracks in the image like the crazing in an old painting, the dress of the performers, the props, the colours and yes, even the lighting, all influenced by oil paintings nearly 200 years old.

Compare the colours and lighting from the video with this portrait of Nelson. The similarities are striking.


Other examples of paintings from the same era follow. Do you see similarities with these too?




As you watch the video you will have seen many visual elements borrowed from paintings like those above. They have taken the visual language of these paintings and used it in the video.

One painting in particular that appears to inspire the video is the one on the cover of the "Death and All His Friends" album. It features a painting entitled "Liberty Leading the People". It was painted in 1830 by Eugène Delacroix in oil on canvas and currently resides in the Louvre museum in Paris. But if you look closely as the video plays, you will notice a lot of the background imagery appears to be either taken from or inspired by this painting (watch out for the red flag imagery, and towards the end, "Liberty" herself).



What is my point? Just because you are asked to find examples of historical art for research does not mean you will have to produce an oil painting. For inspiration you might take colours, texture, lighting, composition, style, story telling, imagery, semiotics, mood, effects... anything you like.

You don't have to feel like you need to be inspired to use the media or technique - though you might be.

Inspiration comes in many ways from many sources. Do you have the eye to look beyond the surface? If you have, you may yet produce great things, original things, that go beyond the graphical fashion of the now.

The Coldplay video proves my point. So look deeper.

Monday 16 February 2009

Where Interactive Media Can Go

Those of you who are old enough may remember back in 1993 a revolutionary new computer game was released - MYST. Back then it used the Mac's hypercard system (you know, the one that might have been a forerunner to the internet if only anyone had realised the potential of linking between stacks on other machines), simple yet effective.

As far as today's interactive media is concerned, the original MYST was pretty low tech. When I consider the simplicity of the original MYST back end it becomes clear that pretty much anyone with an intermediate knowledge of Flash and Actionscript could produce a comparable game today.

What set MYST apart then wasn't the technology, but the creativity with which the technology was used.

And this is what I keep trying to get my students to understand. It isn't all about being able to use the software, loads of people can do that. It is about the thinking, the ideas and the creativity.

That is why we emphasise the design process over the final outcome.

Of course later versions of MYST are a lot more complex than the original in 1993, but the ideas, the thinking and the creativity is still what drives the process, even if the technology has changed.

As demonstrated in this making of video...



The Making Of Myst Iii Exile via Noolmusic.com