Skip to main content
Known Participant
March 24, 2011
Question

Instructions to play h.264 video in app in iOS with 2.6.

  • March 24, 2011
  • 3 replies
  • 4584 views

I've been posting around looking for a ton of solutions to figuring out this video playing issue with iPad and iOS apps.  We all know the performance is terrible.  But for now I think I have a pretty good temp solution for you guys who like me didn't think of the obvious, StageWebVideo.

If we just create the WebStageVideo object around the video we want to use and package it up it plays beautifully.  Plus if you call the file and not an html container you can use Apple's beautiful fullscreen scaling at full performance.

First off if you're coming from the Flash CS5 world, start by following this forum...  http://forums.adobe.com/thread/826075?tstart=0

Then once you have actually got 2.6 development up..create an instance of the WebStageVideo and wrap it up with your video...

-Actionscript 3 code-

my stage is set at 1024x768 here...

button1.addEventListener(MouseEvent.CLICK, localVideoExample);
button1.addEventListener(MouseEvent.CLICK, htmlExample);

var webView:StageWebView = new StageWebView();
  var currentLocation:String;
  webView.addEventListener(LocationChangeEvent.LOCATION_CHANGE,getUpdate);
  webView.addEventListener( LocationChangeEvent.LOCATION_CHANGING,getUpdate);
 

function localVideoExample(e:MouseEvent)
{

            webView.stage = this.stage;
            webView.viewPort = new Rectangle(360, 73, 640, 360);
            var filePath:String = new File(new File("app:/TestMovie.mov").nativePath).url;
            webView.loadURL(filePath);
  }
      
function htmlExample(e:MouseEvent)
{

            webView.stage = this.stage;
            webView.viewPort = new Rectangle(360, 73, 640, 360);
            var filePath:String = new File(new File("app:/test.html").nativePath).url;
            webView.loadURL(filePath);
            currentLocation = webView.location();
   }
      
      
     function getUpdate(event:LocationChangeEvent):void
     {
         myArray.text = "New Input Now";
         event.preventDefault();
         myPlace.text = event.location;
        var dataIn = myPlace.text.split("=");
        myArray.text = dataIn[1].toString();
        if(dataIn[1] == "true")
        {   
            webView.stage = null;
            myArray.text = "FULLSCREEN TRUE";
            webView.viewPort = new Rectangle(0, 0, 1024, 576);
            webView.stage = this.stage;
        }else if(dataIn[2] == "false")
        {
            webView.stage = null;
            myArray.text = "FULLSCREEN FALSE";
            webView.viewPort = new Rectangle(360, 73, 640, 360);
            webView.stage = this.stage;
        }    
     }

Also for those who want to communicate back and forth and create custom controls for their videos from AS3 to the web view here's my html file.  I'm still experimenting with all this but I just wanted to give you guys who are having issues a headstart.  Maybe someone can create an awesome player and push it out there! 

-my HTML file-

