StageVideo on iOS with AIR

I've found it hard to find a recent tutorial apart from this brilliant one by Lee Brimelow: http://www.gotoandlearn.com/play.php?id=134
I'd recommend watching that tutorial first as it explains everything, then if you want to copy the code see below, there's also a zip containing everything (you'll need to follow

Though as the download didn't work and there was nothing specific to iOS I thought i'd type it all out for you and elicit a few details specific to iOS. So you know what i'm using - its AIR 3.2, Flash CS5.5, i've tested it on an iPhone 4 with 5.0 and an iPad with 5.1 - though there's no reason why it shouldn't work on anything above 4.0 as far as i know. If you want to update your SDK to 3.2 then follow the instructions here (http://helpx.adobe.com/x-productkb/multi/overlay-air-sdk-flash-professio... - but use player tag 15 for AIR 3.2).

Here's some iOS settings:
In your "AIR for iOS Settings..." set "Rendering" to "GPU"
Under "Included files:" click on the plus and include your video, remember to change the name of vid.mp4 below to whatever yours is.
You will find that the simulator within flash wont play StageVideo, it will use the alternative "Video" - you can test this by removing the else statement under "if(stageVideoAvail)" - this will show nothing in the simulator but will work on your device. I'm getting an error in the simulator when the video reaches the end, I suspect that there's a missing event handler for this, i'll update soon on that.

To encode the video, thanks to Antonia Holguin who posted some settings that work well: http://swfhead.com/blog/?p=1617
Using After Effects these settings worked well (use them as a starting point perhaps):
• H.264
• TV Standard: NTSC
• Profile: Baseline
• Level: 3.1
• Bitrate: CBR at 1.1

here's the code, make this the Document class of your flash file:

package
{
import flash.display.Sprite;
import flash.events.StageVideoAvailabilityEvent;
import flash.media.StageVideo;
import flash.events.StageVideoEvent;
import flash.geom.Rectangle;
import flash.media.StageVideoAvailability;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;

public class main extends Sprite
{
private var stageVideoAvail:Boolean;
private var sv:StageVideo;

public function main()
{
stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, onAvail);
}

private function onAvail(e:StageVideoAvailabilityEvent):void
{
stageVideoAvail = (e.availability == StageVideoAvailability.AVAILABLE);
initVideo();
}

private function initVideo():void
{
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.client = this;

if(stageVideoAvail)
{
sv = stage.stageVideos[0];
sv.addEventListener(StageVideoEvent.RENDER_STATE, onRender);
sv.attachNetStream(ns);
trace('available');
}
else
{
var vid:Video = new Video(1024, 768);
addChild(vid);
vid.attachNetStream(ns);
trace('not');
}

ns.play('vid.mp4');
}

private function onRender(e:StageVideoEvent):void
{
sv.viewPort = new Rectangle(0, 0, 1024, 768);
}

public function onMetaData(e:Object):void
{

}

public function onXMPData(e:Object):void
{

}
}
}

File: 

Comments

Thank you for sharing this! - You've saved my day!!!

Here's another tip for newbie iPhone developers, concerning how setting the release date for a new app works.

Setting release dates properly has been a frustrating process for me. The release date can greatly affect where your app appears in the New Releases list on the AppStore, which is the only guaranteed list exposure your app will get. However, if you do not set the release date properly, you will lose that opportunity as well.

The way release dates worked in the past was confusing at best. In the beginning, when you changed your release date, you could move your app to the top of the list, which people gamed

First of all, thank you for the only clear CS5.5 StageVideo example on the internet.

My video is playing perfectly, but I still get no audio. I'm experimenting with different settings; do you have any recommendations?

Cheers,
D

I'm not sure about the audio as the video i tried didn't have audio - so not sure. If you find out then post it perhaps

This was SUPER helpful. Thank you so much!

@db, as dumb as this suggestion sounds, I didn't have sound either then I took the iPad off of mute. Inherently it seems that the mute switch doesn't mute your air application, but it does mute the video playback. So just throwing that out there. :)

Thanks so much, I've been stuck on this for two days and your post saved me!

That was biting me as FDT has 'auto' as the default setting.
Also, though I 'knew' this, don't forget that StageVideo is not a DisplayObject - it doesn't get added to the stage - it is always at the z-order of the stage, BUT you *can* put DisplayObjects in front of it - so don't obscure it with, say, the background asset of your app!

I found this post on an Adobe forum dated : Jul 21, 2012 6:31 PM

I had the same issue. It seems to be a bug. There's an easy way to fix it. Just play a sound, before playing the video.
I just added a short sound file that I'm playing onLoad. Without this, Flash doesn't seem to know how to handle sound in video files, but once you played a sound, it "remembers" how to do it for stagevideo.

Silly solution, but it worked for me.

I had the same no-sound issue. this funny solution worked for me as well. ^^
Thanks a lot!

Thanks, very helpful quick start to StageVideo.

I added a few things to rid me of the error handling problems. See below:

I'm not 100% on this but my iOS app was crashing before I caught all these errors (could have been something else I fixed : ) ). I'm not sure if this would cause a fatal crash, but we all know the flash player glosses over these kind of things, whereas I suspect iOS bytecode could fail if it cannot process an error message - it's probably looking for that bit of memory where the function should exist but doesn't.

this.stream.client = new CustomClient();
this.stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
this.stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);

private function netStatusHandler(event:NetStatusEvent):void
{
switch (event.info.code)
{
case "NetConnection.Connect.Success":
break;
case "NetStream.Play.StreamNotFound":
trace("Stream not found: " + videoURL);
break;
case "NetStream.Play.Stop":
trace("the video has ended");
rewindVideo();
break;
}
}

public function asyncErrorHandler(event:AsyncErrorEvent):void
{
trace(event.text);
}

class CustomClient {
public function onMetaData(info:Object):void {
trace("metadata: duration=" + info.duration + " width=" + info.width + " height=" + info.height + " framerate=" + info.framerate);
}

public function onXMPData(info:Object):void {
trace("onXMPData: " + info.toString());
}

public function onCuePoint(info:Object):void {
trace("cuepoint: time=" + info.time + " name=" + info.name + " type=" + info.type);
}

public function onPlayStatus(info:Object):void {
trace("cuepoint: time=" + info.time + " name=" + info.name + " type=" + info.type);
}
}

Add new comment

randomness