AS3 browse and load video - actionscript-3

I'm currently working on a AS3 AIR project which involves allowing the user to browse a video file and load that same video onto the stage. I've managed to allow the user to browse for a video file type and according to my traces it completes loading the video but this is as far as I've got. There is plenty of tutorials which involve how to load video files from local sources or external links but nothing to show me what to do with a browsed file to display it on the stage. Here is the code so far for browsing to the video file:
private function browseVideo():void {
fileReference = new FileReference();
fileReference.addEventListener(Event.SELECT, videoFileSelected);
var videoTypeFilter:FileFilter = new FileFilter("Video files", "*.3g2; *.3gp; *.asf; *.asx; *.avi; *.flv; *.m4v; *.mov; *.mp4; *.mpg; *.rm; *.swf; *.vob; *.wmv;");
fileReference.browse([videoTypeFilter]);
}
private function videoFileSelected(e:Event):void {
fileReference.addEventListener(Event.COMPLETE, onVideoFileLoaded);
fileReference.addEventListener(IOErrorEvent.IO_ERROR, onVideoFileLoadError);
fileReference.load();
}
function onVideoFileLoaded(e:Event):void {
var fileReferenceTarget:FileReference = e.target as FileReference;
var data:ByteArray = fileReferenceTarget["data"];
fileReference.removeEventListener(Event.COMPLETE, onVideoFileLoaded);
fileReference.removeEventListener(IOErrorEvent.IO_ERROR, onVideoFileLoadError);
var videoLoader:Loader = new Loader();
videoLoader.loadBytes(data);
videoLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onVideoLoaderComplete);
trace("video file loaded");
}
function onVideoFileLoadError(e:Event):void {
fileReference.removeEventListener(Event.COMPLETE, onVideoFileLoaded);
fileReference.removeEventListener(IOErrorEvent.IO_ERROR, onVideoFileLoadError);
trace("video file load failed");
}
function onVideoLoaderComplete(e:Event):void {
var loadedContent:DisplayObject = e.target.content;
var loader:Loader = e.target.loader as Loader;
scope.addChild(loader);
}

To play a video using AS3 ( Flash ) you can use a Video object on which you can attach a NetStream object, you can also use an FLVPlayback component. For flex, take a look on my answer of this question where I put an example of playing a video stream. And in all cases, I think that you don't need a FileReference object because a File is suffisant to get the path of your local file and then play it with any manner you want.
Take a look on this example :
function browseVideo():void {
var file:File = new File();
file.addEventListener(Event.SELECT, videoFileSelected);
file.browse([videoTypeFilter]);
}
function videoFileSelected(e:Event):void {
playVideo(e.currentTarget.nativePath);
}
function playVideo(video_path:String){
// using a Video + NetStream object
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.client = this;
var video:Video = new Video();
video.attachNetStream(ns);
addChild(video);
ns.play(video_path);
// using an FLVPlayback component inserted on the Stage
flvplayback.load(video_path);
flvplayback.play();
}
For more details on how to work with video, you can take a look here, you can find all what you need to know about video ( loading videos, supported formats, cue points, ... ).
Hope that can help.

Related

Play mp4 sound in flex

I am working on audio player which play sound of mp4 file format.
This audio file are of recorded files by user, which will play in audio player later.
And another thing is mp4 file url is rtmp not http which is like:
rtmp://domain/vod/mp4:foldername/filname.mp4
I have done following things:
<s:Button id="btnPlay" label="Play" click="Play_clickHandler(event)" />
AS:
public var sound:Sound;
public var mySoundChannel:SoundChannel;
protected function Play_clickHandler(event:MouseEvent):void
{
sound = new Sound();
sound.addEventListener(Event.SOUND_COMPLETE, soundComplete);
var req:URLRequest = new URLRequest("rtmp://domain/vod/mp4:foldername/filname.mp4");
sound.load(req);
mySoundChannel = sound.play();
}
private function soundComplete(event:Event):void {
sound.load(new URLRequest("rtmp://domain/vod/mp4:foldername/filname.mp4"));
mySoundChannel = sound.play();
}
I Have tried above code but didn't succeed. It played only mp3 file format.
Any way i can play this file?
Note: I do not want to convert file to mp3 file format using any method.
I have tried to play this file in VideoPlayer. It works but design looks bad.
FYI:
Audio file format is:
Any help is greatly appreciated.
You can not use a Sound object to play the audio of an RTMP stream like that.
But to do that, I think that the easiest way is to use a NetStream object and with its receiveVideo() function, you can receive just the audio stream, also you don't even need any video player to be attached to it.
Take a look on this example :
var server:String = 'rtmp://localhost/vod',
stream:String = 'mp4:video.mp4',
nc:NetConnection,
ns:NetStream;
function init(): void
{
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, on_NetStatus);
nc.connect(server);
}
function on_NetStatus(e:NetStatusEvent): void
{
if(e.info.code == 'NetConnection.Connect.Success'){
ns = new NetStream(nc);
ns.receiveVideo(false);
ns.play(stream);
}
}
init();
Hope that can help.

