在这一系列教程的前面几部分内容中,我们只是介绍了视频流文件的处理。但是,也有很多时候,我们想在Flash Media Server中导入音频文件。关于音频和Flash Media Server 4.5,我们首先应该知道,这和使用ActionScript 3处理本地音频文件完全不同。在ActionScript中,我们可以使用许多Sound选项来处理音频文件。但是在FMS4.5中,这些选项所起的作用就微乎其微了。原因很简单:文件被加入到了音频流中,就其本身而言,由于需要使用完全不同的传输方法,ActionScript 3中的attachAudio() 方法从各方面来说,都不起作用了。
Flash Media Server 4.5可以转化多种不同的音频格式为音频流:SPEEX、G.711、Nellymoser、MP3以及AAC等。同时还可以转化部分为Flash所支持的AAC格式的文件,如AAC+、HE-AAC、AAC v1以及AAC v2等。这是好的一方面。坏的一方面是,AAC格式文件只能在Adobe Flash Player 9.0.115.0及其以上版本中播放。正是由于2007年下半年Flash Player 更新的发布与H.264标准的重新启用的共同作用,才使得上述需求得以实现。但是,你所遇到的最通常的音频格式是MP3和AAC。要对AAC格式有一个宏观上的了解,可以参阅Fabio Sonnati的这篇博文:AAC是如何工作的。
既然你已经知道了你可以使用什么,现在我们就教你如何在实际操作中使用它。
音频文件的讯息流转化在这个例子中,我们要向你展示如何通过Flash Media Server 4.5播放音频文件。这其实和流式视频没有太大的差别。
现在开始:
下载这篇教程所需文件并解压缩。 创建一个音频文件的应用程序。尽管我们的第二部分:流媒体视频点播中的内容已经涵盖了这一步操作,但我们要了解,流式音频应用程序文件夹结构与流式视频应用程序文件夹结构有着完全相同的创建方法,这对我们而言是非常重要的。在那个文件夹里创建一个名为streams的文件夹,并在streams文件夹中创建一个名为_definst_的文件夹。在这种情况下,需要被转化为流式的音频文件就存放在这个_definst_文件夹里。 在C:Program FilesAdobeFlash Media Server 4.5applications目录下创建一个名为AudioStreams的新文件夹,打开AudioStreams文件夹,在其中创建名为streams的新文件夹。在这个新文件夹中创建一个名为_definst_的新文件夹,并把Exercise中的4个音频文件复制到这个_definst_文件夹中。注意:作者在这里要感谢加拿大多伦多市的汉博公立理工学院(Humber Institute of Advanced Learning and Technology)中传媒研究和信息技术学院(School of Media Studies and Information Technology )的院长William Hanna,感谢他允许我们使用由Humber学院无线电广播(Radio Broadcast)项目的学生制作的AndreHprofile.mp3片段。 打开SimpleAudio.FLA文件。当这个文件被打开之后,你就会看到,我们在时间轴上添加了层(如图1所示)。这些层包含了界面和代码的动作层,这里的界面就是一个显示在服务器和SWF文件之间发生了什么的文本框。
图1. 包含了显示在服务器和SWF文件之间发生了什么的文本框的界面
点击ActionScript 层中的Frame 1,打开动作面板。 动作面板打开后,点击Script窗格的Line 1,输入下面的代码:
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.events.NetStatusEvent;
var nc:NetConnection = new NetConnection();
var ns:NetStream;
当处理点播视频时,在音频播放之前,你需要创建一个NetConnection对象,并对其命名:在这种情况下命名为ns。在内务信息移开的情况下,你可以把注意力转移到连接到服务器和侦听服务器与Flash之间信息上来。
注意:在Adobe Flash Professional前面的几个版本中,当你对一个变量分级时,这个分级的输入语句是被加在Script窗格的顶端的。这是一个很好的特点,因为这是输入分级的一个常见的最佳做法。问题是,这在Flash中有点前后矛盾。这些语句只在有些情况下被添加了。意识到这一点之后,在Flash社区中,不依赖于这一特点,只在必要的时候手动添加输入语句已经成为了一个规矩。
在这个例子中,你将会用到一个常用的处理器(netStatusHandler )来侦听四种特殊信息的连接和流动:连接成功,连接被拒,音频流开始播放,未找到音频流。下面是如何实现:
击两次回车,添加如下代码:
nc.connect("rtmp://localhost/AudioStreams");
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
function netStatusHandler(e:NetStatusEvent):void {
traceField.text = e.info.code + "n" + traceField.text;
trace(e.info.code);
switch(e.info.code){
case "NetConnection.Connect.Success":
beginStream();
break;
case "NetConnection.Connect.Rejected":
break;
case "NetStream.Play.Start":
break;
case "NetStream.Play.StreamNotFound":
trace("Can't find the stream.");
break;
}
}
我们会向你简单介绍一下这个功能。它的目的是捕获四个特殊的NetStatusEvent事件并对其作出反应:连接成功,连接被拒,音频流开始播放,未找到音频流。当你测试一个项目时,如果这些事件发生,就会在层2中的文本框中显示出详细的音频流的活动记录。
显然,如果有连接的存在——NetConnection.Connect.Success ——音频文件就会开始播放(在这个例子中,通过调用beginStream() 功能)。如果没有连接的存在——NetConnection.Connect.Rejected ——核实你的FMS 4.5副本确实在运行,确认你的应用程序代码的拼写与应用程序文件夹相匹配。
接下来就是要核实音频流正在播放。NetStream.Play.Start 就是对此进行确认的信息。最后要核实的信息——NetStream.Play.StreamNotFound ——是可以自我说明的,通常可以通过确认你的文件夹结构以及音频文件路径是正确的来确认。
击两次回车,添加启动音频播放的代码:
/* this function will handle creation of the NetStream object.
we invoke NetStream.play() to begin streaming. */
function beginStream():void {
ns = new NetStream(nc);
ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
ns.play("mp3:AndreHprofile");
}
正如你所看到的那样,其神奇之处就在于netStatusHandler() 函数的调用。第一步是在音频流中加入NetConnection,然后侦听服务器与SWF应用程序间的讯息流水平的信息。一切准备就绪之后,NetStream级的play() 程序就会寻找名为AndreHProfile的MP3文件,并把它添加到音频流中。
保存并测试动画。
音频流控制在前面的练习中,我们向你演示了如何创建一个音频文件流式转化的应用程序以及如何使其播放。如果我们的介绍到此结束,你可能就要开始抱怨。在一点也没有使用户避开讨厌的东西的情况下,这并不是播放音频文件的最佳做法。在下面的练习中,我们不仅要教会用户停止放音,还会向你演示如何显示时间以及如何暂停循迹。
现在开始:
打开你的Exercise文件夹中的ControlAudio.fla文件。文件被打开之后(如图2所示),你会看到,我们添加了层,并在Controls层中添加了几个源于Flash的按钮。如果你打开Properties面板,你也会注意到,我们给了每个按钮一个实体名。
图2. 使用了源于Flsh公用图库按钮控制放音的项目
点击Actions层的Frame 1打开Actions面板。打开之后,在Script窗格中输入下面的代码:
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.events.NetStatusEvent;
import flash.events.Event;
import flash.events.MouseEvent;
var isPlaying:Boolean = false;
var nc: NetConnection = new NetConnection();
var ns:NetStream;
addEventListener(Event.ENTER_FRAME, monitorTime);
nc.connect("rtmp://localhost/AudioStream");
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
function netStatusHandler(e:NetStatusEvent):void {
traceField.text = e.info.code + "n" + traceField.text;
trace(e.info.code);
switch(e.info.code){
case "NetConnection.Connect.Success":
beginStream();
break;
case "NetConnection.Connect.Rejected":
break;
case "NetStream.Play.Start":
break;
case "NetStream.Play.StreamNotFound":
trace("Can't find the stream");
break;
}
}
这个代码和前面项目中的代码并没有很大的差别。但是,它有一些重要的添加。首先是isPlaying 变量的添加。我们打算在监测音频是否处于播放状态的过程中绑定几个功能。我们也想向用户演示音轨播放时有多少的时间流逝。为了做到这一点,我们创建了一个密切关注事件的监听器。
击两次回车,输入下面的代码使音频流动起来:
function beginStream():void {
ns = new NetStream(nc);
ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
ns.play("mp3:AndreHprofile");
ns.pause();
timeField.text = "ready";
}
乍看之下,你可能会觉得这样有点古怪,我们一打开音频流就暂停。我们必须这样,因为在通常情况下,我们一开始播放音频流,无线电波报就会马上从用户的扬声器发出。这不是我们想要的。我们想使用户有机会选择音频流的开关。
击两次回车,输入下面的为Control层按钮分配功能的代码来开始这个过程
playBtn.addEventListener(MouseEvent.CLICK, playStream);
pauseBtn.addEventListener(MouseEvent.CLICK, pauseStream);
stopBtn.addEventListener(MouseEvent.CLICK, stopStream);
既然你已经告诉了Flash每一个按钮应该有什么用,是时候开始编写这三个以playStream() 开始的函数的代码了。输入下面的代码:
function playStream(e:MouseEvent):void {
if(!isPlaying){
ns.resume();
isPlaying = true;
}
}
Play按钮的逻辑语言是相当有效的。点击按钮时,第一行的代码检测了音频流是否播放(!isPlaying )。如果音频没有播放,只有三种可能的状况:beginNetStream() 函数暂停了音频流的播放,用户点击了Pause按钮,或者用户点击了Stop按钮。不管在哪种情况下,音频流被重新开始——音轨开始播放——isPlaying 变量的Boolean值被设置为真。
击两次回车,输入Pause和Stop按钮的函数算法:
function pauseStream(e:MouseEvent):void {
if(isPlaying){
isPlaying = false;
ns.pause();
}
}
function stopStream(e:MouseEvent):void {
isPlaying = false;
ns.close();
timeField.text = "stopped";
}
除了在点击Stop按钮时,timeField区域的文字改为”stopped “之外,这里并没有多少新的东西。如果你对数据流媒体的使用不是很熟悉,在使用Sound对象时,你开始、终止或是暂停的并不是音轨本身。你是在告知服务器不再向音频流发送音频数据还是重新向音频流发送音频数据。
最后需要输入的代码组是Output层的时间显示代码组。击两次回车,然后输入:
function monitorTime(e:Event):void {
if(isPlaying){
timeField.text = Math.round(ns.time) + " seconds...";
}
}
除了在点击Stop按钮时,timeField区域的文字改为”stopped “之外,这里并没有多少新的东西。如果你对数据流媒体的使用不是很熟悉,在使用Sound对象时,你开始、终止或是暂停的并不是音轨本身。你是在告知服务器不再向音频流发送音频数据还是重新向音频流发送音频数据。
多音频文件的播放与控制这个练习之前的内容都是关于单个音频文件的播放。既然你已经知道了如何去实现它,我们接下来就向你演示如何使用户可以在多音频文件中选择播放。
我们其中一名作者的女婿,Phil Darling,是多伦多市一个相当火爆的”indie”乐队,TinBangs的低音歌手和创始人。这个乐队刚发布了一个包含有三首歌曲的EP唱片,计划把它们以音频流的形式发布出去,让他们的歌迷们听到他们的新作品。
注意:作者在这里要感谢Phil Darling和乐队的其他成员,感谢他们允许我们在这个例子中使用这些文件。
这就意味着要给用户提供可以在这三首歌曲中任意选择的机会。为了实现这一目的,我们选择了使用打包在Flash Professional CS 5.5软件中的List组件。
注意:也可以使用其他的方法来实现这个项目,从使用ComboBox组件到使用XML文件作为DataProvider都可以。由于空间的限制,我们选择了使用List组件。
现在开始:
打开你的Exercise文件夹里的SelectAudio.fla文件。 打开文件之后,选择动作层的第一帧,打开Actions面板。 点击“脚本”面板的第一行,并键入下列代码,以导入下面的7个类:
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.events.NetStatusEvent;
import flash.events.Event;
import flash.events.MouseEvent;
import fl.data.DataProvider;
import fl.controls.List
要使用List组件,你需要使用DataProvider级向List组件供给数据,使用controls软件包中的List级使组件运行。
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.events.NetStatusEvent;
import flash.events.Event;
import flash.events.MouseEvent;
import fl.data.DataProvider;
import fl.controls.List
要使用List组件,你需要使用DataProvider级向List组件供给数据,使用controls 软件包中的List级使组件运行。
确立分级之后,你现在就可以创建播放列表了。点击Script窗格的Line 6,然后输入:
var playList:Array = new Array();
playList.push({label:"White Lies (Timekiller)",data:"WhiteLies(Timekiller)"});
playList.push({label:"Young Lions", data:"YoungLions"});
playList.push({label:"Your Sky Is Falling", data:"YourSkyIsFalling"});
audioList.dataProvider = new DataProvider(playList);
audioList.addEventListener(Event.CHANGE, switchStream);
我们通过创建一个名为playList 的数组开始。播放列表中的每一个项目都要在List组件中显示出来。这个组件需要两块的信息。第一块是标签,当应用程序运行时在组件中显示的文字信息。第二块是需要使用的数据,在这种情况下指的是音频文件的名字。List组件然后就会被告知,playList 会向其提供数据。我们也会听取用户在List ( Event.CHANGE )中做出的选择,在检测到这一点之后,就开始执行switchStream() 函数。
点击Script窗格的line 44,输入下面的代码来编写switchStream() 函数:
function switchStream(e:Event):void {
ns.play("mp3:" + e.target.selectedItem.data);
if(!isPlaying){
ns.pause();
}
}
这里最大的改变是在play() 方法上。你直接获取列表项目的数据部分并使用它,而不是输入名字。
保存并测试文件。正如你所看到(见图3)和听到的,你创建了一个你可以在三个文件中做选择的应用程序。它的圆滑之处在于,把三首歌扩展到30首甚至更多,在算法上并没有很大的
图3. 填入了List组件,正在播放Young Lions
这一系列教程的下一部分内容将会向你介绍HTTP动态流转化的过程,并向你演示如何使用Flash Media Server 4.5的多比特率的特性。下一篇教程再见。
|