Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Monnone

Trying to add a "Poster Image" to VideoLoader

Recommended Posts

I'm having a heck of a time figuring this out. What I have going on basically a video faceoff site. Two video will be pitted against each other and the user will vote for one or the other. Two new videos load up so forth and so on until all the videos have been viewed.

 

I'm pulling the video list from an XML file, adding it to an array and randomizing the order of the array so that I can load the 0 position in the array and then remove from the array, that way it won't load up again.

 

What I'd like to do is add a poster frame to each video node. Ideally I'd like to the video node to contain the JPG because of the fact that I'm randomizing the order and it seems to be easier to associate the JPG with the node that contains the video etc.

 

I can't seem to get the JPG from the XML file to the Stage...lol. Sounds easy I know...maybe I'm missing something??

 

Here is my XML list:

 

<?xml version="1.0" encoding="iso-8859-1"?> 



	scaleMode="proportionalInside" centerRegistration="true" alpha="0" autoPlay="false" posterFrame="georgeStrait.jpg"/>

	scaleMode="proportionalInside" centerRegistration="true" alpha="0" autoPlay="false" posterFrame="iWouldntDoIt.jpg"/>

	scaleMode="proportionalInside" centerRegistration="true" alpha="0" autoPlay="false" posterFrame="jerryJeffWalker.jpg"/>

	scaleMode="proportionalInside" centerRegistration="true" alpha="0" autoPlay="false" posterFrame="cowboyPoet.jpg"/>

	scaleMode="proportionalInside" centerRegistration="true" alpha="0" autoPlay="false" posterFrame="whiteJones.jpg"/>


 

And I'm trying all kinds of things so please excuse the mess:

 

private function init(){
		LoaderMax.activate([xmlLoader, VideoLoader]);
		LoaderMax.activate([imageLoader]);
		xmlLoader = new XMLLoader("xml/videoList.xml", {name:"videoList", onComplete:xmlHandler});
		xmlLoader.load();

		loadNewBtn_mc.addEventListener(MouseEvent.CLICK, loadNewClick);
		loadNewBtn_mc.buttonMode = true;

	 	this.addEventListener("XML Loaded", function(){loadVid1();});
	}

	private function xmlHandler(event:LoaderEvent):void {
		var queue:LoaderMax = LoaderMax.getLoader("videoListLoader");
		var thumbQueue:LoaderMax = LoaderMax.getLoader("videoListLoader");
		//var thumbQueue:LoaderMax = LoaderMax.getLoader("videoListLoader");
		//queueImages.addEventListener(LoaderEvent.COMPLETE, onImagesLoaded, false, 0, true);

		//var images:XMLList = (xmlLoader.content as XML).ImageLoader;
		var images:XMLList = (xmlLoader.content as XML).VideoLoader;
		for each (var image:XML in images) {
			//thumbQueue = LoaderMax.getContent("assets/" + image.@name + ".jpg");
			thumbQueue.append( new ImageLoader("assets/" + image.@name + ".jpg") );
			//_images.push(thumbQueue);
		}

		thumbQueue.load()

		_videos = queue.getChildren();
		_images = thumbQueue.getChildren();
		trace("Images: "+_images+"\n");

		queue.load(); 

		this.dispatchEvent(new Event("XML Loaded"));
	}

 

Any help is seriously appreciated.

 

- Brian

Link to comment
Share on other sites

There are a lot of ways to skin this cat. Just to help you understand how to walk through the XML and find each 's posterFrame attribute, here's some code:

function completeHandler(event:LoaderEvent):void {
var thumbsQueue:LoaderMax = new LoaderMax({name:"thumbsQueue"});
var xml:XML = event.target.content;
var videoNodes:XMLList = xml.LoaderMax[0].VideoLoader;
for each (var node:XML in videoNodes) {
	trace("found  node named "+node.@name + ". Poster frame: " + node.@posterFrame);
	thumbsQueue.append( new ImageLoader("assets/" + node.@posterFrame) );
}
thumbsQueue.load();
}

 

However, you could simplify it a bit and just leverage XMLLoader's ability to do all the parsing for you like this:

 

function completeHandler(event:LoaderEvent):void {
var thumbsQueue:LoaderMax = new LoaderMax({name:"thumbsQueue"});
var videoQueue:LoaderMax = LoaderMax.getLoader("videoListLoader"); //finds the  that you had in your XML
var loaders:Array = videoQueue.getChildren(); //gets an array of all the child VideoLoaders
for (var i:int = 0; i 		thumbsQueue.append( new ImageLoader("assets/" + loaders[i].vars.posterFrame, {container:this, x:i * 50}) );
}
thumbsQueue.load();
}

This will load all the thumbnails, add them to the stage and space them 50 pixels apart starting at 0. Obviously you'll need to adjust the x position (and probably add a y position too), but hopefully this gives you the idea. You could, of course, addChild() each one manually if you prefer.

 

Does that help?

Link to comment
Share on other sites

Thanks Jack...let me check this out. I'll get back.

 

Brian

Link to comment
Share on other sites

Thanks for the help so far. How would I integrate the videos now? I have the images tracing back perfectly but I need the videos to get loaded into that same queue, "thumbsQueue" or just "queue". I can successfully get the videos this way:

 

var queue:LoaderMax = LoaderMax.getLoader("videoListLoader");
queue.load();
_videos = queue.getChildren();

 

I then send the array, "_videos" into a randomizer and then through the videoPlayer class. But I need the videos AND the images to get randomized and then sent to the videoPlayer class and the video class will handle loading the appropriate poster frame based on the random results. Man, I hope that makes sense. I'm new to your Loading classes and am really trying to understand...

 

Thanks in advance,

brian

Link to comment
Share on other sites

I'm not sure I understand your question. Do you need to know how to load() one of the videos? Are you asking for help randomizing them? Is it more about how to randomize two arrays in the same way so that their indexes match?

 

I'm not familiar with your particular project but if I were you, I'd probably create a separate class like Video or VideoAsset (or whatever you want to name it) that holds the information for each video. It would have a "video" property that you'd set to the appropriate VideoLoader and a "thumbnail" property that you'd set to the appropriate ImageLoader instance. And there's probably other info you want to track for each video too (name, rollover/out/click handlers, etc.) which would make things nice and tidy. So you'd create an instance of your VideoAsset for each video and dump those into an array that you'd randomize. That way you can grab one and get its VideoLoader or ImageLoader or whatever. It's cumbersome to try tracking ImageLoaders in one array and VideoLoaders in another and associate them by their indexes, especially when you need to randomize them.

 

Make sense? Did I answer the question or totally miss it?

Link to comment
Share on other sites

Thanks for the follow up. I have my methods and video class in place already, etc and it works. What I'm looking for is how do I pass the array of videos along with the poster frames back into the video class. I'll handle displaying the appropriate image in the video class. Your code only addresses the images but not the videos. I've tried different thing but get errors.

 

For example is I do this:

 

var queue:LoaderMax = LoaderMax.getLoader("videoListLoader");
queue.load();
_videos = queue.getChildren();

 

I can tap into the videos but not the images. If I do this:

 

var thumbsQueue:LoaderMax = new LoaderMax({name:"thumbsQueue"});
var xml:XML = event.target.content;
var videoNodes:XMLList = xml.LoaderMax[0].VideoLoader;
for each (var node:XML in videoNodes) {
thumbsQueue.append( new ImageLoader("assets/" + node.@posterFrame) );
}

thumbsQueue.load();
_images = thumbsQueue.getChildren();

 

I get the list of images but not videos. I've tried to include both but get errors. I'm sure this is something simple I'm missing. I need both images AND videos be be included into one array so I can pass the array in the randomize function together. Sounds so simple but I'm scratching my head...

 

Thanks again!

brian

Link to comment
Share on other sites

I tried this too:

 

