Play MP3 in AIR app for iOS and Android - actionscript-3

I was wondering if someone could shed some light on the best method to embed, select and play audio files in an AIR app built for iOS and Android?
I have an app where a user can select a file to play from a list of 10 audio files. These are selected when a slider moves left or right.
I currently would create 10 individual embed snippets and classes
[Embed(source="assets/audio/file1.mp3)]
public static const file1:Class;
[Embed(source="assets/audio/file2.mp3)]
public static const file2:Class;
...
And then in the app initialise each class so I can reference them. Then simply call
file1.play();
Issue is this only plays the sound once where I would like the sound to look until the user selects another sound.
I guess a couple of questions:
1. Is having 10 embed/classes the best way to handle 10 different MP3 files?
2. How would I loop the MP3 seamlessly
Thanks

You stored Array or Vector mp3 files URL which user selected. and playing mp3 filed ended. load next URL from Array, Vector.
var sound:Sound = new Sound();
var soundChannel:SoundChannel;
var currentIndex:int = 0;
var mp3List:Vector.<String> = new Vector.<String>();
//only stored user selected mp3 url
sound.addEventListener(Event.COMPLETE, onMp3LoadComplete);
sound.load(mp3List[currentIndex]);
function onMp3LoadComplete(e:Event):void
{
sound.removeEventListener(Event.COMPLETE, onMp3LoadComplete);
soundChannel = sound.play();
soundChannel.addEventListener(Event.SOUND_COMPLETE, onSoundChannelSoundComplete);
}
function onSoundChannelSoundComplete(e:Event):void
{
e.currentTarget.removeEventListener(Event.SOUND_COMPLETE, onSoundChannelSoundComplete);
currentIndex++;
if(currentIndex==mp3List.length) currentIndex = 0;
sound.load(mp3List[currentIndex]);
soundChannel = sound.play();
sound.addEventListener(Event.COMPLETE, onMp3LoadComplete);
}

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.

AS3 browse and load video

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.

Got my external NetStream working - but how to load an .flv from my library?

How do I load an .flv (lets call it "library.flv") sitting in my (internal) Flash library into my Netstream?
I can easily load external .flv's with the below, but I need to load the .flv from my library
//Creating the video object
var ADFvideo = new Video(110,180);
videoContainer.addChild(ADFvideo);
ADFvideo.x = 0;
ADFvideo.y = 0;
//Loading the flv into the video object
var ADFnc:NetConnection = new NetConnection();
ADFnc.connect(null);
var ADFns:NetStream = new NetStream(ADFnc);
ADFvideo.attachNetStream(ADFns);
//Handling metaData (it arrives as the video starts playing, so it is the pefect time to fire the first event);
var ADFcustomClient:Object = new Object();
ADFcustomClient.onMetaData = ADFmetaDataHandler;
ADFns.client = ADFcustomClient;
var ADFinfoObj:Object;
function ADFmetaDataHandler(ADFinfo:Object):void
{
//meta stuff
}
ADFns.play("files/external.flv"); /* current way of loading the external .flv */
ADFns.addEventListener(NetStatusEvent.NET_STATUS, statusChanged);
function statusChanged(stats:NetStatusEvent)
{
//event changes
}
I don't think you can use NetStream with an embedded flv video. When you import the video to your library, you will have the option to convert it to a movieclip or to keep it as a simple video that will sit on the timeline. For the later option, you can't create an AS Linkage. It is not recommended for longer clip as you will experience syncronisation issue, playback problem and pre-loading issues.
You could try this adjustment of your posted code as a starting point.. Tested using 3-second video (H.263 / Sorenson) of 1280 width by 720 height with 44100hz 128 MP3 sound and there was no "..experiencing sluggish behaviour" on my side with a crappy testing machine.
When the video ends you need to use your function statusChanged(stats:NetStatusEvent) to handle what happens next (I've edited the code to do constant replays as example)
Anyway this code means the final compiled SWF and FLV exist as one package. So a 200kb FLV will add +200kb to the output SWF size. Just bear in mind especially with large / multiple FLV embeds.
//// Specify embed item and create Class to store such item
[ Embed(source = "yourFileName.flv", mimeType = "application/octet-stream") ]
var bytes_FLV : Class;
//// End embedded item setup
//create bytes for NStream from embedded item
var file_BA:ByteArray = new bytes_FLV();
//Creating the video object
var ADFvideo = new Video(110,180);
videoContainer.addChild(ADFvideo);
ADFvideo.x = 0;
ADFvideo.y = 0;
//Loading the flv into the video object
var ADFnc:NetConnection = new NetConnection();
ADFnc.connect(null);
var ADFns:NetStream = new NetStream(ADFnc);
ADFvideo.attachNetStream(ADFns);
//Handling metaData (it arrives as the video starts playing, so it is the pefect time to fire the first event);
var ADFcustomClient:Object = new Object();
ADFcustomClient.onMetaData = ADFmetaDataHandler;
ADFns.client = ADFcustomClient;
var ADFinfoObj:Object;
function ADFmetaDataHandler(ADFinfo:Object):void
{
//meta stuff
}
///ADFns.play("files/external.flv"); /* current way of loading the external .flv */
//Send file_BA to NStream for playback..
ADFns.play(null);
ADFns.appendBytesAction(NetStreamAppendBytesAction.RESET_BEGIN);
ADFns.appendBytes(file_BA);
ADFns.addEventListener(NetStatusEvent.NET_STATUS, statusChanged);
function statusChanged(stats:NetStatusEvent)
{
//event changes
//trace("NetStream Status : " + stats.info.code);
if (stats.info.code == "NetStream.Buffer.Empty")
{
//Buffer.Empty = video has ended..
ADFns.appendBytesAction(NetStreamAppendBytesAction.RESET_BEGIN);
ADFns.appendBytes(file_BA);
}
}

How to play a video while it is loading in Flash AS3?

I have a problem in Flash with AS3 to playing a video mp4, this is a H.264 video with AAC, I try to play video while it is loading as any web site, but my code doesn't work, I have two codes:
Using FLVPlayback:
var par:Object = LoaderInfo(this.root.loaderInfo).parameters;
//vidRepFla is my FLVPlayback
vidRepFla.addEventListener(VideoEvent.READY,vid_ready);
vidRepFla.addEventListener(VideoProgressEvent.PROGRESS,vid_progress);
vidRepFla.isLive = true;
vidRepFla.bufferTime = 1;
vidRepFla.play(par.source);
function vid_ready(e:VideoEvent):void{
trace('Playing!');
vidRepFla.play();
}
function vid_progress(e:VideoProgressEvent){
trace(e.bytesLoaded);
}
Using NetStream:
var par:Object = LoaderInfo(this.root.loaderInfo).parameters;
var video:Video;
var connect_nc:NetConnection = new NetConnection();
connect_nc.connect(null);
var stream_ns:NetStream = new NetStream(connect_nc);
stream_ns.client = this;
video = new Video();
addChild(video);
stream_ns.bufferTime = 1;
video.attachNetStream(stream_ns);
stream_ns.play(par.source);
Do you know if I need something more or if this type video don't work the bufferTime?
Thanks!
I work with Netstream and use a different method. I did notice something on the Adobe documentation for this. I read that the bufferTime setting Only works on flv files, this could be the problem since you are using mp4.
More information here:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html

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).