Mp3流媒体播放器(Flex端)
当然,Flv格式视屏也是可以播放的。
推荐参考文档:http://livedocs.adobe.com/fms/2/docs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000788.html
目前自己也是初学者,不过希望分享一下,如果是高手,就大可在此打住(*^__^*) 嘻嘻……。
先看下效果:
实现的几个基本功能:
第一 和javascript交互,显示进度。
第二 实现自动播放下一首
当然 当你点击播放按钮他肯定要能切换歌曲。
功能很简单了。不过还是有很多细节要注意的,呵呵。
我们先分析一下ActionScript需要用到的几个类,以及构建流程。
NetConnection -> NetStream
就这两个核心类。其中关键是时间的处理。通常NetStream有比如 NetSream.Player.Start事件,这些很重要。我们贴出部分代码:
publicfunction init():void {
registerJavaScriptFunction();
createConnection();
}
privatefunction registerJavaScriptFunction():void
{
ExternalInterface.addCallback("pauseAndResume_flex",pauseAndResume);
ExternalInterface.addCallback("stop_flex",stop);
ExternalInterface.addCallback("play_flex",play);
MSG("注册函数给javascript用");
}
privatefunction createConnection():void {
NetConnection.defaultObjectEncoding = flash.net.ObjectEncoding.AMF0;
connection = new NetConnection();
connection.connect(streamLink);
connection.addEventListener
(NetStatusEvent.NET_STATUS,netStatusHandler);
connection.addEventListener
(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);
connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR,onBWDone);
MSG("创建Connection以及注册必要的监听器");
}
代码格式稍微有点乱,Word用的不行。
init是初始化函数,主要注册javascript回调函数以及创建Connnection连接。
connection.connect(streamLink)中的streamLink是类似于rtmp://ip//name的地址。ActionScript面向对象部分很像C#或者Java,不过动态性方面则和javascript一样,很酷。
初始化后就要通过NetStream连接具体的对象了(对了前面的事件处理函数函数比如securityErrorHandler之类的,我们放在后面讲).
privatefunction connectStream():void {
stream = new NetStream(connection);
stream.bufferTime=15;
stream.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler);
var nsClient:Object = {};
nsClient.onMetaData = ns_onMetaData;
nsClient.onCuePoint = ns_onCuePoint;
nsClient.onPlayStatus=ns_ononPlayStatus;
video.attachNetStream(stream);
stream.client = nsClient;
//uic.setActualSize(320,240);
uic.addChild(video);
MSG("NetStream创建完毕");
// addChild(video);
}
需要注意的是,nsClient.onPlayStatus=ns_ononPlayStatus;也就是onPlayStatus事件还是蛮重要的。通常事件,比如NetStream.Play.Start NetStream.Play.Stop(严格来看这些当然不是事件,而只是时间发布时附带的一个标志),但Adobe得开发人员不知道吃错药了还是怎么着,把NetStream.Play.Complete 和NetStream.Play.Switch放到了OnPlayStatus属性中。
很多人都以为Complete事件簿其作用呢。
现在我们看看在Connection以及NetStream的创建过程中安装的监听器的具体处理。
privatefunction ns_ononPlayStatus(item:Object):void
{
for (var prop in item) {
MSG(""t"+prop+":"t"+item[prop]);
if(item[prop]== "NetStream.Play.Complete")
{
if(interval!=0)
{
clearInterval(interval);
}
MSG("完成播放"+this.linkName);
noticeJavascript();
}
}
}
privatefunction netStatusHandler(event:NetStatusEvent):void {
switch (event.info.code) {
case"NetConnection.Connect.Success":
connectStream();
break;
case"NetStream.Play.StreamNotFound":
Alert.show("没有找到媒体");
case"NetStream.Play.Stop":
{
MSG("已近停止播放"+this.linkName);
if(interval!=0)
{
clearInterval(interval);
}
MSG(stream.time+"--"+(duration-2))
if (stream.time > duration-2){
MSG("完成播放"+this.linkName);
noticeJavascript();
}
}
case"NetStream.Play.Start":
{
interval=setInterval(configProgressBar,300);
}
default:
//message.text+=""n"+("netStatusHandler:code: " + event.info.code);
break;
}
}
还有几个回调事件函数,你可以给个空实现,这不影响。
要实现自动播放下一首,必须触发NetStream.Play.Complete事件,当然你也可以用Stop模拟,方式如下(有人成功过,我没有):
If(stream.time>duration-2)
{
MSG(“播放结束”)
}
个人做过试验,该方法似乎不起作用,歌曲播放结束后time要小于duration很多。网上有人说可以通过上面的模拟。大家可以自己尝试一下。
播放结束后,可以通知javascript播放结束,这个时候回调一个noticeJavascript函数通知javascript.JavaScript则调用Flex的Play函数,这样可以轻松实现连续播放。当然这种便利性得利于Flex与Javascript的良好交互性。他们之间的调用可以参考官方文档。我这里给出基本用法。
注册一个函数让Javascipt调用的格式:
ExternalInterface.addCallBack(“给javascript调用的函数名”,Flex中的函数名);
调用一个Javascript函数的方式则更简单直观:
ExternalInterface.call(“javascript函数名”,参数);
参数是个不定参数,可以任意多个,不过记得顺序需要和Javascript申明的一样。
自动播放解决了。那么在html页面显示歌曲精度问呢。细心的话,大家在前面应该看到这一段代码:
interval=setInterval(configProgressBar,300);
我们调用了一个每隔300毫秒执行的一个configProgressBar的函数,该函数内部调用了Javascript函数绘制界面。
内部代码为:
buffer_bar.setProgress(stream.bufferLength/stream.bufferTime*290 as Number,290);
time_b.setProgress(stream.time/duration*290 as Number,290);
ExternalInterface.call("setProgressBar",stream.time,duration,stream.bufferLength,stream.bufferTime);
这样进度绘制的问题就解决了。
前面的停止播放暂停很简单,大家可以看看源码。
之前我遇到一个问题,每次播放当用户手动播放某一首歌曲的时候,如何停掉前面的一首歌曲,当时有两个,通过netStream.close()关闭流,但不关闭connection.第二种则是通过netStream.play(false)让后再播放另一首,我尝试过似乎都可以,但是第一种会导致进度绘制停顿,没闹明白什么原因,初步猜测应该是监听器注册地问题,可能需要将监听器重新注册一遍。
先写到这吧。在上班的时候写的,有点急,不过我会不断地修改这篇文章。大家有时间也可以共同修改。