Seamlessly looping video files in AS3 with Netstream.appendBytes

Often I find, particularly with exhibit type projects, there is a requirement for some looping video. ย Often the loop is required as it’s part of the UI, rather than consumable content. ย A designer or animator has made some cool effect and video is simply the best way to deliver this asset.

Now there comes a problem ย – in older versions of flash player it was quite easy to just loop a video, but in more recent releases it’s broken and according to adobe this is not important enough to fix.

The only way that I found to get around this was to convert the file to a swf with the video on the timeline. I had some success with this, but the quality always suffered and every time the designers updated the asset I had to reconvert. Someone on the bug report suggested however that there might be way to get the video file to repeat seamlessly by using appendBytes but hadn’t provided a working example. So I just ran into this again and decided to tackle it ย once and for all – here’s a class that’ll seamlessly loop an flv (appendBytes only supports flv):

Edit: I recently had cause to use this again in a project so have tidied up the code a little and fixed a bug where I had delays in later loops. Also I’ve added a variation for cases where an animation plays in with one video, then loops with another.

19 thoughts on “Seamlessly looping video files in AS3 with Netstream.appendBytes”

  1. This looks like an awesome idea. I’ve been trying to seamlessly loop flash video for a long time.

    I gave up, but thought I’d scan Google to see there was any progress.

    I can’t figure out how to implement your class. I’ve never used ByteArrays for video.

    Can you write a short example that calls your class? Thanks!

    1. Hey, glad you like it!

      You can either use something like http://www.greensock.com/loadermax/ to load the flv as a bytearray, or simply embed it at compile time – this example is just off the top of my head – may contain errors:

      [Embed(source="../bin/assets/video/myVideo.flv", mimeType="application/octet-stream")]
      public var videoBytes:Class;

      public function playVideo():void {

      var flvAsByteArray:ByteArray = new videoBytes();
      var video:Video = new Video();

      addChild(video);

      var loopingVideo:AppendByteVideoLoop = new AppendByteVideoLoop(video, flvAsByteArray)

      }

      1. Thank you very much!

        I have too many videos to embed, so I’ll give loadermax a try.

        I already use some of the other greensock tools.

        I really appreciate your efforts!

    2. I think I actually took this stuff further as a more useful package, I’ll have a look to see if I can share the final result

  2. Really very much appreciated. I couldn’t believe how long it took me…trying to sort out something that should be really simple. Good work.

    1. I’m not aware of that restriction, do you have a reference?

      It’s worth noting that if you have .mp4, ffmpeg can repackage to flv so that you can still use this technique:

      ffmpeg -i input.mp4 -vcodec copy -acodec copy output.flv

  3. This is really cool! Supersmooth transitioning between videos with no flickering at all.
    Unfortunately it does not work on iOS (with AIR).
    As appendBytes does not work with h264 and other codecs are laggy on iOS ๐Ÿ™

    1. Hi AM,

      Yes appendBytes only works with a .flv wrapper. I thought you could wrap H264 in flv though?

      See the ffmpeg command for rewrapping an mp4 (I assumed my mp4 was h264). Maybe thatโ€™ll help?

  4. Hello
    1000 thanks for that code, i just came across it while doing research.
    Did you try using it with the StageVideo Class?

  5. Hi Robin,

    Thanks very much for creating this solution and making it public. It’s really helped me a lot with my current project! ๐Ÿ™‚

    I have implemented the class and used with a bunch of different videos and it works great.

    The only issue I can see is that at the time of ‘addToStream’ there is a slight jitter / dropped frames. It feels like it’s struggling a little to do the appendBytes bit? I’m using AIR 17 for this. (BTW: AIR 16 seems to call ‘onMetaData’ many times, milliseconds apart which kills this solution. Seems fixed in AIR 17).

    Is there any way to add less bytes each time, maybe using something like ‘FLVSlicer’ or something? I’d appreciate your help if you have any ideas and would be happy to compensate you for your time if you have a moment to discuss on I.M / Email.

    Thanks once again for your help ๐Ÿ™‚

    1. Hi John, glad it’s useful ๐Ÿ™‚

      onMetaData may be being called often if the file has lots of metadata perhaps?

      How big is your flv – perhaps it’s stuttering due to sheer size – have you tried looking at what’s going on in Adobe Scout?

      1. Hi Robin,

        Thanks for your quick reply.

        The FLV is very small:
        Resolution: 960×540
        Duration: 20 secs
        Size: 2.33MB

        You can find it here if you want to see it: https://dl.dropboxusercontent.com/u/48240680/coffee.flv

        Originally from: http://videohive.net/item/roasted-coffee-beans-falling-down-/8515465

        I don’t know if it’s something in the encoding of the file instead? I’m using these encoding params for FFmpeg:

        -an -f flv -vcodec libx264 -movflags faststart -crf 23 -r 30 -g 60 -profile:v baseline -level 3.0 -keyint_min 15 -tune fastdecode -preset slower

        I wonder, do you have any seamless looping FLV hanging around that you know works?

        Re: onMetaData – the same file would produce different results in AIR 16 vs. 17. Recently AIR dev team have raised known issues about FLV in release notes… not sure if related.

        Re: Adobe Scout – no I have not tried yet but I will try and fire it up and see if I can see anything.

        Happy to pay / donate if you have some time to reach out on IM. And of course thank you for your help so far too! ๐Ÿ™‚

        1. I’ve given it a go – the playback isn’t as smooth in air as it is in VLC, but performs better at 60fps than 30 (despite the video being 30). Any slight jitter doesn’t seem associated with the appendbytes injection.

          Scout seems to show everything within budget.

          Have you tried with StageVideo – that might be better?

          Here is a sample flv I used for testing, 1920×1080 with transparency: https://www.dropbox.com/s/qxuoy7pefwt5b9l/l1.flv?dl=1

          1. Thank you for taking the time to test all of that, it’s really appreciated from someone who’s been in the trenches all day! ๐Ÿ™‚

            I took your advice and ran Scout as well and didn’t see anything out of the ordinary either.

            The one slight disparity between our tests is that I’m testing on an Android Mini PC so any glitches seem a bit more noticeable than the PC. (http://www.laptopmag.com/reviews/mini-pcs/rk3188-android-mini-pc)

            I agree with you that the video itself seems to have some sort of mismatch between it’s start and end (ie. not perfectly seamless as advertised) . I did the loop in after effects and re-encoded it (so a total of 40secs) and I could see a slight niggle around the 20secs mark so I guess it must be the video.

            Thanks for the sample file (reminds me of my early video game days circa early 80’s!) . I notice that it is encoded with VP6 instead of H.264. I think VP6 gives alpha channel capability, but are there any other advantages in using it over H.264 (in the context of loops and ‘appendBytes’)?

            So the looping part now is really good, thanks. My only issue (and not your concern of course!) is that my app randomly crashes whilst doing this looping. It works perfectly if I set the loop and leave it… but in my app I have to pause the loop, show another image and then start it again. I’m doing a simple _stream.pause() and _stream.resume(), but after 500+ pause and resumes the app dies. Memory etc. all seem nominal so perhaps something under the AIR hood (like the mulitple ‘onMetaData’ calls). Perhaps if I try encoding it in VP6 I might get a different result.

            StageVideo is a great suggestion, unfortunately in the latest versions of AIR it is totally broken on Android (AIR 17 Known Issue: [Android] FLV video encoded with H264 is not working with stage video, video is not getting rendered (Bug 3950740)). Perhaps if they get it working in subsequent versions I can migrate to that, get it off the timeline a bit. Maybe I can run this in a worker for now so it’s uninterrupted maybe.

            Thanks once again for your help and discussing the issue with me, it’s been a real ray of light on an otherwise awful day! ๐Ÿ™‚

  6. no worries John, yeah I was testing a few concurrently,. so was using transparent flv’s – in general I think h264 gives better quality at lower filesize so I would use that if transparency isn’t required.

  7. Hi,

    So how do you use this code afterall? Could you point to some examples?

    Embed apparently requires Flex and embedding is not something I would like to use, and I have no idea how to use greensock.

    It seems like a very cool solution, but if I cant figure out how to use it, whats the point?

    Some actual example of using this class would be really nice.

    Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *