views:

873

answers:

4

Hi,

I've multiple videos stored as MovieClip objects and would like to merge them into a single MovieClip video object in order to play all of them in sequence (so that a user thinks it's a single video).

Thanks a lot!

EDIT: I want to do it programmatically in ActionScript inside the Flash Player.

A: 

Add them to the timeline one after another, make sure each movieclip exists on the timeline for as long as the duration of the movie it contains is. You can do this by adding keyframes to the timeline that will contain the movieclips. Also, make sure your video framerate and Flash player framerate are the same.

This isn't really a programming question.

Jotham
I have just clarified that I need to do it in ActionScript inside the Flash Player, so it is a programming question.
bartekb
+1  A: 

Would be great if there was a TIMELINE_COMPLETE event. But there isn't! So the next best thing is the undocumented addFrameScript method.

You can use addFrameScript() to add code to the last frame of your MovieClips (or any other frame). This code could remove the old MovieClip (the one that has just finished), and add the new MovieClip (the next one in the queue).

public function Main() 
{
    // Remember addFrameScript() is zero based.
    currentVidMc.addFrameScript(currentVidMc.totalFrames - 1, frameFunction);
}

private function frameFunction():void 
{
    //delete frame script by passing null as second parameter
    currentVidMc.addFrameScript(currentVidMc.totalFrames - 1, null);

    removeChild(currentVidMc);
    addChild(newVidMc);
    newVidMc.gotoAndPlay(1);
}

EDIT*

To make a smooth transition, you could try loading in the new clip early (about 15 frames sounds good to me, but you will have to try) with visible set to false, and stopped. Then when the last frame of the current clip rolls around, just remove the current clip, and set the new clips visible property to true, and play it. Most of the jump comes from the loading of the clip to the stage, so pre-rendering the clip may help.

TandemAdam
Thanks. Unfortunately, this doesn't solve my problem. I've done something similar using the ENTER_FRAME event of MovieClip. When the ENTER_FRAME event is fired I compare currentFrame with totalFrames and if they are equal, I start playing the subsequent MovieClip. However, I get a noticeable delay at the stitching points of MovieClips. I thought that I could get rid of the delays if it was possible to combine the MovieClips into a single one. Is it possible?
bartekb
You are quite correct. This is a common issue. I have added an edit to my answer that may help.
TandemAdam
Thanks. I've tried preloading everything, but still when I call play() or gotoAndPlay() when switching MovieClips, the delay is noticeable even on a pretty fast machine. Seems like there is no way around it.
bartekb
This is not good news for me either! I have a project coming up where I need to do this. I am a little worried now. Hope you find an answer.
TandemAdam
I'll definitely share a solution here if I find any. Please let me know if you find one.
bartekb
A: 

Not really an answer but 2 things you could perhaps try.

package {
    import flash.display.MovieClip;
    import flash.events.Event;

    public class OneMovieToRuleThemAll extends MovieClip {

     public subClips:Array; //vector for cs4
     private var index:int = 0;

     public function OneMovieToRuleThemAll(subClips:Array) {
      this.subClips = subClips;
     }

     //pre subClips.length > 0
     public function playAll() {
      for(var i:int = 0; i < subClips.length; i++) {
       subClips[i].visible = i == 0;
       subClips[i].stop();
       addChild(subClips[i]);
      }
      addEventListener(Event.ENTER_FRAME, onEnterFrame);
     }

     private function onEnterFrame(e:Event) {
      if(index >= subClips.length) {
       //dispatchEvent finished
       removeEventListener(Event.ENTER_FRAME, onEnterFrame);
      }

      if(subClips[index].currentFrame < subClips[index].totalFrames) {
       subClips[index].gotoAndStop(subClips[index].currentFrame + 1);
      }else{
       subClips[index].visible = false;
       index++;
       subClips[index].visible = true;
      }

     }
    }

}

It's usually discouraged to use enter_Frame and gotoAndStop(currentFrame) because it's slow, but maybe this is equally slow for each frame so you wont notice any 'stitching'

An alternative could also be to build a new movieclip with a Bitmap for each frame of each movie with BitmapData.draw(..); Then use the same enter_frame loop and toggle visible properties for each frame. Probably uses allot of memory and I have no idea if it's even remotely feasible speed wise.

Les
A: 

if i were you i'd wright a simple wrapper it'd just: * know the order of files to show from some xml config * while playing the first file measure fps (or available RAM or internet connection - depends on how you deliver your files to the pc playing vedia) * when at last the wrapper decides that it's just 200%-300% of the prognosed time of loading the second file to some playable percentage. * if your prognosing algorithm is cool enough - you have the second vid before the first stopped. so here is the easiest part imho [if your last and first frames match good enough]: you just pause the second vid on the frame you need and set its' alpha to 0 placing it under the first one. when the first one comes to the matching frame you start decreasing it's alpha increasing the second ones' instead and releasing it from the pause.

the only human task (except of coding the wrapper, but it feels just like a couple of screens of code maximum) is searching for matching frames and putting it all to config, but you can avoid even it by using the BitmapData.compare() method. good luck!

www0z0k