My guide to advanced video delivery with AIR for mobile resulted in a lot of interest, but also in the question how to exactly achieve 720p video quality on tablets, and the request for an encoding example with the corresponding player.
Here are two examples applications, one raw player without any framework, and a second with OSMF, both running on an iPad 1 and the Motorola Xoom.
Simple Video Player
package { import flash.desktop.NativeApplication; import flash.desktop.SystemIdleMode; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.StageVideoAvailabilityEvent; import flash.geom.Rectangle; import flash.media.StageVideo; import flash.media.StageVideoAvailability; import flash.net.NetConnection; import flash.net.NetStream; [SWF(backgroundColor="#000000")] public dynamic class AIRMobileVideo_AS extends Sprite { public function AIRMobileVideo_AS() { NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE; NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true) stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE ; stage.addEventListener( StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY , stageVideoState ); } protected var stream:NetStream ; protected function stageVideoState( e:StageVideoAvailabilityEvent ):void { var available:Boolean = e.availability == StageVideoAvailability.AVAILABLE ; if ( available ) { var nc:NetConnection = new NetConnection() ; nc.connect(null) ; stream = new NetStream(nc) ; stream.client = this ; var video:StageVideo = stage.stageVideos[0] ; video.viewPort = new Rectangle( 0, 0, 1280 , 720 ) ; video.attachNetStream( stream ) ; stream.play( "http://www.overdigital.com/video/Hillman_720p23.976_2400kbps.mp4") ; } } public function onMetaData( info:Object ):void { } private function handleActivate(event:Event):void { NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE; } private function handleDeactivate(event:Event):void { NativeApplication.nativeApplication.exit(); } } } |
Source: AIRMobileVideo_AS
Video Player based on OSMF
package { import flash.desktop.NativeApplication; import flash.desktop.SystemIdleMode; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import org.osmf.containers.MediaContainer; import org.osmf.elements.VideoElement; import org.osmf.media.MediaPlayer; import org.osmf.media.URLResource; [SWF(backgroundColor="#000000")] public dynamic class AIRMobileVideo_OSMF extends Sprite { public function AIRMobileVideo_OSMF() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE; NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true) var videoPath:String = "http://www.overdigital.com/video/Hillman_720p23.976_2400kbps.mp4"; var resource:URLResource = new URLResource( videoPath ); var element:VideoElement = new VideoElement( resource ); var mediaPlayer:MediaPlayer = new MediaPlayer( element ); var mediaContainer:MediaContainer = new MediaContainer(); mediaContainer.addMediaElement( element ); addChild( mediaContainer ); } private function handleActivate(event:Event):void { NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE; } private function handleDeactivate(event:Event):void { NativeApplication.nativeApplication.exit(); } } } |
Source: AIRMobileVideo_OSMF
The OSMF version on both tablets.
Considerations
- Ensure videos are mobile optimized, since mobile HW decoders likely don’t support all levels or profiles of H.264. Follow the encoding cookbook, and the mobile encoding guidelines.
- Make sure to use the StageVideo API if you use an AS only approach, or the latest OSMF version which has build-in StageVideo support. Define <renderMode>direct</renderMode> in the Adobe AIR application xml file to enable StageVideo.
- Consider adaptive streaming to adjust to less consistent mobile networks, as example HTTP Dynamic Streaming on Android, or HLS streaming on iOS.
Update 01/27/12: If you use the captive runtime approach, please update Flash Builder/Flash to the latest AIR version for 720p Android playback (AIR 3.1.0.5560 or higher)
Hi, I’m trying to use this in a flex mobile application (flex 4.6).
it work when I test on desktop iPad simulator but not on the devise. I even used your mp4 in order to avoid encoder problem.
I’m non able to make iOS play mp4 video. And can’t get any information on how to do this.
It would be great if you could post a sample code of how to do this with a flex project.
Thanks
@PaoloBernardin1 Does it work on the actual device? The simular could cause some issues, since it’s a simulator, and not a real emulator. With Flex you also need to hide the background (set it 0 alpha) when using StageVideo.
@Jens Loeffler
What if you’re buildiing an as3 mobile project, how do you set the background alpha to 0?
You don’t have to worry about it with AS only, just make sure StageVideo is the lowest layer (no background graphic underneath).
I have been able to get the OSMF sample to work with a progressive download, but not with an HLS stream (sourced from my Wowza streaming server). The same HLS url will play on the iPod Touch / iPad 2 directly in QT player (using browser to load it).
I did alter the OSMF sample to use a media factory to create the media element, but no dice.
@JimInspired Hi Jim. I assume this is on iOS. Did you set renderMode to direct? In addition, does your HLS URL end with .m3u8? Please also make sure you don’t use autoPlay, there is currently an issue.
@JimInspired FYI, I can get HLS stream to play in the non-OSMF sample. I’ve done a bunch of research and from what I can tell, OSMF does not support HLS streams.
@JimInspired Hi Jim, it works – did you check if you followed the tips I mentioned above?
I’m using iPad iOS 5.1 with Flash builder 4.6. I’m trying building an iPad app holding a list and videos in its itemrenderer components.
The code that I’m using to use the StageVideo is working pretty well when using outside the List/itemRenderer component, that means in the same View class. The video is coming as expectedly and playing on iPad. But whenever I’m trying to call the same code inside an itemrenderer object, the app crash.
The code snippets as you described:
var available:Boolean = e.availability == StageVideoAvailability.AVAILABLE ;
if ( available )
{
var nc:NetConnection = new NetConnection() ;
nc.connect(null) ;
stream = new NetStream(nc) ;
stream.client = this;
var video:StageVideo = stage.stageVideos[0] ;
video.viewPort = new Rectangle( 0, 0, 622 , 480 ) ;
video.attachNetStream( stream ) ;
stream.play( new File(new File(“app:/elements/video/FoxTraveller_NIB.mp4”).nativePath).url ) ;
}
I’ve noticed that available field coming as ‘available’ but it instantly crash.
Any help would be highly appreciated! Please.
Thanks & Kind Regards.
@santanu4ver Thanks for sharing, that is pretty odd – could you provide a sample application and file a bug on http://bugs.adobe.com/?
@Jens Loeffler Hi, thanks! Actually it was my fault, a few associated methods with the stream.client which generally ‘not’ requires to explicitly code while in View component but in a ItemRenderer component (here the stream client bind with the ItemRenderer). In my case those methods weren’t present so it was actually crashing while running in device, I found it after debug mode. Now since the methods are not present in the ItemRenderer component, it works as expected. Thanks.
@santanu4ver Great to hear, yes, that’s a pretty common issue once you start defining your own client handler.
Hey,
Thanks for this great article.
I would like to know if I have to use the stageVideo API or if it could work without it. Basically, I would like user could slide video by touching the screen. Thanks !
@starchicken Yes, you have to use StageVideo, otherwise the performance won’t be good. You can move the video object around though by modifying the StageVideo view area – there is an example in this article. http://www.overdigital.com/2012/01/09/the-ultimate-guide-to-understanding-advanced-video-delivery-with-air-for-mobile/
@Jens Loeffler Thanks !
Hi jens, thanks for the article.
I tested the version based on OSMF. In my Ipad runs perfectly. I do not have an Android tablet and failing I used Samsung GT-I9000 Galaxy, the video load but soon after the application quits playing. I do not know if this device is suitable for such applications. Can you say something about it?
Greetings
PD. Sorry for my bad English
@tonilopez It should work – what is the video you are testing with? You could also try to use AIR 3.3 from Adobe Labs – http://labs.adobe.com/technologies/flashplatformruntimes/air3-3/
I’m still not able to make it work in a flash builder project, I get not error, but i can’t see the video play on the device.
would you mind posting a flash builder project sample?
@PaoloBernardin1 You should be able to import the examples into Flash Builder (it was created with Flash Builder). Do you hear audio? Make sure to set renderMode to direct on Android (or direct/gpu on iOS), and if you use the Flex framework, set the background alpha of the application to 0.
@Jens Loeffler Actually I was able to make it work by updating to air 3.2 and to the latest release of osmf.swc.
But the video (i’m using your mp4 as a test) doesn’t run very smooth.
Plus are there any controls available for the mediaplayer or we have to implement it ourselves?
Thanks for you help
@PaoloBernardin1 What device are you testing on? The 720p video only runs smoothly on tablets and ICS, for Android 2.x smartphones you have to follow the Android encoding guidelines (http://www.adobe.com/devnet/devices/articles/encoding-guidelines-android.html) – the smartphone (Android 2.x) rule is basically not higher than 640×360, and no excessive bitrates. Strobe Media Playback has a mobile touch skin, more information here: http://sourceforge.net/apps/mediawiki/osmf.adobe/index.php?title=HTML5_%26_JavaScript_support_for_SMP. Also on Android tablets + ICS, you have to use renderMode direct in the application.xml, otherwise 720p won’t work.
@Jens Loeffler I’m using an IPad2
@PaoloBernardin1 That’s indeed odd, on iPad2 with H.264 the video is just passed to the native player. Maybe it stutters because of insufficient bandwidth?
Thanks for this post.I tried this with rtmp url for playing the live stream.It plays well.But the video doesnot display in full screen rather it display only in corner of the screen..After changing output size in encoder the video enlarges and it doesnot fit in sceen but out of screen..How to make the video display within screen in exact fit to the screen size for any encoder video size?
@divyat That’s really odd. What encoder are you using, and what are your encoder settings?
@Jens Loeffler
I am using FMLE encoder. Format is H.264,Frame rate15.00,Total bandwidth required to stream 248kbps.
I couldn’t display the full video source within the screen but a part of the video only within the screen .
@divyat Did you try the OSMF and the AS only version? At least the AS version should automatically scale, for OSMF you need to set scaling manually.
Thank you Jens Loeffler,
After setting width and height of mediaContainer to the fullscreenwidth and fullscreenheight the video displayed in fullscreen..
@divyat Great to hear!
I imported the sample code into Flash Builder 4.7 beta and deployed it to an iPad2 (iOS 5.1.1) and a ASUS Transformer (Android 4.0.3). I left the mp4 URL as is. It doesn’t work on either device. On the iPad I observe a NetStream NetStatusEvent “NetStream.Play.Failed”. On the ASUS Transformer, I hear audio but see no video.
I also tried playing the mp4 in the default browser on both devices. It plays on the Transformer but not on the iPad.
By the way, on the Transformer, the app exits immediately. I worked around it by commenting out “NativeApplication.nativeApplication.exit()” in handleDeactivate().
This follows right along with a string of problems I have seen with StageVideo which I summarized on the Adobe AIR mobile development forum.
http://forums.adobe.com/thread/1069285
It should definitely work – can you double check if renderMode is set to direct, and you are using the latest AIR runtime?
@Jens Loeffler Yes, renderMode is set to direct in AIRMobileVideo_AS-app.xml:
<renderMode>direct</renderMode>
Yes, I am using the AIR 3.4 SDK:
<application xmlns=”http://ns.adobe.com/air/application/3.4″>
That’s a bit odd, i tested it on the ipad and on the Motorola Xoom. Could you try one of the URLs in this XML files?
http://www.overdigital.com/demos/nab/appDemoSourcesIOS.xml – I also have a more complete example here: http://www.overdigital.com/2012/06/27/source-code-adobe-air-3-3-retina-video-application/
@Jens Loeffler @PaoloBernardin1 I have set the background alpha to 0 in the main application window, but still no luck. Can you please explain where the background should be set to 0
@kolexinfos @PaoloBernardin1 Background alpha 0 is for Flex applications. StageVideo is always at the bottom layer, if you have a colored background, it will overlay the video and you won’t see it (audio only). Do you hear audio at all?
@Jens Loeffler @PaoloBernardin1 I have actually been able to view the video. The challenge as actually that the video element was not been properly be added to the display list which i was able to fix, thanks.
Hi Jens,
Having played around with the StageVideo API a bit now, I have one quick question for you. Is there a way to set the viewport of the classic video object, that AIR has changed into a StageVideo? If yes, I can set it to a 0 width, height rectangle.
I tried setting viewport of stage.stageVideos[0] but no avail.
Thanks,
Pulkit
Hi,
Thank you for your tutorial.
I have tested this “Simple Video Player”,
But I hearing in my Ipad only sound, video is not visible. Ipad Screen is black
Testing with Flash CS6 and Air 3.7
What can I do?
Thanks
baadshahn do you use a background layer? Try to remove it.
Hi Jens,
How do I add controls to the video player based on OSMF? I know I should be able to do this with the Strobe Media Player, but how? Do you have any examples?
Thanks in advance for your help.
@pc Are you looking for a skining language, or can you write your own UI? Strobe has more abstract skinning capabilities. There is also a chrome player, i believe in the OSMF repository somewhere which has a skinning approach.
OSMF is really designed for you to write your own UI code.
Jens Loeffler Thanks for the prompt reply, I can write my own code if I need to I was just looking for an easy example of how to do this.
I found this link http://www.adobe.com/devnet/flash/articles/mastering-osmf-pt2.html and thought it would help. The problem is it seems to be using an older version of the API or something, when I try to include the classes like ControlBG etc it doesn’t work. So I cannot create the control bar UI in the way they describe. Do you know of an examples that use the latest API? I really only need basic functionality play/pause/showing elapsed time etc.
Thanks again.
@pc Jens Loeffler Yes, the API changed a lot since the first version this article was written for. Maybe there is something useful in the example app section? http://sourceforge.net/adobe/osmf/svn/2081/tree/osmf/trunk/apps/samples/framework/
@pc It seems like my responses disappeared, need to check with @livefyre what happened. Did you find a good UI framework?
Hi,
Thanks for the tutorial. I have a demo set up based on your OSMF version of the video player. It works on the simulator and on an iPad. My problem is that seeking does not work on the iPad. In the simulator I can skip to various points in the video as long as it is fully buffered, i.e. the whole movie is buffered. When I test the code on an iPad it doesn’t seem to buffer the video, it just starts playing, and I can’t seek to other points. The only point I can seek back to is 0, therefore starting the video again.
Any thoughts on this?
Thank you.
@biter this is indeed odd – could you try the simple video player code in the example above? Wondering if it is OSMF or content related.
Jens Loeffler Hi Jens, I tried the simple video player. I couldn’t get it to work in the simulator because e.availability == unavailable when I tested the code on my desktop. I’m not sure why this should be, I’m using a new iMac. I ran the code on an iPad and it worked fine but this is not so good for testing.
The OSMF version I created has a sprite to track the buffering. It grows as more of the video is buffered. When the video is fully buffered the scaleX property is 1. In the simulator this works fine, the sprite grows to full width. When I test the code on an iPad the sprite does not grow, so buffering is not happening. I’ve checked the MediaPlayer canBuffer property when running on an iPad and it is true, the canSeek property is also true. Any thoughts on why buffering would not be happening on an iPad? I’m testing on the latest iPad.
@biter Jens Loeffler Some events are not available on AIR for iOS, which is related to how H.264 video playback is implemented on iOS. Under the hood, AIR use the native video framework on IOS, with all it’s features and limitations (e.g. only MP4/MOV or m3u8 playback, not RTMP or HDS). It’s because it was the only way to enable it on iOS, given the API.
When you are testing it on the desktop, it works with the regular model, meaning all events are available.
Here is more official information on this: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html -> Unsupported properties
Hi,
Thanks for the tutorial. I am using Flash Builder 4.7 and Adobe AIR 3.9, will i be able to use your code to play video on my iPad?
Thank you.
Yes, should still work.
Thank you very much!
Hi, thank for this example it’s was so helpful, but when I test it using HLS and HDS links its not work, there are any solution for OSMF to make it work in such links.
Thanks.
and I saw the support list in this page http://www.overdigital.com/2012/01/09/the-ultimate-guide-to-understanding-advanced-video-delivery-with-air-for-mobile/
on android: true into tag -> now it works perfectly with basic as3 classes without flex or StageVideo or OSMF, just AIRSDK 18.0