It’s often convenient to playback video remotely from a web server rather than bundling it directly within your app. This is necessary, for example, in apps where the user has to select from a collection of dynamically uploaded video.

Let’s see how to progressively download either an FLV or H.264 video from the web and handle buffering of that video.

Flash iOS Apps CookbookThis tutorial is a previously unreleased recipe from Flash iOS Apps Cookbook and supplements the content found in Chapter 12, Working with Video and Audio.
Flash iOS Apps Cookbook provides the recipes required to build native iOS apps using your existing knowledge of the Flash platform. Whether you want to create something new or simply convert an existing Flash project, the relevant steps and techniques are covered, helping you achieve your goal.

Getting Ready

Depending on your preferred video format we’ll work from either the code you wrote as part of Playing Local FLV Video or Playing Local H.264 Video. Alternatively, download this recipe’s accompanying code bundle and use it as a starting point.

For FLV video, open chapter12/recipe8-flv/recipe.fla and use it as a starting point. Alternatively, for H.264 video, open chapter12/recipe8-mp4/recipe.fla. H.264 video is only available to those using the AIR 3.0 SDK and above.

Both FLAs have had a movie clip named bufferingIcon added to the center of their stage. We’ll show this clip whenever the video is buffering.

View of your FLA's stage.

If you examine either FLA’s AIR for iOS settings you’ll see that, unlike the local equivalents, there’s no need to bundle the video with the app. Instead we’ll upload the corresponding video to a web server. If you don’t have access to a web server then you’ll need to purchase a package from one of the many available web hosting companies.

Alternatively set one up locally on your development computer. Microsoft Windows users can set-up IIS: www.howtogeek.com/howto/windows-vista/how-to-install-iis-on-windows-vista, while Mac OS X users can configure and run the built-in Apache web server: http://macdevcenter.com/pub/a/mac/2001/12/07/apache.html.

If you already have access to a web server then you’ll likely have an FTP client for uploading content to your space. If not then consider installing FileZilla. It’s free and can be downloaded from filezilla-project.org for both Windows and Mac OS X.

Once ready, upload either chapter12/resources/video.flv or chapter12/resources/video.mp4 to a suitable location on your web server.

How to do it…

Perform the following steps.

  1. Open your FLA’s document class.
  2. Add an additional import statement to it:
    import flash.events.NetStatusEvent;
  3. Within the constructor, make the following changes to your NetStream object, allowing the buffering of the video to be managed:
    netStream = new NetStream(netConnection);
    netStream.client = this;
    netStream.bufferTime = 4;
    netStream.addEventListener(NetStatusEvent.NET_STATUS, statusUpdated);
  4. Staying within the constructor, find your existing call to the NetStream object’s play() method and alter it to load your remote video rather than a local version. For FLV video your code should look like this:
    netStream.play("http://www.yourdomain.com/video.flv");

    If you’re working with H.264 video then change the existing code to this:

    netStream.play("http://www.yourdomain.com/video.mp4");
    In either of the above calls to play(), replace www.yourdomain.com with the URL to the folder on your own personal web server where you uploaded the FLV or H.264 video to.
  5. Now add an event handler that sets the visibility of the buffering icon depending on the status of the NetStream object’s buffer:
    private function statusUpdated(e:NetStatusEvent):void {	
      switch(e.info.code)
      {
        case "NetStream.Buffer.Empty":		
          bufferingIcon.visible = true;
          break;
    
        case "NetStream.Buffer.Full":
          bufferingIcon.visible = false;
          break;
      }
    }

    We’ll show the icon whenever the video buffer is filling and remove it from view when video playback is about to take place again.

  6. Save your document class and move back to the FLA.

    Streaming video onto your device.

  7. Publish the FLA and test the app on your device. When launched it will connect to your web server and begin loading the video. When enough data has downloaded, the video will start playing.

How it works…

The ActionScript required to play a video from the web isn’t that dissimilar to the playback of a local video. In both cases, a technique known as progressive downloading is employed, where playback begins after the video has partially loaded. This allows playback to begin as soon as possible without the whole video having to first be loaded and held in memory. You’re probably already familiar with this type of video streaming as it’s used by popular sites such as YouTube and Vimeo.

To enable progressive downloading, the NetStream object holds an internal buffer, which is filled with video data as it becomes available. Once filled, playback of the buffer’s data will commence. As video data is played, it’s removed from the buffer and eventually discarded from memory.

With progressive downloading of video, the hope is to always have enough video data held within the buffer to produce seamless playback of the video. If the video data is being consumed faster than the buffer is being filled, then the buffer will eventually become empty. When this happens, the video is paused until the buffer is large enough for playback to resume again.

When playing local video from the file system it’s unlikely that the video buffer will ever become empty as your application will have almost immediate access to the data. However, this won’t be the case with remote video and the number of interruptions during playback will depend on the video’s size, the device’s download speed, and the bandwidth capabilities of the server hosting the video.

The NetStream class provides the bufferTime property, which can be used to dictate how many seconds of video data should be contained within the buffer before playback can commence. The larger this value, the longer the user will have to wait before the video initially starts playing, but the less likely it will be that the buffer becomes empty during playback.

It’s possible to monitor the status of the buffer by listening for the NetStream object dispatching NetStatusEvent.NET_STATUS. By examining this event’s info.code property you can determine when the buffer has become empty, and when it has filled again. This is useful as it allows you to inform the user that the app is currently waiting for more video data in order to continue playback. In this recipe’s example code, we did this by making the bufferingIcon movie clip visible when the buffer became empty. When it filled again, we hid the movie clip from view, providing the user with an unobstructed view of the resumed video.

When downloading video from the web, it’s advisable to warn the user beforehand. After all, if they’re using a carrier’s cellular network at the time then they could incur significant data costs.

There’s more…

The NetStatusEvent object can be used to determine the status of more than just the NetStream object’s buffer.

NetStream Status

The NetStatusEvent object is dispatched in response to a plethora of useful status changes, errors and warnings. Here are just a few strings that the info.code property can be queried for:

  • NetStream.Play.Start: Playback has started.
  • NetStream.Play.Stop: Playback has stopped.
  • NetStream.Play.StreamNotFound: The video file cannot be found.
  • NetStream.Play.InsufficientBW: The client does not have sufficient bandwidth to play the video at its intended frame rate.
  • NetStream.Pause.Notify: The stream has paused.
  • NetStream.Unpause.Notify: The stream has un-paused.
  • NetStream.Buffer.Flush: Playback has ended and the buffer is now empty.

You can determine the code’s type by examining the info.level property, which will be set to one of the following strings: status, error or warning. For a comprehensive list of supported strings, perform a search for flash.events.NetStatusEvent within Adobe Community Help.

The flash.net.NetConnection object also dispatches NetStatusEvent objects, which you can listen for.

Streaming Video with Flash Media Server

While it’s not covered within this book, it’s possible to stream video from a Flash Media Server using the NetConnection and NetStream classes. Flash Media Server is a server solution optimized to deliver real-time media and is ideal for high-volume websites where performance and reliability are critical.

See also

  1. I realize that your post was on local AV but since you did do the fast mention of FMS I had to offer that since 2007 there has been a far nicer server solution not just for streaming but also RDO work ( which is truly what makes Flash a killer). Test drive Wowza Media Server. I was a strong FMS dev but when Adobe bought Macromedia and decided to do nothing to FMS besides adding h.264 I found Wowza and was blown away. They provide a full back end including a free Eclipse IDE for coding Anything you can imagine for flash clients. The majority of their users just stream and your interest seems to match just that but when the time comes to code RTMP and server side objects with automatic push (meaning massively multiuser applications with real time events) Wowza truly shines. But, if you really just want to stream vide and audio you can have that in about 5 minutes after downloading Wowza, hth

  2. Great to know. Thanks for the info Robert!

    Christopher (Author)