var thumbsQueue:LoaderMax = new LoaderMax({name:"thumbsQueue"});
var xml:XML = event.target.content;
var videoNodes:XMLList = xml.LoaderMax[0].VideoLoader;
for each (var node:XML in videoNodes) {
thumbsQueue.append( new ImageLoader("assets/" + node.@posterFrame) );
thumbsQueue.append( new VideoLoader("assets/" + node.@url) );
}

thumbsQueue.load();

_images = thumbsQueue.getChildren();
trace("Images: "+_images+"\n");

 

And when I pass that into the video class all the video play at one time where before it would only load the videos and I would allow them to play based on a button click.

Link to comment
Share on other sites

The reason they all played at once with that code is because by default autoPlay is true - you didn't set it to false when you created your VideoLoaders inside your loop.

 

I actually was trying to answer your question about the array with my last post, but maybe I didn't explain it well enough. Before I try again, let me make sure I understand what you're asking. You said you wanted the ImageLoaders AND the VideoLoaders in ONE array, right? So do you want the VideoLoaders first, then the ImageLoaders? Like if there are 10 VideoLoaders and 10 ImageLoaders, your array would have 20 elements - would the first 10 be videos and the last 10 be images? Or should it be every other one? Help me understand exactly what you're after with the array. Like I tried to explain in the previous post, I think that's a poor way to engineer this, but I don't want to overstep my bounds (you're not asking my opinion about structure, you're asking something specific about an array).

Link to comment
Share on other sites

Well, I'm certainly open to suggestions on how I need to get this done using your classes. Let me see if I can recap what I'm trying to do in the most simplest terms.

 

I have two videos that will play side by side. The user will click a vote button for the video of their choice. A new set of videos will load after the user votes, etc., etc. I'll PM you a link to the working test project so far.

 

You are 100% correct in that I don't want to over engineer this. I'd like to handle this the right way.

 

The bottom-line is that I need to have a poster image that gets displayed for each video until the user actually clicks the video to play it. On video play, the poster image would fade away, user eventually votes, etc, etc for about 36 videos. I have an XML file for the videos, I randomizing the video array, pull the first item in the array and then load it up it via the video class. I'm then and shifting out that first position in the randomized array to remove it, randomizing it again and loading in a new video into that first position. This way I won't ever play the same videos again...once they are seen, they are no longer available in the array list.

 

Recap:

 

_video array gets randomized, load item 0 into vid class, play when clicked, vote happens, shift first item from array on vote- rinse and repeat.

 

I have this working. I'm sure it could be coded better but I'm still a bit wet behind the ears with AS3 on OOP. Seems like I'm forever learning...

 

So, here's what I feel like I need to happen on this poster image business: Since I'm randomizing my videos, albeit through an array or whatever, a poster image needs to be associated with each video. My thought was to add a node to the XML item: posterFrame="posterImageBlah.jpg" for example. Pass my loader array (or video array, I'm not sure what it is actually), "_video" into my video player class and let the video player class load the poster image, etc. and then carry on like it's currently working.

 

Again, you are right, currently I'm getting the videos AND the images listed in the array as separate items, which is not what I need.

 

Hopefully I've explained it enough. Again, thank you very much for any help you can provide. I absolutely love your Tween classes and talk them up when ever I can...keep up the fantastic work Jack.

 

Brian

Link to comment
Share on other sites

Yep, that sounds pretty much like what I was expecting. So I just did a poor job of explaining the concept of what I was suggesting. I'll take another crack at it:

 

You have two pieces of information associated with each video that will be viewed (well, 2 that we care about right now): the video (flv) and the thumbnail image (jpg). Procedural programmers (old school, non-OOP) would think "I'll just create two arrays, one for the videos and one for the thumbnails". Technically that could work, as long as we make sure the order matches in each (_thumbs[0] is goes with _videos[0], etc.). But what about randomizing the array? Doh! Now that gets trickier and exposes the weakness in this style of coding. You must implement a bunch of extra logic to make sure both arrays stay synchronized. Ugly and error-prone.

 

Object Oriented Programming (OOP) gives us a much better way of approaching this problem. We can create an object for each video that has two properties - "thumbnail" and "video", thus consolidating the flv and jpg data into one object. Then we put that into our array that can be randomized however we want - we never have to worry about synchronization problems anymore. Here's a simple example using a generic object (I'll explain a better, more formal way later):

 