<!DOCTYPE HTML>
<html lang="en">
<script type="text/javascript" src="jquery.js"></script>
<head>
    <title>Test Video</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="user-scalable=no, width=640, height=360, initial-scale=1.0, maximum-scale=1.0"/>
    <style type="text/css">
        BODY {
            body { margin: 0; padding: 0; }
            }

        /* Video */
        .video {
            position:absolute;
            top:0px;
            left:0px;
            }
            .video VIDEO {
                display:block;
                opacity:.4;
                -webkit-transition:all .2s linear;
                -moz-transition:all .2s linear;
                -o-transition:all .2s linear;
                transition:all .2s linear;
                }
            .video:hover VIDEO {
                opacity:.6;
                }
        .video-on VIDEO,
        .video-on:hover VIDEO {
            opacity:1;
            }
       
        /* Button */
        .video-button {
            position:absolute;
            z-index:1;
            border:none;
            background:#CCC;
            text-indent:-9999px;
            cursor:pointer;
            -webkit-transition:all .2s linear;
            -moz-transition:all .2s linear;
            -o-transition:all .2s linear;
            transition:all .2s linear;
            }
        .video-button:hover {
            -webkit-transform:scale(1.1);
            -moz-transform:scale(1.1);
            -o-transform:scale(1.1);
            transform:scale(1.1);
            }
        .video-button:after {
            position:absolute;
            background:url(buttons.png) no-repeat;
            content:'';
            }

        /* Play */
        .video-play {
            bottom:30px;
            left:30px;
            -webkit-box-shadow:0 0 50px #FFF,
                inset 5px 5px 20px #444,
                inset 0 -20px 40px #000;
            -moz-box-shadow:0 0 50px #FFF,
                inset 5px 5px 20px #444,
                inset 0 -20px 40px #000;
            box-shadow:0 0 50px #FFF,
                inset 5px 5px 20px #444,
                inset 0 -20px 40px #000;
            width:50px;
            height:50px;
            -webkit-border-radius:25px;
            -moz-border-radius:25px;
            border-radius:25px;
            }
        .video-play:after {
            top:15px;
            left:16px;
            width:21px;
            height:21px;
            background-position:0 0;
            }
        .video-play-on:after {
            background-position:-23px 0;
            }

        /* Mute */
        .video-mute {
            bottom:35px;
            left:100px;
            -webkit-box-shadow:0 0 30px #FFF,
                inset 4px 4px 15px #444,
                inset 0 -15px 35px #000;
            -moz-box-shadow:0 0 30px #FFF,
                inset 4px 4px 15px #444,
                inset 0 -15px 35px #000;
            box-shadow:0 0 30px #FFF,
                inset 4px 4px 15px #444,
                inset 0 -15px 35px #000;
            width:38px;
            height:38px;
            -webkit-border-radius:19px;
            -moz-border-radius:19px;
            border-radius:19px;
            }
        .video-mute:after {
            top:13px;
            left:11px;
            width:17px;
            height:14px;
            background-position:0 -21px;
            }
        .video-mute-on:after {
            background-position:-18px -21px;
            }
    </style>
    <script type="text/javascript">
        var videoFS = false;
        function init() {
            var videos = document.querySelectorAll( 'div.video' ),
                videosLength = videos.length;
            for( var i=0; i < videosLength; i++ ) {
                var root = videos;
                    video = root.querySelector( 'video' ),
                    play = document.createElement( 'button' ),
                    mute = document.createElement( 'button' );
                video.controls = false;
                // Initiall class name
                play.className = 'video-button video-play';
                play.innerText = play.title = 'Play';
                play.onclick = function() {
                    if( video.paused ) {
                        video.play();
                        // Additional class names for container and button while playing
                        root.className += ' video-on';
                        play.className += ' video-play-on';
                        play.innerText = play.title = 'Pause';
                    } else {
                        video.pause();
                        // Removing additional class names for container and button in paused state
                        root.className = root.className.replace( ' video-on', '' );
                        play.className = play.className.replace( ' video-play-on', '' );
                        play.innerText = play.title = 'Play';
                    }
                }
                // Initiall class name
                mute.className = 'video-button video-mute';
                mute.innerText = mute.title = 'Mute';
                mute.onclick = function() {
                    if(videoFS == true) {
                        videoFS = false;
                        //document.location = document.location+'#fullscreen:false';
                        document.location.hash = 'fullscreen=false';
                        $('#vidHolder').css("left","0px");
                         $('#vidHolder').css("top","0px");
                         $('#player').css("width","640px");
                         $('#player').css("height","360px");
                        // Removing additional class name in unmuted state
                        mute.className = mute.className.replace( ' video-mute-on', '' );
                        mute.innerText = mute.title = 'Mute';
                    } else {
                        //document.location = document.location+'#fullscreen:true';
                        document.location.hash = 'fullscreen=true';
                        $('#player').css("width","1024px");
                         $('#player').css("height","576px");
                         $('#vidHolder').css("left","0px");
                         $('#vidHolder').css("top","0px");
                        videoFS = true;
                        // Additional class name for button in muted state
                        mute.className += ' video-mute-on';
                        mute.innerText = mute.title = 'Unmute';
                    }
                }
                root.appendChild( play );
                root.appendChild( mute );
            }
        }
        window.onload = init;
    </script>
</head>
<body>
    <div class="video" id=vidHolder>

        <video id="player" controls width="640" height="360">
            <source src="
TestMovie.mov" type="video/mp4">
        </video>
    </div>
</body>
</html>

This topic has been closed for replies.

3 replies

April 14, 2011

Great work!  However, when you try to open up a MP4 in a StageWebView on the iPhone, it goes directly to fullscreen.  What even can you listen for to find out when the "Done" button is pressed in the native video player?  Any figure out a workaround for this?

Known Participant
May 4, 2011

If you write an html page that handles the video and do some javascript handling you should be able to get on complete callbacks.  Then you can pass whatever you need back to your application.

Participant
May 4, 2011

how?

Participant
March 25, 2011

hi!
I have done almost anything i know but i still get the bizarre error – “VerifyError: Error #1014: Class flash.media::StageWebView could not be found.”

what could be wrong?

i followed the instructions carefully...

Known Participant
March 25, 2011

Depending on where you are developing from, in my case in the  example, Flash CS5 you must replace your airglobal.swc.  Otherwise  you'll get an error thrown.

The file in your AIR 2.6  download  ../frameworks/libs/air/airglobal.swc must go into (in my case  Flash CS5 for mac) to Applications/Adobe Flash CS5/Common/Configuration/Actionscript 3.0/AIR2.0/ replacing the airglobal.swc that is there.  Without this you'll be unable to take  advantage of the new API's in 2.6.  You still won't be able to compile  or test this from your IDE but when you compile to the iPhone or iPad  you'll see it working.  Also I have my settings set for AIR.  If you need more help getting 2.6 running I suggest checking out the Adobe iPhone Packager forum from the link above.  It contains all the other instructions.

BTW, I just renamed my old airglobal.swc, just in case  anything goes terribly wrong you still have it, and then I dropped the new airglobal in the aformentioned folder.

I wanted to update and comment, & clean up what I posted but apparently if you start a discussion on the forum you can't edit it?

April 2, 2011

thanks for this tip it works great. The only problem is you can't test it from the flash ide. Is that correct? In my test it runs fine once i put it on the iphone but in ide i can't test anything cause it throws the error? Is there a way to make the error go away so i can test the rest of the app?

Known Participant
March 25, 2011

Also,

http://voisen.org/blog/2010/10/making-the-most-of-stagewebview/

It'll show you how to communicate back and forth locally from javascript to your web app.