Almost certainly a crossdomain.xml policy file missing issue where you put your video. The SWF is running from one location which is trying to access content on a different domain/server which is restricted unless you tell Flash that is ok. You can get a sample file here, along with the reason the content is restricted:
Otherwise put the mp4 in the dropbox and load it relative in the SWF (e.g. ns.play('myvideo.mp4');).
Thanks for replying, sinious. Things have gotten more interesting. I had been using the "import video menu" (fig 1 below), but decided to poke around Adobe AS resources for code and found this:
1. var nc:NetConnection = new NetConnection();
4. var ns:NetStream = new NetStream(nc);
5. ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
7. function asyncErrorHandler(event:AsyncErrorEvent):void
9. // ignore error
12. var vid:Video = new Video();
In the unlikely case that it needs pointing out, my knowledge of code is poor. I replaced the string in parenthesis in line six with the dropbox address, put the above code in a keyframe on my actions layer where I want the video to start playing, then uploaded the SWF/html and mp4 to dropbox. It ended up playing, but there were serious issues. First, the SWF seemed to ingore a preloader. A "play" button is only supposed to present itself, when loading is complete, but it presented immediately. Nothing happened when the button was pushed. A while later (I guess after loading actually finished) the mp4 spontaneously started playing. Additionally, the swf is relatively large (1280 x 720), but the mp4 that played was scaled way down (320 x 240). How can I stop the mp4 from being scaled down, and why is the preloader being ignored? The preloader works fine with other SWFs, but this case is different.
Finally, do I still need to address the cross domain issue? The difference in the urls is the suffix (.mp4 and .swf), so I'm guessing that they reside on separate sub-domains. So after looking over the link you provided, I guess the category "a public server that allows data access from any domain" might apply? Do I just upload the relevant policy file as an xml to the same Google drive or Dropbox as everything else?
Thanks again for all your help.
This was the orig method I was using, before I tried the code above:
You must still have a FLVPlayback component on your stage if you see any play controls. The other method you used (which is what FLVPlayback component does for you) has controls built in, but the code version does not, and 320x240 is the default size of a "new Video()".
You should remove the FLVPlayback component because you're not using it. The only problem now is you're going to need some controls for your video.
Before going any further, you may want to consider simply serving people a link directly to your MP4. If they have something like Quicktime installed the video will play directly in their browser with play controls, no extra work necessary. If they don't have a plugin to play the MP4 in their browser it will ask them to save the MP4 locally and then they can play it back with their OS's default media player (Windows Media Player, Quicktime, VLC, etc).
If that option doesn't work for you let me know. To give you a quick tip, the way you're doing it now can be amended to just "display" the video at the correct size if you change this one line:
var vid:Video = new Video();
var vid:Video = new Video(1280,720);
Be sure to remove the FLVPlayback however, it's not in use if you're playing a MP4.
You could just put in a play button to restart the video from 0 if you don't want to get heavy on coding by making a play button and adding it to the stage while setting the proper values on your NetStream:
e.g. play buttons instance name (under or on the side of the video) is "play_btn":
ns.seek(0); // remove this line if you don't want to start the video over when pressed
And pause would similarly be (pause_btn instance name):
Seek is more involved..
Thanks for the display size tip, sinious! The size is fixed.
"You must still have a FLVPlayback component on your stage if you see any play controls."
No, the play button is presented by a preloader I regularly use. I deleted the FLVPlayback component before going with the code route.
1. In your play button code, "ns.seek(0)" determines the starting point, right? So whatever value I replace zero with would become new starting point, and if I remove the line entirely, it will start from the paused position?
2. The naked mp4 does indeed play in browsers without any swf, but that prevents me from including a preloader. I'd like the video to pause on an introductory frame, while everything loads/buffers, then present a play prompt for viewers to use. In the past this has been pretty easy, but it seems that in this case the preloader is presenting the play button as soon as the swf container loads, but not taking the mp4's load time into account. I can't figure out how to tell the preloader to wait for the mp4. It is also ignoring a "gotoAndStop(1)" at the end of play, and instead remains on the last frame of the mp4.
3. It doesn't seem like the cross domain thing is an issue in this case, but I do appreciate that information as well, because in the future it will be very helpful to load a small swf on a site with strict size restrictions and have it call up a larger mp4 from an outside host.
Edit: the preloader is using "loaderInfo.bytesLoaded/loaderInfo.bytesTotal" to determine when loading is complete, but that's only returning information on the swf without the mp4.The way it's set up now, the preloader stops play on frame one, then presents a play button after the swf loads. Pressing the play button advances the timeline to frame two where the action calling the mp4 is initiated. I tried moving this action to frame one as well, with no change. If it makes sense to ask this, how do I return information on the load status of the mp4, and incorporate that into the preloader?
Yes seek(#) works in seconds, and you can use fractions like seek(20.5);.
To assure the video button only appears when you want it to, the buffer is an easy way to know.
Set the buffer size you'd like on the NetStream with bufferTime:
ns.bufferTime = 10; // buffer 10 seconds of video
The default is 0.1 (or basically no buffer).
Here's a caveat. During progressive (non-streaming-server) playback, any time a person seeks to a new position in the video, if the video hasn't downloaded the number of seconds you specify in the buffer beyond where they seek, this event will occur again letting you know the buffer filled up again. You don't want your play button accidently showing up again so for your homework you should devise a plan so you'll know if the play button should show up only once in the beginning or every time the buffer is full. A second hint is if the users connection is slow a buffer may run out, requiring it to fill back up, firing off the buffer full event again.
You'll want a listener on the NetStream object of type NetStatusEvent, listening for "NetStream.Buffer.Full", indicating that there is your desired amount of video in the buffer from your current playhead position to begin playback.
You should be listening to the NetStreams NetStatusEvent for a variety of codes you can find i n the link above as well (play start, stop, etc).
An example of a listener:
if (event.info.code == "NetStream.Buffer.Full")
// show play button
I've revisited this issue, after reviewing more resource material, but still can't manage to use the buffer to drive a load display. This is what I've tried:
24. ns.bufferTime = 10;
26. var timer:Timer = new Timer(100);
27. timer.addEventListener(TimerEvent.TIMER, checkBufferLength);
30. function checkBufferLength(event:TimerEvent):void
32. var bufferPercent:Number = ns.bufferLength/ns.bufferTime;
33. progressBar_mc.scaleX = bufferPercent;
With the above code, the progress bar never scales (remains at zero). The video does eventually load and presents my play/pause button. The video plays and the play/pause button works fine as well as code to loop to the beginning:
if (event.info.code == "NetStream.Play.Stop")
I also tried setting ns.bufferTime equal to the total video length and replacing line 32 with:
var bufferPercent:Number = ns.bytesLoaded/ns.bytesTotal;
With this method, the progressBar did scale (and scale relatively fast), but the video didn't start when the bar finished scaling. The video took its own sweet time, and seemed to be independent of whatever the bufferPercent was measuring in this case. The progress bar also scaled slightly beyond it's full length, and poked out of the container, mocking my efforts. I'm probably missing something obvious, but while there is a litany of resource material available for normal preloaders, I can't find much that covers measuring NetStream buffering. Thanks!
Halelujah, I figured it out!!
In case the info is useful to anyone else:
The index information that flash needs to make the NetStream bufferTime and bufferLenth properties usable, has to be at the front of the outside video file that your SWF is calling up. Unfortunately for standard MP4's, this information is usually at the back/end of the file. So in many cases, regardless of what bufferTime you set, the video will not play until it has downloaded in it's entirety. However, there are several third party utilities that can move the necesary information to the front. "Any Video Converter" did this and reduced file size by 40% wih no noticeable quality loss. Alternatively, you can use an F4V format. I was able to export a high quality F4V copy of the file, using After Effects (AE kicks butt!), that worked perfectly using the code in response 8 ( var bufferPercent:Number = ns.bufferLength/ns.bufferTime; ). Finally, the reason the progress bar scaled beyond it's container, was that I had created it in Photoshop then scaled it down after import into flash, so setting the scaleX equal to bufferPercent was returning it's x dimension to the original pre-import size. Dividing bufferPercent by the same factor used when scaling down the original import resolved this error.
Special thanks to Sinuous without whom I'd still be completely lost