I'd like to know if it's possible to play a youtube video inside an AIR app using AS3 code.
It seems that youtube API is deprecated...
If anybody knows a way or a good tutorial.
Thx
----------------EDIT
I've tried this code :
var wt:uint;
var ht:uint ;
var webview:StageWebView ;
var rect:Rectangle;
var url:String;
url = "https://www.youtube.com/watch?v=hFupHx5G44s";
trace(url);
wt = this.stage.stageWidth;
ht = this.stage.stageHeight;
webview = new StageWebView();
rect = new Rectangle(0,300,wt,ht/2);
webview.stage = this.stage;
webview.viewPort = rect;
webview.loadURL(url);
But it's loading the all page of youtube (youtube video + the recommended videos..) with a scroller on the right.
I'd like to load only the video (not all the youtube page).
Edit :
I'd like to load only the video (not all the youtube page).
Use this link format :
url = "https://www.youtube.com/v/hFupHx5G44s";
for example, choose a format like below :
https://www.youtube.com/v/hFupHx5G44s - use the /v/ to get a SWF version
https://www.youtube.com/embed/hFupHx5G44s - use the /embed/ to get a HTML5 version
It's for an ANDROID AIR app.
You should have mentioned that detail in the question. You could try adding
Security.allowDomain("www.youtube.com");
Security.loadPolicyFile("https://www.youtube.com/crossdomain.xml");
//////////# End of Edit
Why not use stageWebView to load the embed (HTML5) player as web page?
The YouTube AS3 API being deprecated likely means you cannot create your own user interface or use features like search. You can re-create the search function easily though (load "search results" source into String and extract links by parsing the source code).
Anyways, I just tried this code below and it worked for an AIR Desktop App.Maybe you can use it as a starting point...
package
{
import flash.display.MovieClip;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.net.URLRequest;
import flash.events.*;
import flash.system.*;
public class Youtube_AIR_code extends MovieClip
{
public var YT_Loader : Loader;
public var my_VIDEO_ID : String = "hFupHx5G44s"; //# the YouTube ID
public function Youtube_AIR_code ()
{
Security.loadPolicyFile("http://www.youtube.com/crossdomain.xml");
YT_Loader = new Loader();
YT_Loader.contentLoaderInfo.addEventListener(Event.COMPLETE, YT_Ready );
YT_Loader.load( new URLRequest("http://www.youtube.com/v/" + my_VIDEO_ID) );
}
function YT_Ready (e:Event) : void
{
trace("YouTube SWF :: [status] :: Loading Completed");
//addChild(YT_Loader);
//# Wait for Youtube Player to initialise
YT_Loader.content.addEventListener("onReady", on_YT_PlayerLoaded );
}
private function on_YT_PlayerLoaded (e:Event) : void
{
//# Check Original Width/Height - Scale it proportionally
trace( "YT_Loader content Width : " + YT_Loader.content.width );
trace( "YT_Loader content Height : " + YT_Loader.content.height );
//# Testing changed size and position
YT_Loader.width = 320; YT_Loader.height = 240;
YT_Loader.x = 30; YT_Loader.y = 100;
addChild(YT_Loader); //# can add to stage only
}
} //# End Public Class
} //# End Package
Have you seen the Video Player ANE from My Flash Labs?
http://www.myflashlabs.com/product/video-player-ane-adobe-air-native-extension/
Related
I'm trying to use ExoPlayer instead of MediaPlayer because it's a common bug that MediaPlayer returns wrong getCurrentPosition() and I need a substitute.
But I can't find an info anywhere how to open a local file through the file path to the file same as MediaPlayer's .setDataSource(String filepath)
Google doesn't have any example and the official documentation site strangely crash my FireFox browser on both computers
The ExoPlayer demo app in github can be modified to play local files.
To do that, edit https://github.com/google/ExoPlayer/blob/master/demo/src/main/java/com/google/android/exoplayer/demo/Samples.java file to add a new video set.
public static final Sample[] LOCAL_VIDEOS = new Sample[] {
new Sample("Some User friendly name of video 1",
"/mnt/sdcard/video1.mp4", DemoUtil.TYPE_OTHER),
new Sample("Some User friendly name of video 2",
"/mnt/sdcard/video2.mp4", DemoUtil.TYPE_OTHER),
};
To do that, edit https://github.com/google/ExoPlayer/blob/master/demo/src/main/java/com/google/android/exoplayer/demo/Samples.java file to add a new sample set.
sampleAdapter.add(new Header("Local Videos"));
sampleAdapter.addAll((Object[]) Samples.LOCAL_VIDEOS);
A minor modification with Srikanth Peddibhotla's code works
The Uri string for the file should be "file:///mnt/sdcard/YourFilename.mp4" instead of "/mnt/sdcard/YourFilename.mp4" in Samples.java
public static final Sample[] LOCAL_VIDEOS = new Sample[] {
new Sample("Some User friendly name of video 1",
"file:///mnt/sdcard/video1.mp4", DemoUtil.TYPE_MP4),
new Sample("Some User friendly name of video 2",
"file:///mnt/sdcard/video2.mp4", DemoUtil.TYPE_MP4),
};
Also, add the following lines to SampleChooserActivity.java
sampleAdapter.add(new Header("Local Videos"));
sampleAdapter.addAll((Object[]) Samples.LOCAL_VIDEOS);
Using ExoPlayer 2.1, and starting with the demo project, you can play mp3 files from the assets folder without modifying any Java code, just by adding the mp3 files in the assets folder and creating or modifying a json file. Starting with the ExoPlayer demo project:
Put the mp3 files in the demo/assets folder (with media.exolist.json).
Either modify media.exolist.json or create a new file such as my.exolist.json containing one or more entries formatted like this:
{
"name": "Children's Songs",
"samples": [
{
"name": "Mary Had a Little Lamb",
"uri": "asset:///mary1.mp3"
},
{
"name": "Itsy Bitsy Spider",
"uri": "asset:///spider1.mp3"
}
]
},
(The final comma assumes there will be another category following, such as Blues Songs, Jazz Songs etc. with more mp3 entries. The final category has no comma after it.)
The figure below shows the chooser activity screen after you click on Children's Songs:
Click Mary Had a Little Lamb or Itsy Bitsy Spider and that mp3 plays.
Google changed some variable name and class definition these days! Below differ works for me.
--- a/demo/src/main/java/com/google/android/exoplayer/demo/SampleChooserActivity.java
+++ b/demo/src/main/java/com/google/android/exoplayer/demo/SampleChooserActivity.java
## -30,6 +28,8 ## import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
## -44,7 +44,12 ## public class SampleChooserActivity extends Activity {
super.onCreate(savedInstanceState);
setContentView(R.layout.sample_chooser_activity);
final List<SampleGroup> sampleGroups = new ArrayList<>();
- SampleGroup group = new SampleGroup("YouTube DASH");
+
+ SampleGroup group = new SampleGroup("test videos");
+ group.addAll(Samples.LOCAL_VIDEOS);
+ sampleGroups.add(group);
+
+ group = new SampleGroup("YouTube DASH");
group.addAll(Samples.YOUTUBE_DASH_MP4);
group.addAll(Samples.YOUTUBE_DASH_WEBM);
sampleGroups.add(group);
diff --git a/demo/src/main/java/com/google/android/exoplayer/demo/Samples.java b/demo/src/main/java/com/google/android/exoplayer/demo/Samples.java
index 9f58528..9e86f99 100644
--- a/demo/src/main/java/com/google/android/exoplayer/demo/Samples.java
+++ b/demo/src/main/java/com/google/android/exoplayer/demo/Samples.java
## -248,6 +248,13 ## import java.util.Locale;
"http://vod.leasewebcdn.com/bbb.flv?ri=1024&rs=150&start=0", Util.TYPE_OTHER),
};
+ public static final Sample[] LOCAL_VIDEOS = new Sample[] {
+ new Sample("Some User friendly name of video 1",
+ "file:///mnt/sdcard/test1.mp4", Util.TYPE_OTHER),
+ new Sample("Some User friendly name of video 2",
+ "file:///mnt/sdcard/test2.mp4", Util.TYPE_OTHER),
+ };
+
private Samples() {}
}
Looks like it's a pretty common trouble but I still can't see any solution.
The goal is to play some AAC stream in Adobe AIR mobile app.
I've used a transcoder from https://code.google.com/p/project-thunder-snow/. The one adds FLV headers to AAC data so the stream can be played through a standard AS3 NetStream object (as I understand). It works fine for Win and Mac, but the same app launched on Android or iOS produces neither sound nor any error. I've figured out that transcoder works fine, the cause is in the different
characteristics of NetStreams.
So, is there any solution or, at least, any documentation describing the difference between the NetStreams on PC and mobile platform?
okay... I might have a clue for you. I tried running the NBAAC code link you posted on the other question from inside Flash CS5 and got this error:
onChannelReady : MetaData
Error: Error #2067: The ExternalInterface is not available in this container. ExternalInterface requires Internet Explorer ActiveX, Firefox, Mozilla 1.7.5 and greater, or other browsers that support NPRuntime.
So it seems the player is designed to be used only inside an html page & uses ExternalInterface (Javascript) for getting metadata from browser into SWF
I removed the ExternalInterface stuff and it played ok in Flash Player & Device Central without browser/HTML. Try this code in your AIR app (I don't have AIR installed anymore to confirm..)
package
{
import com.thebitstream.flv.CodecFactory;
import com.thebitstream.flv.Transcoder;
import com.thebitstream.flv.codec.*;
import com.thebitstream.ice.*;
import com.thebitstream.nsv.*;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
//import flash.external.externalInterface;
import flash.media.SoundTransform;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.net.NetStreamAppendBytesAction;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.URLStream;
import flash.utils.ByteArray;
import flash.utils.setTimeout;
[SWF (width="250",height="250")]
public dynamic class NBAAC_AIR_v2 extends Sprite
{
public var request:URLRequest;
public var transcoder :Transcoder
public var transport :NetConnection;
public var transportStream :NetStream;
public var serverConnection:URLStream;
//public var host:String=" "; //now not used in line... request=new URLRequest(resource);
public var resource:String="http://aacplus-ac-64.timlradio.co.uk/;"; //test station
public function NBAAC_AIR_v2 ()
{
super();
/*
if(loaderInfo.parameters.host)
host=loaderInfo.parameters.host;
if(loaderInfo.parameters.resource)
resource=loaderInfo.parameters.resource;
*/
//CodecFactory.ImportCodec(MetaData);
CodecFactory.ImportCodec(AAC);
CodecFactory.ImportCodec(AACP);
transcoder = new Transcoder();
transcoder.addEventListener(CodecEvent.STREAM_READY,onChannelReady);
transcoder.addEventListener(StreamDataEvent.DATA, onTag);
transcoder.initiate();
transcoder.loadCodec("AAC");
transport = new NetConnection();
transport.connect(null);
flash.utils.setTimeout(boot,500);
}
public function boot():void
{
//externalInterface.addCallback('nbaac.setVolume', onVolume);
//externalInterface.addCallback('nbaac.togglePause', onTogglePause);
//externalInterface.addCallback('nbaac.setBuffer', setBufferLength);
//externalInterface.addCallback('nbaac.getBuffer', getBufferLength);
//externalInterface.addCallback('nbaac.getTime', getTime);
/*
var meta:Object={};
meta.uri="";
meta.StreamTitle="";
*/
//externalInterface.call('logit','start up');
transportStream = new NetStream(transport);
transportStream.bufferTime=2;
transportStream.client = this;
transportStream.soundTransform=new SoundTransform(.5,0);
transportStream.play(null);
transportStream.appendBytesAction(NetStreamAppendBytesAction.RESET_BEGIN);
var headerTag:ByteArray=transcoder.createHeader(false,true);
transportStream.appendBytes(headerTag);
headerTag.clear();
//transcoder.readMetaObject(meta,0);
serverConnection=new URLStream();
serverConnection.addEventListener(ProgressEvent.PROGRESS,loaded);
serverConnection.addEventListener(IOErrorEvent.IO_ERROR, onIo);
serverConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onNoPolicy);
serverConnection.addEventListener(Event.CLOSE, onClose);
request=new URLRequest(resource); //removed "host" from url
//request.requestHeaders=[new URLRequestHeader("GET",resource+" HTTP/1.0")];
//request.requestHeaders=[new URLRequestHeader("Icy-MetaData","1")];
request.method=URLRequestMethod.GET;
serverConnection.load(request);
}
private function getTime() :Number
{ return transportStream.time; }
private function getBufferLength() :Number
{ return transportStream.bufferLength; }
private function setBufferLength (val:Number) :void
{ transportStream.bufferTime = val; }
private function onTogglePause():void
{ transportStream.togglePause(); }
private function onVolume (val:Number) :void
{ transportStream.soundTransform = new SoundTransform(val, 0); }
private function onIo(pe:IOErrorEvent) :void
{ /* externalInterface.call('logit','IOErrorEvent') */ }
private function onTag(sde:StreamDataEvent) :void
{
sde.tag.position=0;
transportStream.appendBytes(sde.tag);
}
private function onChannelReady(ce:CodecEvent) :void
{ trace('onChannelReady :',ce.codec.type); }
private function onClose(e:Event):void
{ /* externalInterface.call('logit','onClose') */ }
public function onMetaData(e:Object):void
{ /* externalInterface.call('logit','onMetaData') */ }
private function loaded(e:ProgressEvent):void
{
var chunk:ByteArray=new ByteArray();
while(serverConnection.bytesAvailable)
{ chunk.writeByte( serverConnection.readByte() ); }
chunk.position=0;
transcoder.addRawData( chunk, 0, "AAC" );
}
private function onNoPolicy(se:SecurityErrorEvent):void
{ /* externalInterface.call('logit','SecurityErrorEvent'+host+resource+'<br />'+se.text); */ }
}
}
Why is my flash-based video player on android always crash after a few hours of play?
I'm writing a flash-based Android App. The only thing that native android part do using webview to load a flash swf. The swf acted as the container for all module (which all written in flash as3). One of the module is a simple video module which loop play a set of video playlist forever.
I've considered memory leak, but after printing memory usage (using flash's System.totalMemory), the result is always around 12MB to 14MB (which seems normal for two videos). I've test the flash using both webview and other third party swf player for android (such as "Swf Player" and "Smart SWF Player"), all results in crash after a few hours.
The as3 code is simple and I can't see any possible cause for this. Here is my main class:
import flash.display.MovieClip;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.events.NetStatusEvent;
public class simpleVid extends MovieClip {
private var video:Video;
private var nc:NetConnection;
private var ns:NetStream;
private var uri:Array = new Array("vid1.flv", "vid2.flv");
private var counter:int = 0;
public function simpleVid() {
// constructor code
nc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
video = new Video();
video.attachNetStream(ns);
ns.client = {onMetaData:videoReady, NetStatusEvent:onStatusEvent};
ns.addEventListener(NetStatusEvent.NET_STATUS, onStatusEvent);
ns.play(uri[counter]);
stage.addChild(video);
counter++;
counter = counter % 2;
}
public function videoReady(item:Object){
video.width = 1280;
video.height = 720;
}
public function onStatusEvent(event:NetStatusEvent):void{
if (event.info.code == "NetStream.Play.Stop") {
ns.play(uri[counter]);
counter++;
counter = counter % 2;
}
}
}
Is there is anything I missed or I did wrong in this code?
Thanks in advance.
The problem "mysteriously" disappeared after I switch to AIR instead of flash.
No code is changed, I only changed the release setting from Flash player to air for android.
Now it can run continuously for several days without problem.
I was wondering if anybody knows a way or method to display on as3 a webview external html page to the back of a display abject?
here is my code
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.filesystem.File;
var fPath:String = "http://mysite.com/demo.php";
var webView = new StageWebView();
webView.stage = stage;
webView.viewPort = new Rectangle(15, 283, 340, 327);
webView.addEventListener(Event.COMPLETE, onComplete);
webView.loadURL( fPath );
function onComplete(event:Event):void{
trace("event = ", event);
trace("event.target = ", event.target);
}
StageWebView is always on top of the display list. There is a work around where you can draw it to BitmapData object and then display that in a Bitmap in the back of the display list using drawViewPortToBitmapData
Obviously the drawn version is not interactive.
hth.
I have a simple button that plays a small MP3 file, looping it 30 times. The MP3 is streamed from a server (urlMP3).
I can see on my Galaxy S2 that it accesses the server for each of the 30 loops. Is it downloading the MP3 each time it loops or downloading once and playing from the phone's memory?
//Button 'audioYes' to play audio loop x 30
var soundLoop:Sound = new Sound();
var soundChannel:SoundChannel;
var soundLoopUrl:URLRequest = new URLRequest(urlMP3);
audioYes.addEventListener(MouseEvent.CLICK, f2_MouseClickHandler);
function f2_MouseClickHandler(event:MouseEvent):void {
soundLoop.load(soundLoopUrl);
soundLoop.play(0, 30);
}
If it is downloading each time, what would be a good way to download it once and then play? Thanks for your help.
Edit: Sep 1 2012
I've created a simple flash file and added the following provided by #Rytis. I'm getting an error from the last line, this.mySound.play "Error #1009: Cannot access a property or method of a null object reference." What do I do with that?
import flash.media.Sound;
import flash.net.URLLoader;
import flash.display.Loader;
var mySound:Sound = new Sound();
var myurlLoader:URLLoader = new URLLoader();
myurlLoader.addEventListener(Event.COMPLETE, this.onSoundLoadComplete)
myurlLoader.load(new URLRequest("01.mp3"))
function onSoundLoadComplete(event:Event):void{
this.mySound = URLLoader(event.target).data as Sound;
this.mySound.play(0,30);
}
Short answer - download sound and store it to variable before playing it.
Example:
package {
import flash.events.Event;
import flash.media.Sound;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class SoundLoadTest {
protected var sound : Sound;
public function SoundLoadTest () {
var urlLoader : URLLoader = new URLLoader();
urlLoader.addEventListener( Event.COMPLETE, this.onSoundLoadComplete )
urlLoader.load( new URLRequest( "path/to/sound.file" ) )
}
protected function onSoundLoadComplete ( event : Event) : void {
// save loaded sound to a class field
this.sound = URLLoader( event.target ).data as Sound;
// start playing sound
this.sound.play( 0, 30 );
}
}
}