How insane is it that there’s no way to seamlessly loop video in Flash? Very insane! That’s how!!!
Here’s my requirement : I have a lot of prerendered 3D animations that need to loop. Spinning objects and stuff. So I’ve converted them to FLV and I’m loading them in with that really fiddly NetStream and NetConnection stuff. And they need to just quietly spin away in the background not taking up too much processor time.
So ideally in old-school programming days, we’d have a nice image sequence sitting in our timeline that just animates away. But of course, they make the swfs HUGE.
If only there was a way of combining the small filesize of flvs along with the speed of rendering of image sequences… Well now there is!
After a good day or so of tearing my hair out, I now present to you… the VideoMovieClip! It’s just like a normal movieclip except it’s made out of an flv. So you can gotoAndPlay, nextFrame, stop, play just as though it was a movieclip!
How awesome is that!?? Except I haven’t quite got it working.
I’ve had a day or two of nightmares.
The first was a bug with drawing into a BitmapData from a video object. If you do a bitmapData.draw(myVideo) it draws the Video object at the same size as it was when you set it up, ignoring any subsequent resizing. So the trick is to wait until you get the metadata and then set up the Video at the size given. Except if you do that then you can’t take a snapshot of the video straight away so you lose the first frame. So I’ve had to set up a matrix than converts from the old size to the new size. Nightmare.
But the most nightmarish part is that with Flash Video, you have no way of finding out when frame has been rendered! And we need to know when each frame renders so we can record it into a bitmap. It’s SUCH a nightmare!
So why not use an ENTER_FRAME? Because, even if you match your swf’s framerate to the flv, the video playback seems to run independently from the movie! You can’t guarantee that you’ll get every frame. Nightmare.
So why not just pick up the flv framerate from the metadata and set up a timer that fires at the same interval as the framerate? Great idea! Except it seems that flv’s actual framerates can be completely different from the metadata! Nightmare.
But what I did notice is that you can check the NetStream’s time property. This is the time (in seconds) that the video has been playing. If you set up a timer on every milisecond and trace out the NetStream time you’ll notice that it doesn’t increment smoothly. It steps up every few mils. Could this mean that that’s when a new frame appears? Let’s try it and see…
So I got a handy system that checks the NetStream time every frame and snapshots the video! Yay! Except, if the Flash Player slows down at all or has one of its hissy little fits, you miss frames. And when you miss a frame, it’s too late! You can’t even tell the NetStream to go to a specific time, so we can pick it up again. (well you can but it will just go to the nearest keyframe) In fact, it’s even really hard to find out that we missed one at all! Nightmare!!!!
So now it logs when it misses a frame and just runs the video again, hoping to pick up the missing frames. But I was finding it was missing loads of frames and wrongly trying to capture too many frames on some videos. And then I realised, the NetStream.time hack only works if there’s no audio in the flv! Nightmare!
But here it is so far. What I’ve got is an flv with numbers on so I can check for dropped frames. The first time you see 3 seconds of numbers, it’s the flv playing, and we’re recording it. When the little versions appear that means it’s finished one pass. If they’re all recorded we’ll then be watching the bitmap sequence. You can tell it’s the bitmap sequence if it has the red background. Otherwise it’ll try again to fill in the missing numbers.
Click the mouse to try again (although i haven’t cleaned up so if you keep clicking your memory usage will stack up).
And let me know if it works for you!
[kml_flashembed movie=”/wp-content/uploads/manual/2008/videomovieclip.swf” width=”320″ height=”500″ FVERSION=”9″ QUALITY=”high” /]
And if you’re feeling incredibly brave, check out the source : videomovieclip.zip. And I’m sorry about the state of it! :$
[UPDATE]
So thanks to Tink (see comments) it turns out that all of my work was unnecessary! All you have to do is embed the flv on a timeline and it syncs perfectly with your framerate and can do all the movieclip stuff..! Just going to do some performance tests and get back to you…
25 replies on “Seamlessly looping video in Flash”
“The first was a bug with drawing into a BitmapData…”
I don’t think that’s a bug. BitmapData.draw works that way with any object you draw to it. Draws it in its untransformed state. Learn to love the matrix!
heheheh trust me, I’m more than intimate friends with the Matrix. The thing that confused me with the Video object was that I was only resizing it to make it 100%. In other words, it always thinks it’s the size it was when it was first made.
No matter, that one was easy to fix…
I’m getting even DEEPER now… apparently the NetStream.time update jumps don’t have anything to do with the frame update at all, it just seems to update 30 times a second – so it’s fine if your video runs at that framerate.
Man this is doing my head in now… I really need to sleep!
Seb
yeah, thats a good idea. how smaller is a decent flv sequence against a png sequence, once its been compressed?
Yohami:
From what I’ve seen, it can be pretty substantial. It depends on your compression settings of course, but on a project I worked on a while back, it was like 1/2 the size (at also lower but acceptable quality). I think it has to do with interframe vs. intraframe compression
It would also be cool if we could play VideoMovieClip backwards 😉
Nice! I had a similar idea a while back. I wanted to create “impossible flash effects”, by rendering ridiculous amounts of particles (or so) with a kind of a “loader” or “renderer”, which would generate a sequence of bitmaps (as you have done), which would then playback smoothly… To make the “trompe l’oeil” (posh I know) more powerful, the video could be rendered somehow based on user interactions… erm, like “omg this must be real time since this sure ain’t no pre rendered video or nuffin”. 😉
Nice work! You may (will?) encounter a problem with getting bitmap data from a video if it is coming from a proxy server. A while back I was rendering video in Papervision and it all worked fine until the videos were hosted on Akamai without a transparent proxy and then I got no bitmap data at all. bah.
🙂
You could import your video into an FLA, stick it on the timeline, export the SWF, then load and display the SWF.
If you wanted more than one video that acted like a MovieClip and your using AS 3.0, you could put each on their own timeline in a MovieClip, load the SWF with all the videos and then create the instance of each clip thats required.
Hey there,
I have done the exact same thing a while back for a project, and I went in the end for the approach to stick the flv in a swf which solved all the issues.
M.
@Tink and Manuel
You know what, I think you’ve only gone and done it!!! I just assumed that the video would get recompressed from the IDE but it doesn’t! And it’s the same size! And it syncs perfectly with the swf timeline! Am going to do some performance tests now… Why can I never think of the simple solution!!!?
@yohami
Yeah I find with some of these videos MASSIVE savings in file size. That’s becuase the frames don’t change that much. I’m seeing files that are 1/8 the size of the original image.
@sakri
Hehehe why not just render an insane amount of particles in AS3? 😉
@Alistair
yeah only too familiar with that security lock-down, there was a workaround in Flash 8 but it’s beened killed in FP9. Unfortunately my method isn’t too robust. But thanks to Tink and Manuel I think we’re sorted!
Glad to be of some use 🙂
That new security lock-down only applies to videos streaming, progressive downloads shouldn’t be affected by it.
//justin.everett-church.com/index.php/2007/12/07/wiwtw-bitmapdatadraw-and-rtmp-snapshotting/
@Manuel / Tink
Sticking flv´s into swf´s is infrequently functional, namely in the case of your flv´s are very small kb-sized.
When you handle bigger (kb-size) flv´s this method sucks ´cause you have to load a larger amount of data first.
Cheers.
frank
Hey Frank, yes true this technique isn’t right for EVERY application, but as my videos are all short and need to be preloaded, this should work just fine! I’ll let you know how i get along.
Seb
Hi,
I’m going to develop a little flash to manage 360° video. It’s just an FLV with a photo product rotating.
I would like to have the possibility to slide in my video.
I did 2 tests:
1/ FLV imported in a SWF, it’s okay, the file size is really smaller BUT the performances are really bad. 53% CPU Usage just when I slide on the timeline.
2/ PNG Sequence. this time the animation is perfect. CPU Usage less than 10% when I slide on the timeline but the file size is 3 times bigger.
Any ideas to have the best of the two solutions… filesize and performances ?
Thank you for your advice.
Regards,
S.
Hi Sakana,
yes, in fact we implemented this system in the end. Embed the FLV on the timeline, then the first time you play it you record each frame into a bitmapdata. Then you can subsequently play back one bitmapdata at a time. It’s a small filesize but with the speed of rendering of a png sequence!
Seb
Okay I see. But for example, if you have an FLV of 6 sec 640×480 it can become a huge size in the memory of the user computer non ? And maybe crash the player.
Thank you for your feedback,
Regards,
S.
That is true, but in theory that’s the same amount of memory that a PNG sequence would use once it was loaded into memory…
Okay, I will check that because if it’s “uncompressed” bitmap in memory it will be more.
S.
After some tests…
With an FLV of 6 sec 181 frames 640×480 pixels. After recording each frame with bitmapData I notice 217mb in memory usage. But the png sequence took 246mb in memory after loading the swf.
Another alternative, when I compress my mov file to FLV, I check the option, “key frame placement” and I put a key frame on each frame of the movie. The result : the size of the flv increase… from 600kb to 2mb. BUT when I load the flv I can navigate on the timeline like a png sequence with good performances and the size of memory usage is 16mb !
I think this last solution is the best match between performances/size.
Regards,
S.
That’s really useful information, thank you! Does the flv loop seamlessly with this method?
cheers
Seb
No 🙁
Indeed, if I watch carefully I can see the little pause between last frame and first frame.
Regards,
S.
Hi Seb,
How are you ?
Hey did you noticed that in CS 4 the loop issue is corrected. If you import an FLV on your timeline and just compile you will never see the cut.
Regards,
S.
FLV in CS4 also stops for a while. Sakana, where did you get this information? I’ve check a moment ago and it’s still problem.
hey Dave when embeding an flv into flash on the timeline check in the properties of the flv under Source it tells you the number of frames the movie will play over, sometimes it stretches the frames on the time line to more than that also if you are using the Adobe media encoder you will drop frames (normaly 2 first and last frame) for the loop
Hello there. can u explain to me the step to loop image sequence ? i already finish my animation in flash by using image sequence and i want to loop this animation infinitely ? can u help me. btw im using as2
Hi there, I don’t use Flash any more so I can’t help – sorry!