var _videos:Array = [];
var queue:LoaderMax = LoaderMax.getLoader("videoListLoader");  //from your XML
var loaders:Array = queue.getChildren();
for (var i:int = 0; i     var obj:Object = new Object();
   obj.video = loaders[i];
   obj.thumbnail = new ImageLoader("assets/" + loaders[i].vars.posterFrame);
   _videos.push(obj);
}
//then randomize _videos however you want
//to play the first video, it would be as simple as:
_videos[0].video.playVideo();

//to load the thumbnail, you'd do:
_videos[0].thumbnail.load();

//add it to the stage like:
addChild(_videos[0].thumbnail.content);

 

The more formal (and better) way to handle that object is to create a custom class. For example:

 

package {
    public class VideoAsset {
       public var video:VideoLoader;
       public var thumbnail:ImageLoader;

       public function VideoAsset(video:VideoLoader, thumbnail:ImageLoader) {
           this.video = video;
           this.thumbnail = thumbnail;
       }
   }
}

 

Then we can use it in our code like this:

 

var _videos:Array = [];
var queue:LoaderMax = LoaderMax.getLoader("videoListLoader");  //from your XML
var loaders:Array = queue.getChildren();
for (var i:int = 0; i     _videos.push( new VideoAsset(loaders[i], new ImageLoader("assets/" + loaders[i].vars.posterFrame) );
}

 

You could, of course add rollover/out/click logic to your VideoAsset class very easily so that all videos have the same behavior. It centralizes your code.

 

Is this making sense now? I could show you a quick and dirty way of accomplishing what you're after with your existing architecture, but I'm resisting that because I'm trying to nudge you in a direction that I think you'll find serves you better and makes things easier.

Link to comment
Share on other sites

Man, awesome. Let me take a look...

 

Also, my AS3 is coming along nicely but the more I get into it the more I want/need to do! Vicious circle...and any nudging you provide is well received!

Link to comment
Share on other sites

I have everything working like a charm. Thanks so much for your help!

 

Also, since I'm not at the agency anymore and working for myself it might be time to grab my personal license...

 

Thanks for your hard work Jack!

 

Brian

Link to comment
Share on other sites

Fantastic! Glad to hear you got everything working well.

 

Enjoy the tools. And good luck on your project.

Link to comment
Share on other sites

Hey Jack, everything was bumping right along then I discovered another issue. The way I have things setup right now ALL the videos load at once. This is problematic because of the randomization of the array. I'd like only the first two videos to load when called upon, vote, then next two videos will load.

 

I checked my web proxy while on my test site and sure enough, all the videos are loading at once. So if the randomization calls for the very last video the user will have to wait quite a while to play the video while all the previous videos load.

 

According to Charles, my web debugging proxy, all the videos are loading. I imagine this is expected because I'm doing this:

 

queue.load();

 

I guess I don't want to load them like this. So how do I tell the video class which video to load? I see with the poster frames we did this:

 

addChild(_videos[0].thumbnail.content);

 

Which works great for the images because I'm handling that without a separate class. And I see you gave me the example code:

 

_videos[0].video.playVideo();

 

but how would I pass that into the vid class? Also, I don't need to change the priority of the loading video as there will only be two at a time.

 

Also, currently initiating the video to load into the two players like:

 

vidPlayer1_mc.showVideo(_videos[0].video);

 

Where showVideo is a method in the video class that handles most of everything.

 

I've updated the link I PM'd you as well, just in case.

 

Thanks so much!

Brian

Link to comment
Share on other sites

Well, I figured it out. If you're curious, and probably already know the answer...

 

Instead of loading all the videos in one shot in the doc class with: queue.load();

 

I'm handling loading of each video individually in the video class itself. In the video class, "video" is a VideoLoader so it was as simple as saying: video.load();

 

Done.

 

:shock:

 

Brian

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×