How to load image to swf which is loaded into other swf? (AIR, AS3)

I have an application in AIR, which is loading swf files and makes previews of them. When those swfs loads other content (eg. jpg) then i have an error, that url not found - i am convinced that is about jpg file. This problem shows only when i load swf by filereference using loadBytes(). When i load swf by Loader using load() - problem doesn`t exist. How can i fix this issue? Sorry for my english. I attach code fragment with loading swfs.
private static function loadFile(loadType:String, swfNum:Number = 0):void {
lc = new LoaderContext();
lc.allowCodeImport = true;
lc.allowLoadBytesCodeExecution = true;
currentSwfNum = swfNum;
var fRef:FileReference = DataBase.swfsList[currentSwfNum];
fRef.addEventListener(Event.COMPLETE, onFileReferenceLoad);
fRef.load();
}
private static function onFileReferenceLoad(e:Event):void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, ifComplete);
loader.loadBytes(e.target.data, lc);
}
private static function ifComplete(e:Event):void {
var mc:MovieClip = LoaderInfo(e.target).content as MovieClip;
mc.addEventListener("SHOOT", SwfSingleCapture.captureSingleShoot);
}
DataBase.swfList - it is an array of FileReference objects, which are selected by FileReferenceList and browse().

Preload a bit of FLV or F4V with the main project loader

My project has a main loader that load all the assets for the project. I need to load a bit of my video with it.
The video has 16mb, i want to load 3mb to use after the main loader is completed.
I've tried to open a new connection using Netconnection/Netstream to load 3mb and close the connection, but when the project starts and the video is played, a new connection is opened loading it from beginning.
I'm trying to find a way that i can use those 3mb already loaded. Doing this way, the user don't need to wait a main loader and a secondary loader (buffertime).
That's my code, sorry guys.
var loader:Loader = new Loader();
var nc:NetConnection = new NetConnection();
var ns:NetStream = new NetStream(nc);
var client:Object = new Object();
var swfRatio:Number;
var videoRatio:Number;
function init():void
{
nc.connect(null);
client.onCuePoint = cuePointHandler;
client.onMetaData = metaDataHandler;
ns.client = client;
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressLoader);
addEventListener(Event.ENTER_FRAME, progressTotal);
loader.load(new URLRequest("swf/main.swf"));
ns.play("f4v/main_movie.f4v");
ns.pause();
}
function progressLoader(event:ProgressEvent):void
{
swfRatio = (event.bytesLoaded / event.bytesTotal);
}
function progressTotal():void
{
//Here i get the amount that i want to preload from my video, in this case i want 3mb or 3072000 bytes
videoRatio = (ns.bytesLoaded / 3072000);
//This is a variable that i use to fill my loader asset and verify if my content its totaly loaded.
var frameValue:int = ((videoRatio + swfRatio) / 2) * 100;
if (frameValue >= 100)
{
removeEventListener(Event.ENTER_FRAME, progressTotal);
// Here i close my connection, i suppose that i need to use the same connection in my player.
ns.close();
ns = null;
nc.close();
nc = null;
loaderComplete();
}
}
function loaderComplete():void
{
removeChild(assetLoader);
//Here i add my player to the stage, i want to use the preloaded video with him.
addChild(loader.content);
}
function cuePointHandler(infoObject:Object):void {
trace(infoObject.name);
}
function metaDataHandler(infoObject:Object):void {
trace("metaData");
}
Then in my player that i've just loaded and added to the stage i'm using OSMF to help me with controls.
To test the "preloaded video" i'm doing this:
private var mediaPlayer:MediaPlayerSprite;
private function _init(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE, _init);
mediaPlayer = new MediaPlayerSprite();
addChild(mediaPlayer);
//And here OSMF start to load the entire main_movie.f4v again.
mediaPlayer.resource = new URLResource("f4v/main_movie.f4v");
}
It looks like your strategy would work if you let the video download completely. I'm assuming if the video downloaded completely, the browser may cache it and make it available to the next NetStream that comes along.
Your strategy looks OK otherwise. What you are doing (playing, then pausing the video immediately) is the way to start buffering the video. But since there are two NetStream's being used (one by the main loader, the other by the OSMF player) this won't work.
Perhaps you can devise a scheme where you pass the NetStream from the main loader into the loaded SWF (main.swf). So that it can use the data it's already downloaded. Just a thought, I've never tried this.
Another idea would be to get the OSMF player in your main.swf to do the buffering. That would mean the buffering would start happening only after main.swf is loaded (which may be too late).

AS3 - XML Playlist with Single-Track Looping

So this one has me stumped. My plan for my website is to have music tracks pulled from an XML file which act as the background music for the various .swfs loaded by the menu buttons. I.e. hit 'Home', and it takes you back to the home .swf and plays the appropriate music. I want to do this through XML rather than attaching the music directly to the .swf to cut down on load time (syncing isn't a concern), as I can't seem to retain audio quality without bulking up the .swf significantly.
I'm encountering two problems: one is that with the current code, the music only plays once, and doesn't loop. The other is that I want the functionality to play one song as an intro, and then continue to loop another. I.e., hit the home button, intro plays, followed by the looping section, and never returns to the intro unless you hit home again. I can't seem to figure out how to manage either of these things short of creating a unique function for every single button.
Here's the code I'm using:
var my_songs:XMLList;
var my_total:Number;
var my_sound:Sound;
var my_channel:SoundChannel;
var current_song:Number;
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("playlist.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
function processXML(e:Event):void {
var myXML:XML = new XML(e.target.data);
my_songs = myXML.SONG;
my_total = my_songs.length();
//playSong(0);
myXMLLoader.removeEventListener(Event.COMPLETE, processXML);
myXMLLoader = null;
}
function playSong(mySong:Number):void {
var myURL = my_songs[mySong].#URL;
if (my_channel) {
my_channel.stop();
my_channel.removeEventListener(Event.SOUND_COMPLETE, playSong);
}
my_sound = new Sound();
my_sound.load(new URLRequest(myURL));
my_channel = my_sound.play();
my_channel.addEventListener(Event.SOUND_COMPLETE, playSong);
}
test_btn.addEventListener(MouseEvent.CLICK, onPlay);
function onPlay(e:MouseEvent):void {
playSong(0);
}
Thanks in advance for any help you can give!
YourSongstarting(0,999); // how ever you call to play the song
This above will repeat song forever. I suggest you stream the audio file as this will load the song quicker, then you can keep the songs in memory.you can still use xml or any other external textfile for the audio tracks locations or directly in flash/class files if this site is concrete.
any events you wold like to control simply compare the "Buffer" value out of 100%.Look up streaming audio as3 there are plenty of tutorials with source code if need be let me know i can give you an example.
You were close
var my_songs:XMLList;
var my_total:Number;
var my_sound:Sound;
var my_channel:SoundChannel;
var current_song:Number;
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("playlist.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
function processXML(e:Event):void {
var myXML:XML = new XML(e.target.data);
my_songs = myXML.SONG;
my_total = my_songs.length();
playSong(0);
myXMLLoader.removeEventListener(Event.COMPLETE, processXML);
myXMLLoader = null;
}
function playSong(e:Event):void {
if( current_song > my_total )
current_song = 0;
var myURL = my_songs[current_song++].#URL;
if (my_channel) {
my_channel.stop();
my_channel.removeEventListener(Event.SOUND_COMPLETE, playSong);
}
my_sound = new Sound();
my_sound.load(new URLRequest(myURL));
my_channel = my_sound.play();
my_channel.addEventListener(Event.SOUND_COMPLETE, playSong);
}
test_btn.addEventListener(MouseEvent.CLICK, onPlay);
function onPlay(e:MouseEvent):void {
playSong(e);
}

loading images and video in AIR without HTTP

I'm curious what the correct methodology is for loading image and video data directly from the file system, without employing HTTP.
I'm writing an AIR slideshow application, and it works great but currently relies on a local MAMP server to hand the app all the media via the standard, tried and true, FLASH media loading methodologies.
I know that since FLASH was developed as a web plugin it handles this way of receiving data best, but I'd really like to extricate this rather onerous and unnecessary bit and have the app as a stand-alone player, however, I'm unclear what the "correct" way is to load the media.
I have the File objects ready and I've gotten as far as having the user select the local directory from which to pull the media and I'm getting a list of the files (based on their extensions) from the list... but now what?
You first have to put the content of your file in a ByteArray (code from FileStream documentation)
var bytes:ByteArray = new ByteArray();
var myFileStream:FileStream = new FileStream();
var myFile:File = File.documentsDirectory.resolvePath("test.jpg");
myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler);
myFileStream.openAsync(myFile, FileMode.READ);
function progressHandler(event:ProgressEvent):void
{
if (myFileStream.bytesAvailable)
{
myFileStream.readBytes(bytes, myFileStream.position, myFileStream.bytesAvailable);
}
else
{
myFileStream.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
loadImage();
}
}
Then you may load these bytes in a Loader to display the image (see method Loader.loadBytes)
function loadImage():void
{
var loader:Loader = new Loader();
loader.loadBytes(bytes);
addChild(loader);
}
Cheers
With this code the Loader fires the Event.COMPLTE event and you will be able to manipulate the Bitmap from it:
var bytes:ByteArray = new ByteArray();
var myFileStream:FileStream = new FileStream();
var myFile:File = File.documentsDirectory.resolvePath(YOUR_PATH);
myFileStream.addEventListener(Event.COMPLETE, fileCompleteHandler)
myFileStream.openAsync(myFile, FileMode.READ);
function fileCompleteHandler(event:Event):void
{
myFileStream.readBytes(bytes);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
loader.loadBytes(bytes);
function imageLoaded(e:Event):void
{
addChild(Bitmap(loader.content));
myFileStream.removeEventListener(Event.COMPLETE, fileCompleteHandler);
myFileStream.close();
}
}
PS: Thanks Kodiak, I made my code based on yours.