I'm building a narrative click-through kiosk app in Flash/AS3. Currently, there are several (10+) locally loaded .flv files that I'm loading into an FLVPlayback component on the timeline. I am experiencing loading delays and am wondering what the best practice / best case scenario for this case. These are all using the "Load external video with playback component" option for Video importing.
So far I've tried implementing it two ways:
One frame, one FLVPlayback playback on the stage named "video_player", and upon the click through / user action to switch the video, I do the following:
var new_flv:String = "next_flv.flv";
video_player.stop();
video_player.source("_flvs/"+new_flv);
video_player.seek(0);
video_player.play();
This results in delays anywhere from a few seconds to 10 seconds.
This is unconventional to me, but I used multiple frames on the timeline. Each frame had an FLVPlayback instance on the stage, each with a different relative path placed in the 'source' property in the component parameters (see http://www.ashleylovespizza.org/stuff/flv_example.png ). The code is switching between frames based on frame label and then hitting play (autoplay is off in the component parameters as well).
var new_flv_frame_name:String = "next_frame";
this.gotoAndStop(new_flv_frame_name);
this.video_player.play();
The issue, again, is that loading is taking a long time. What could prevent this behavior? One long flv that I seek() to different moments of time on the playhead? Can I preload in a separate FLVPlayback instance, similar to double buffering?
Any tips or best practices are appreciated.
Although you have not told me where the flv files are being loaded from (locally or remote), and as you have said you are building a kiosk style app, I am going to go out on a limb here and say that you should almost certainly use Adobe AIR for a kiosk app.
There is no reason for creating more than one FLVPlayback instance, its capable of playing multiple videos using getVideoPlayer(index), its up to you to manage the streams by calling close() on them.
If you are loading files remotely, then using Adobe AIR you can download each video to a local folder using the FileStream class. This will speed up the process of playing back these files.
Related
I have created a menu for my game with buttons and whatnot as a separate .fla file named Menu. My actual game is another .fla file called Game.fla. I was wondering what the best way would be of loading this menu before the game plays?
Thanks.
I would suggest that you create a .swc with your Menu.fla, and then just add that .swc to your Game.fla
If you are using CS6, make sure that you are setting linkage for any MovieClips you want to create instances of in your code.
In the actionscript settings on the library path tab, you can add a .swc that will be included into your .swf when compiling.
In your code, you can now create an instance and add to the display list :
// Assuming MainMenu was a movieclip with linkage set in your .swc
var mainMenu:MainMenu = new MainMenu;
addChild(mainMenu);
I should note that this does not load the .swc at runtime, it includes the .swc to your .swf at compile time. I would recommend this method over loading a .swf in most cases. Cases where I might not, is if there was a large amount of content that wasn't needed all at once. That would allow you to minimize the amount of memory you were using and reduce the .swf size of your main .swf so it loads quicker.
Anytime you are loading .swf's in at runtime you are adding another layer of complexity, so I'd not recommend it unless you do have a good reason to do so. From what you have described, this doesn't sound like a situation where I'd load an external .swf at runtime.
Load the swf output from Menu.fla and keep a check on the progressEvent from loader. Don't show the game screen until Menu.swf is completely loaded and initialized.
Some more details wrt comment from OP:
You can you http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Loader.html#load%28%29 to load external swfs. init Event would mark that the swf's actionscript has started executing. OTOH, complete event would tell that all the swf bytes have been loaded.
public var swfLoader:SWFLoader = new SWFLoader();
[Embed(source="/some/file1.swf")]
public var file1:Class;
[Embed(source="/some/file2.swf")]
public var file2:Class;
then I do:
swfLoader.load(file1);
Later on:
swfLoader.unloadAndStop(true);
which unloads the video, but not the sound! So I add in
SoundMixer.stopAll();
Which is ok, for a while. Later on, I do:
swfLoader.load(file2);
And eventually, while watching file2, file1's audio will start playing in the background over file2's audio, with no way to stop it! What is the proper way to stop the audio of file1? The way I keep seeing is use unloadAndStop() which I am using. Unless I have to create a new swfLoader object each time?
As per Konrad's answer below, I should stop playing the sound in cleanup events, such as REMOVED_FROM_STAGE, however, how can I stop playing the sound on a swf file that is loaded with a SWFLoader? I don't see an obvious way to do that.
Solutions is bit tricky, because problem is with loaded content.
Garbage collector won't remove sound because it is still playing (so its referenced by Flash Player) but you don't have access to its sound channel (because its hidden similar to private variables in classes). That behavior is totally correct.
Solution: In loaded swf code you should stop playing that sound (in REMOVED_FROM_STAGE or other 'cleanup' event handler). Other solutions (like SoundMixer.stopAll) will work in some cases but not in all.
We often forget to clean after ours applications. Its not problem if they exist same as instance of Flash Player (removing it will clean all memory used by our swf). Problems begins when we load and unload swfs. Ignoring cleanups is fast way to memory leaks.
swfLoader.unloadAndStop(true);
Does remove the swf and the sound as well .
Works fine for me .
Even the documentation says :
Unloads an image or SWF file. After this method returns the source property will be null. This is only supported if the host Flash Player is version 10 or greater. If the host Flash Player is less than version 10, then this method will unload the content the same way as if source was set to null. This method attempts to unload SWF files by removing references to EventDispatcher, NetConnection, Timer, Sound, or Video objects of the child SWF file. As a result, the following occurs for the child SWF file and the child SWF file's display list:
Sounds are stopped.
Stage event listeners are removed.
Event listeners for enterFrame, frameConstructed, exitFrame, activate and deactivate are removed.
Timers are stopped.
Camera and Microphone instances are detached
Movie clips are stopped.
So I have run into an issue and I think it is mostly because I haven't worked with as2 in about 5 years so things are pretty hazy. Anyway, my problem is that I need to display PDF files within the flash movie. To do so I have resorted to running SWFTools in my backend and converting pdfs to swf for display. SWFTools, though, outputs AS2 files which I can load into AS3 but I can't actually control (for example, calling stop()).
Thus I have resorted to using an AS2 loader which gets loaded into the AS3 project which is responsible for loading the converted pdf swfs. The problem I am running into is that the listener does not seem to be firing when I load the AS2 file in via AS3 but it fires just fine when run on it's own.
This is the code I am running. To summarize when I run this code on it's own "LOADED" correctly prints to the output and the loaded SWF stops. However, when I run it via an AS3 container the swf loads in correctly but the "LOADED" trace never occurs and the stop is not executed.
thanks so much for any help!
var loader:MovieClipLoader
var listener = new Object();
listener.onLoadComplete = function(loadedClip) {
trace("LOADED");
loadedClip.stop();
}
loadFile("data/testing.swf");
function loadFile(target){
loader = new MovieClipLoader();
loader.addListener(listener);
loader.loadClip(target, holder_mc);
}
SWF Tools does support AS3, you need to change it in the options.
1. Open your PDF in swf tools
2. Edit=>Options
3. Viewer tab
4. Check "No viewer" and flash version 9. (Or use the simple viewer)
- You can also do the "Insert stop after each frame"
I know this because I've done the same thing with a PDF. If you don't have those options, then it's time to download the latest version!
We're developing a small Flash gamelet for an European client of ours, who require us to develop our Flash game in such fashion that they can load our SWF game into their ActionScript 3 project, dynamically.
Basically they have a console that will load many other Flash games, amongst our own, depending on which button the player presses on a "Choose Your Game" screen.
Basically, we have a FLA project that we're authoring in Flash Professional CS4 and everything is basically a straightforward Flash game. When we test the game via Ctrl+Enter or run the compiled SWF file by double clicking it, all works well, the game executes perfectly and everybody is a happy bunny.
What we need to grasp is loading our SWF into our clients AS3 project, which is basically an external ActionScript 3 project created in Flex Builder 3. The client posted us the following code to load the SWF:
var myGame:FunkyChickenGame = new FunkyChickenGame();
addChild(myGame);
...which gets executed in the ActionScript 3 application constructor of the clients app, or perhaps an event handler for a button pressed on the "Choose Your Game" screen.
We tried creating a blank AS3 project in Flex Builder and tried loading the SWF as per my snippet above. All our traces within the external SWF's document class are showing up as expected in the Flex Builder console view, so the code is running perfectly.
The problem we're experiencing is that despite calling addChild(myGame)...we're not seeing any graphics, just the default background color of the encapsulating AS3 project.
Note however, when we run the SWF by double clicking the Game.swf file in Windows, it all executes perfectly, the game works without flaw and glitches.
Any help on this topic would be highly appreciated. Thank you in advance.
What you need to use is an instance of the Loader class, like so:
var loader:Loader = new Loader();
// you'll need to write a method named onLoaded to capture the COMPLETE event
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
loader.load(new URLRequest("game.swf"));
addChild(loader);
Creating an instance of a class is as wage as it can get. Your client has a funny way of posting references.
However FunkyChickenGame may be a class created by the client that can launch your game. Maybe the games are embedded in their flash app, but that would mean long loading time. If indeed many games are "loaded" this way.
My advice would be that you don't use stage, root or whatever properties that could link to the main app instead your game, and leave the client to decide how he would like to load it.
I'm using BulkLoader to load an array of 10 or so FLV files. I want to be able to use and control these FLVs throughout my app independently. So for instance, FLV_1 may be displayed in duplicate but I want to pause one instance and play the other in tandem.
I would like to pass the NetStream object around to other Video objects and display both. Is this possible? If so, how do I go about doing it?
It's definitely possible. BulkLoader will expose you the NetStream object, so you can pass it around to Video or anything else, for example:
var videoItem : VideoItem = bulkLoader.get("my-video.flv");
var video : Video = new Video();
video.attachStream(videoItem.content);
// or the shortcut:
video.attachStream(bulkLoader.getNetStream("my-video.flv");
Regards
Haven't tested this but logically you shouldn't be able to play more than one video containing the same instance of a NetStream asynchronously, simply because the pause/play/etc. methods are triggered directly on the NetStream instance (and not on the Video containers...).
On the other hand you can probably play the same instance of a NetStream synchronously within different Video instances (to be double checked!).
Probably the easiest hack would be to load the same FLV into two different items (in case you use BulkLoader) referencing them with unique ID's and hoping the end-user has his browser cache enabled. Thereafter you would add and control each NetStream separately just as if you were handling two different movies.