Highlighted

AIR for Android video issue

Participant ,
Sep 29, 2014

Copy link to clipboard

Copied

On Android, in an app that I’ve developed successfully for iOS, I’m seeing this problem:

There are 5 videos built-into the app. On Samsung phones (S3 and S4), running Android 4.4.2, at the first attempt to play a video there’s sound but no picture. After returning to the video menu and attempting again, video and sound play normally. If a video is stopped and another one is started, initially a frame of the previous video is displayed (for a fraction of a second), then play resumes normally with the chosen video.

The sound-but-no-video problem does NOT show up on a Nexus 7 running 4.4.3, although the flash-frame problem does.

I’m publishing with AIR SDK 15 packaging both with and without captive runtime to try to isolate the source of the problem. I’m using <contains video> true </contains video> in the descriptor.

This feels like AIR-for-Android buggishness. Any confirmation out there? Similar problems? Workarounds?

I’ve read somewhere that AIR runtime  v.3.3 may solve some video problems on Android, but not sure where to find an archived Android version of AIR that old.

TOPICS
Development

Views

1.3K

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

AIR for Android video issue

Participant ,
Sep 29, 2014

Copy link to clipboard

Copied

On Android, in an app that I’ve developed successfully for iOS, I’m seeing this problem:

There are 5 videos built-into the app. On Samsung phones (S3 and S4), running Android 4.4.2, at the first attempt to play a video there’s sound but no picture. After returning to the video menu and attempting again, video and sound play normally. If a video is stopped and another one is started, initially a frame of the previous video is displayed (for a fraction of a second), then play resumes normally with the chosen video.

The sound-but-no-video problem does NOT show up on a Nexus 7 running 4.4.3, although the flash-frame problem does.

I’m publishing with AIR SDK 15 packaging both with and without captive runtime to try to isolate the source of the problem. I’m using <contains video> true </contains video> in the descriptor.

This feels like AIR-for-Android buggishness. Any confirmation out there? Similar problems? Workarounds?

I’ve read somewhere that AIR runtime  v.3.3 may solve some video problems on Android, but not sure where to find an archived Android version of AIR that old.

TOPICS
Development

Views

1.3K

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Sep 29, 2014 0
Adobe Community Professional ,
Sep 29, 2014

Copy link to clipboard

Copied

How are you playing the videos?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 29, 2014 0
Participant ,
Sep 29, 2014

Copy link to clipboard

Copied

Not sure that I understand your question, Colin. I'm playing them within the app using StageVideo, which is the class that my app selects with GPU rendering. Is that what you mean?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 29, 2014 0
Adobe Community Professional ,
Sep 29, 2014

Copy link to clipboard

Copied

Yes, StageVideo was the right answer! There are other ways of playing video (StageWebView, FLV via netstream, for example).

I have seen some issues on the lines that you're seeing. I think the big breakthrough for me was when I realized that the event that tells you that there is stage video available sometimes happens before you get to the point of showing the video. In the end I used this approach:

if ( _stage.stageVideos.length >= 1 ) {

  _enableStageVideo();

  }else{

  _stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, _onStageVideoAvailability);

  }

That way, if the stage video availability has happened before you set your listener, the stageVideos length is already greater than zero.

As for seeing the previous video, that's the nature of hardware decoding. The buffer still has the remains of the last frame it showed. I never did this myself, but one option is to always play a silent black video after you close down the real video. Then the next video starts with a buffered black frame, which would be less annoying.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 29, 2014 0
Participant ,
Sep 29, 2014

Copy link to clipboard

Copied

This sounds sensible, I'll try it.

But if you have something like this:

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(x,y,w,h) ;
     video.attachNetStream(stream) ;
     stream.play (mymoov) ;
       stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);

         ...


where the 'stream.play()' is contingent on StageVideoAvailability, how could anything happen 'before you get to the point of showing the video'?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 29, 2014 0
Adobe Community Professional ,
Sep 29, 2014

Copy link to clipboard

Copied

The availability event seems to do the right thing on desktop, but can be enthusiastic on mobile. Roughly speaking, half the time it will fail if you rely on the event happening. So, check the stageVideos length first.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 29, 2014 0
Engaged ,
Sep 29, 2014

Copy link to clipboard

Copied

He was referring to StageVideo being available or not. The availability event may not fire after the event listener is established because it was already made available and so you should just check to see if stage.stageVideos.length has a value that is greater than 0. But since you are using AIR15, StageVideo is supposed to always report as "AVAILABLE" since it now implements an automatic fallback to a Video object if StageVideo is not supported.

On the showing a frame from the previous video, are you calling NetStream.close() before changing videos?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 29, 2014 0
Participant ,
Sep 29, 2014

Copy link to clipboard

Copied

Yes, but not Netstream.dispose(). Trying that now.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 29, 2014 0
Participant ,
Sep 29, 2014

Copy link to clipboard

Copied

Still bad news here. Same buggy video performance.

A few thoughts about this:

1. the idea of stageVideoAvailablityEvent coming before its listener function has a target isn't really making sense. In my testing you get a stageVideoAvailablityEvent only when a target object goes on-stage. So, for instance, when I say in an object's contructor:

addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, stageVideoState );

stageVideoState doesn't fire. Of course, at this point the object has been instantiated but it doesn't yet have a stage. Then when I say

stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, stageVideoState );

   inside of the objects' ADDED_TO_STAGE function, stageVideoState DOES fire.

At that point I set my StageVideo object = stageVideos[0], successfully except for the buggy behavior.

2. The fact that I get less buggy behavior on Android 4.4.3 running on a Nexus7 suggests that the problem is not in the AS3 but rather in the compiled code, doesn't it?

3. Is anyone (Colin, wadedwalker?) getting completely acceptable results running on-board video (not web video) inside of AIR-for-Android apps?

thanks, c.u.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 29, 2014 0
Adobe Community Professional ,
Sep 30, 2014

Copy link to clipboard

Copied

You could try this app I made:

Let’s Get Ready! - Android Apps on Google Play

There are parent tips articles in there that do streaming videos, using StageVideo, and two of the three games use local videos with StageVideo. Because of Google's 50MB APK limit the videos have to be installed using an expansion pack, so the location of the files isn't the standard one.

If you want to try with files that are in the standard location, and you can get the Samsung phones to buy from Amazon (it's a free app), try this version:

Amazon.com: Let's Get Ready!: Appstore for Android

The Amazon one has the videos inside the APK.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 30, 2014 0
Engaged ,
Sep 30, 2014

Copy link to clipboard

Copied

I will try to get around to making a test file to see how it plays out on my Nexus 5, but work and home life has kept me extremely busy. My past work with StageVideo has only been in web, so Android using StageVideo will be new territory for me.

Responding to your first point, events are firing all the time regardless of having an event listener in place. So depending on how a project is setup, it would be possible for the StageVideoAvailibility event to fire before the event listener is established. Below is code I have setup for a Video player I have been working on and off of for a long time.

In regards to having less buggy issues with the Nexus 7 vs Samsung devices, I find that sometimes it is just unique device problems. For example, I built a native extension that lets you get metadata from media files (such as the cover art and duration) without having to play the media file first and wait for the metadata events. On my Galaxy Nexus and Nexus 5, there is a noticeable UI delay when fetching this information. On my wife's P.O.S. Samsung Galaxy Relay 4G that is 2 years old, it is instant with no delay at all.

if (stage.stageVideos.length != 0) {

     _initializeStageVideo()

}

else {

     stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, _onStageVideoAvailability);

}

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 30, 2014 0
Participant ,
Sep 30, 2014

Copy link to clipboard

Copied

Colin, I can't get trouble-free play of your app (via PlayStore) on my Samsung S4. Probably better to give you details less publicly, if you're interested. 

c.u.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 30, 2014 0
Adobe Community Professional ,
Sep 30, 2014

Copy link to clipboard

Copied

You can say things here, if it would be of general interest.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 30, 2014 0
Participant ,
Sep 30, 2014

Copy link to clipboard

Copied

Well, first things first.  The code that you suggested yesterday:

if ( _stage.stageVideos.length >= 1 ) {

  _enableStageVideo();  ...

   seems to have gotten me out of the audio-but-no-video-on-first-play problem that I was having. Thanks, to you and wadewalker.

   I really learned some things there:

   1. that stageVideoAvailabilityEvents are indeed firing earlier than I thought that they were,

   2. that Android and iOS seem to have different behaviors in this regard;

   3. and that this site is a salvation for amateurs like me

Re. your 'Lets Get Ready' app: I had a couple of freeze-type crashes on two separate starts of the app when I first tried it. But just now I've run it for a while with none of that trouble. I do see the same problem I'm having with a 'cached frame' from a previous video stepping on the beginning of a new video. For example (on my S4 running 4.2.2) when I choose a video under 'Preparing your Child' in the 'Emergency Preparedness...' section, then stop it mid-way through and then start another video under 'Talk About It',  I get that annoying 'flash-frame' from the previous video for just a tenth of a second or less, before black and the loading spinner of the new video. Sometimes there are two flash frames from the previous two videos! I'll try this on a Nexus 7 in a bit. You can email me at craig@umanoff.com if you're interested in the result.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 30, 2014 0
Engaged ,
Sep 30, 2014

Copy link to clipboard

Copied

At least some progress is being made and that at least is always nice. Colin here is fantastic at trying to help people on this forum. I try to help in areas that I can, but my expertise is rather limited compared to him.

Colin, I must have skipped over one of your replies because I just realized I posted almost the exact same thing you did for a code sample. My apologies. Not trying to steal your thunder on that one.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 30, 2014 0
Adobe Community Professional ,
Sep 30, 2014

Copy link to clipboard

Copied

I mentioned that I didn't try the playing of a black video as a work around to the video buffer issue. It doesn't happen on iOS, and also doesn't happen on some Android devices. People are only likely to watch the videos once, it might be more annoying if the video played every session.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 30, 2014 0
Umanoff LATEST
Participant ,
Oct 02, 2014

Copy link to clipboard

Copied

Well, as it sometimes happens with me, I have spoken too soon. The answer that I marked as ‘correct’ the other day (Colin, are you there?), seems to be not quite the right answer. At least, it doesn’t solve the video problem that I’m having with some, but not all, Android devices.

After trying Colin’s suggestion – using  if (stage.stageVideos.length != 0) to make sure that a stageVideoAvailabilityEvent hasn’t already fired when I try to play my first StageVideo instance – and getting perfect results in 10 consecutive tries on my Samsung S4 and S3 phones, I figured that was IT.

Next day, same devices and same code, it DIDN’T work! I pulled hair, issued profanities, hammered on the table. It didn’t matter—I still got a ‘mis-fire’ on the first play of a video whenever (almost whenever) I opened the app. After the first play everything was good – which is the exact problem that I started with many days ago. When I played Colin’s Sesame Street ‘Let’s Get Ready’ app again – the same first-play-of-video problem shows up there too.

This problem does not show up on Nexus 7  and the Samsung Galaxy 5 Tab. It is a royal p.i.t.a. on Samsung phones, where I need my app to work.

I created a bare-bones app to reproduce the problem, code below. Just a single class to play a single video with no controls. A few parameters (path to the video, and viewport stuff) are passed in from the document Class. I run it 10 times on my S4. It fails 7 times and plays well 3 times. The 'initialize2()' function never fires, proving that the stageVideos array already exists by the the time the 'initialize1()' function is called.

I'm pretty sure that this is not a coding problem (because it works well on some Androids and in iOS), but WHAT is it??

package vidTestSource

{

  import flash.desktop.NativeApplication;

  import flash.desktop.SystemIdleMode;

  import flash.display.MovieClip;

  import flash.display.Sprite;

  import flash.display.StageAlign;

  import flash.display.StageScaleMode;

  import flash.events.Event;

  import flash.events.NetStatusEvent;

  import flash.events.StageVideoAvailabilityEvent;

  import flash.geom.Rectangle;

  import flash.media.StageVideo;

  import flash.media.Video;

  import flash.media.StageVideoAvailability;

  import flash.net.NetConnection;

  import flash.net.NetStream;

  public class MobileVideosolo extends MovieClip

    {

      public var stream:NetStream ;

      public var video:StageVideo;

      var xx:Number;

      var yy:Number;

      var ww:Number;

      var hh:Number;

      var mymoov:String;

  public function MobileVideosolo(mymoov,xx,yy,ww,hh)

  {

      this.xx = xx;

      this.yy = yy;

      this.ww = ww;

      this.hh = hh;

      this.mymoov = mymoov;

     addEventListener(Event.ADDED_TO_STAGE, onstage);

  }

function onstage(e)

  {

    if (stage.stageVideos.length != 0)

     {

       initialize1();

      }

     else

     {

      stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, stageVideoState );

     }

function stageVideoState(e)

     {

       initialize2();

       stage.removeEventListener (StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, stageVideoState);

     }

function initialize1()

    {

      var nc:NetConnection = new NetConnection() ;

      nc.connect(null) ;

      stream = new NetStream(nc) ;

      stream.client = this ;

      video = stage.stageVideos[0] ;

      video.viewPort = new Rectangle(xx,yy,ww,hh) ;

      video.attachNetStream(stream) ;

      stream.play (mymoov) ;

      MovieClip(parent).sVtext.text = "Init 1";

      stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);

   }

 

function initialize2()

   {

    var nc:NetConnection = new NetConnection() ;

     nc.connect(null) ;

     stream = new NetStream(nc) ;

     stream.client = this ;

     video = stage.stageVideos[0] ;

     video.viewPort = new Rectangle(xx,yy,ww,hh) ;

     video.attachNetStream(stream) ;


     stream.play (mymoov) ;

     MovieClip(parent).sVtext.text = "Init 2";

     stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);

   }

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 02, 2014 0