FMS 3.0使用指南
作者:★Tea'mo☆
QQ:39470896
E-mail:sxw52039@https://www.wendangku.net/doc/7d10478249.html,
前言
本文档是作者在学习FMS时总结所成,其中有部分资料来源于网络,因为参考点很多,且无法注明具体的转载点,还请各位原创作者谅解。如果侵犯了您的权益请即刻通知我,我将立刻加以改正!
本文档作为学习交流参考资料,不可作用于商业用途,因转载文中内容而造成的侵权行为作者概不负责!
文档中所有示例代码都是基于Flex Build3开发,且全部通过测试,各位可放心使用。另因工作原因,实在很难抽出时间来做详细的注释,但逻辑还算比较清晰,相信只要参照API很容易就能看清是什么意思。如有任何不明白的地方都可以联系我,我将尽力解答。因为作者也只是自学,所以文中难免会有许多不足或者错误之处,还请各位原谅,另外也十分欢迎各位将发现的问题或者好的建议反馈给我。希望此文档能给大家带来实质性的帮助!另外随着学习的深入,我也会不断的将文档更新共享给大家!真诚感谢你们的支持!
祝各位工作顺利,身体健康!
★Tea'mo☆
2010年4月15日
1、FMS基本概念
(1)什么是FMS
Macromedia于2002年年末发布了令人惊异的FMS的前一个版本Flash Communication Server MX服务器(简称FCS)。后来该名为Flash Media Server (简称FMS),使用FMS你只需要配备Web摄像头和麦克风,并加上十几行ActionScript脚本便可以完成一个电视会议系统。
FMS给全世界的人带来一种全新的通讯方式。有了FMS服务器,您可以参加实时网络会议;使用FMS的功能在工作中进行协作以及通过Internet或企业Intranet共享信息。
还不只是这一点,Flash Player的强大功能使得实时通讯和应用程序的集成由梦想变为现实,这正是未来网络软件发展的趋势,这都是Flash Player惹的“火”。
Flash Media Server(简称FMS)服务器是用于用户之间相互通讯的新平台,它集成了Flash多媒体交互的特性,又添加了实时音频、实时视频和实时数据流等新特色,使用该平台,你可以通过网络存储录制下来的音频、视频,也可以共享数据对象,并且可以将这些音频、视频和共享数据对象传递给多个客户端,实现实时同步共享。该平台集成了通讯功能和应用程序功能,它通过Flash Player (Flash Player 6或更高)在客户端提供音频共享、视频共享和共享数据流,为用户带来了更为丰富的体验。
(2)FMS的传输协议
FMS使用实时通讯协议(RTMP),RTMP 是一种未加密的TCP/IP协议,专门设计用来高速传送音频、视频和数据信息。
使用FMS可以捕获(甚至录制)用户客户端的视频和音频流。信息通过FMS使用Real-Time Messaging Protocol (RTMP)协议被传递到客户端(用户计算机上的Flash Player)。当一个Flash影片应用程序要使用 FMS时,Flash Player就连接到服务器,这样就在客户端Flash Player和FMS之间提供了往复的源源不断的信息流,称为network stream(网络流)。其他的用户也可以同时连接到相同的FMS接收信息、更新数据以及音频和视频,这些都是“网络流”。
(3)FMS的特色
FMS是一个完全基于软件环境的多媒体实时通讯环境,代表了当前实时通讯领域内的发展方向,并且,其自身也融合了大量的新特色,用于创建下一代通讯应用程序,这些新特色包括:
a它提供了一个高效高性能的运行时,该“运行时”不但可以用于执行代码、处理数据内容,并且还可以进行通讯。
b它将内容、通讯功能和应用程序界面集成进一个通用环境,这个通用环境就是Flash Player,通过强大且分布广泛的Flash Player,使得通过FMS进行通讯变得更加便利。
c它为交互性提供了强大、高扩展性的对象模型。在为FMS开发Flash通讯应用程序的过程中,您就会慢慢认识到FMS无处不在的面向对象开发的特点。 d它还建立了一个高效的组件架构模型,使用该组件架构模型可以创建高效的Flash通讯组件,而使用组件和其它的可重用模块,可以使你快速的开发基于FMS的通讯应用程序。
e它还允许使用应用程序服务器提供的web服务和数据服务,从而可以和其它的应用服务器技术结合起来以创建功能更强大、更完整的富媒体应用程序。 f它并且可以识别那些处于连接状态和处于未连接状态的客户端,以降低网络负载。
g使用它,你可以将通讯应用程序客户端轻松的部署在多个平台和设备上,这多亏了Flash Player的广泛使用。
使用FMS和Flash创作环境,你可以非常轻松迅速的创建即时通讯应用程序,它可以让两个或多个的用户实现即时交流(交流可以使用文字、音频和视频)。例如,你可以使用FMS创建会议系统、在线社区、客户支持、销售支持、培训、远程展示或者即时消息系统。FMS是一个实时数据流平台,使用该平台加上客户端Flash Player的支持,可以将实时的数据流通过网络传递到Internet、PDA、iTV 或者其它的设备上。
FMS的功能平台由两部分组成:服务器提供通讯方式;Flash影片应用程序(SWF 文件)提供终端用户界面。你可以使用Flash创作工具作为开发环境创建Flash 影片应用程序,该影片应用程序使用FMS提供的服务(也就是位于FMS上的Flash 通讯应用程序)。有时你也可以编写服务端脚本为通讯应用程序添加新的功能,
使用服务端脚本可以更灵活的控制共享状态信息,并且可以作为一个负载平衡器调节多用户之间的实时交互。
2、正确安装FMS 3.0软件
Flash media server有三个版本:
Flash Media Interactive Server :拥有完整特性的服务。
Flash Media Development Server:一个用于开发的交互式服务的版本。支持所有的特性,但是有连接数的限制。
Flash Media Streaming Server:只支持实况和视频点播的服务。这个版本不支持服务器端的脚本或视频编码。
安装选择不同的版本体现在输入的注册码的不同。如果发现安装的版本错了,也不需要重新安装,找一个FMIS的序列号,然后覆盖安装目录下conf/fms.ini中的FMSS序列号,然后重启FMS 服务即可由FMSS切换到FMIS。
另外如果忘记了在安装过程中设置的管理员用户名或者密码都可以在此文件中找到,如下图所示:
3、启动FMS服务
用户可以通过开始菜单选择开启服务,其中有两个start都必须全部开启,还有一种简便的方式如下:在安装目录下tools文件下双击StartServerService.bat启动服务,同样双击StopServerService.bat关闭服务。
4、建立一个自己的服务器项目
安装目录下的Applications文件夹下新建一个文件夹(如sxw),那么以后所连接的这个地址的所有文件就是保存在该目录下了。
5、建立一个简单的连接FMS服务器的文件
Flex示例文件如下:
source\ConnectFMS\ConnectFMS.mxml
fontSize="12" fontWeight="normal"/> import mx.controls.Alert; private var nc:NetConnection; private var rtmpUrl:String="rtmp://localhost/sxw"; private function onClick():void { nc = new NetConnection(); nc.connect(rtmpUrl); nc.client = this; nc.addEventListener(https://www.wendangku.net/doc/7d10478249.html,_STATUS,onNetStatusHandler); } private function onNetStatusHandler(evt:NetStatusEvent):void { switch (https://www.wendangku.net/doc/7d10478249.html,.code) { case "NetConnection.Connect.Success": Alert.show("成功连接FMS服务器!"); break; case "NetConnection.Connect.Rejected": Alert.show("访问FMS服务器权限不足,连接被拒绝!"); break; case "NetConnection.Connect.InvalidApp": Alert.show("指定的应用程序名称没有找到"); break; case "NetConnection.Connect.Failed": Alert.show("连接失败!"); break; case "NetConnection.Connect.AppShutDown": Alert.show("服务器端应用程序已经关闭(由于资源耗用过大等原因)或者服务器已经关闭!"); break; case "NetConnection.Connect.Closed": Alert.show("与FMS的连接中断!"); break; } } public function onBWDone():void{} public function close():void{} ]]>
注意:可能会遇到如下问题:
(1)ReferenceError: Error #1069: 在 hello 上找不到属性 close,且没有默认值。解决方法是将安装目录下Applications文件夹下的live文件夹中出readme.txt外的四个文件拷贝到自己的项目文件夹下(test)(2)ReferenceError: Error #1069: 在 https://www.wendangku.net/doc/7d10478249.html,Connection 上找不到属性 onBWDone,且没有默认值。解决方法是在程序中加入代码:Netconnection.client=this;
Public function onBwDone:void{}
说明:Flash客户端与FMS服务器的连接过程如下:
每当客户端试图连接服务器,一个NetConnection.connect(),服务器将会调用application.onConnect 来鉴定是不是允许客户端连接,onConnect()方法返回null 或不返回则将进入未决状态,直到onConnect方法中返回true或执行acceptConnection(client)则允许,返回false或执行rejectConnection(client)则拒绝。
6、在线视频录制与视频回放
Flex示例代码如下:source\FMSRecord\FMSRecord.mxml
private var nc:NetConnection;
private var ns:NetStream;
private var video:Video;
private var cam:Camera;
private var mic:Microphone;
private function init():void
{
message.text="【系统】输入视频文件名称,点击开始录制录制视频\n 【系统】设备初始化...\n";
video=new Video();
cam = Camera.getCamera();
mic = Microphone.getMicrophone();
if(cam==null)message.text+="【系统】没检测到视频摄像头,无法录制!\n";
else
{
video.attachCamera(cam);
message.text+="【系统】设备初始化完成!可以录制!\n";
}
localdisplay.addChild(video);
}
private function onPublishClick(evt:MouseEvent):void
{
message.text+="【系统】正在连接服务器,请稍候!\n";
nc=new NetConnection();
nc.client=this;
nc.addEventListener(https://www.wendangku.net/doc/7d10478249.html,_STATUS,onPublishStatusHandler);
nc.connect("rtmp://localhost/sxw");
}
private function onPublishStatusHandler(evt:NetStatusEvent):void
{
switch(https://www.wendangku.net/doc/7d10478249.html,.code)
{
case "NetConnection.Connect.Success":
message.text+="【系统】连接服务器成功!\n";
ns=new NetStream(nc);
ns.attachCamera(cam);
ns.publish(tbName.text,"append");
ns.addEventListener(https://www.wendangku.net/doc/7d10478249.html,_STATUS,onPublishStatusHandler);
break;
case "NetStream.Record.Start":
message.text+="【系统】视频录制开始!\n";
break;
case "NetStream.Record.Stop":
message.text+="【系统】视频录制结束!\n";
break;
case "NetStream.Record.Failed":
message.text+="【系统】尝试视频录制失败!\n";
break;
case "NetStream.Publish.Start":
message.text+="【系统】"+tbName.text+"已经成功发布!\n";
break;
case "NetStream.Record.NoAccess":
message.text+="【系统】试图录制仍处于播放状态的流或客户端没有访问权限的流!\n";
break;
case "NetStream.Publish.BadName":
message.text+="【系统】试图发布已经被他人发布的流!\n";
break;
case "NetConnection.Connect.Closed":
message.text+="【系统】与服务器断开连接!\n";
break;
case "NetStream.Play.Stop":
message.text+="【系统】播放结束!\n";
break;
case "NetStream.Buffer.Empty":
closeStream();
break;
default:
message.text+="【系统】"+https://www.wendangku.net/doc/7d10478249.html,.code+"\n";
break;
}
}
private function onStopHandler(evt:MouseEvent):void
{
message.text+="【系统】视频录制已经结束,可点击视频回放观看!\n";
closeStream();
}
private function closeStream():void
{
ns.removeEventListener(https://www.wendangku.net/doc/7d10478249.html,_STATUS,onPublishStatusHandler);
ns.close();
ns=null;
}
public function onBWDone():void
{
}
private function playVideo():void
{
ns=new NetStream(nc);
ns.client=this;
ns.addEventListener(https://www.wendangku.net/doc/7d10478249.html,_STATUS,onPublishStatusHandler);
var v:Video=new Video();
v.attachNetStream(ns);
ns.play(tbName.text);
clientVideo.addChild(v);
}
public function onMetaData(info:Object):void
{
trace("metadata: duration=" + info.duration + " width=" + info.width + " height=" + info.height + " framerate=" + info.framerate);
}
public function onPlayStatus(dd:*):void
{
}
]]>
注意:可能会遇到如下问题:
code=NetStream.Record.NoAccess,解决方法是在自己所建的应用文件夹中找到main.far文件,用WinRAR解压打开里面的Application.xml文件做相应的修改并更新。修改后的代码如下:source\FMSRecord\Application.xml
更新main.far的方法如下:用Winrar解压出来,修改之后,在Dos环境中运行打包命令:
Windows:
D:\WebSer\Flash Media Server 3\applications\test\main>"D:\WebSer\Flash Media Ser
ver 3\tools\far.exe" -package -archive main -files Application.xml main.asc
Linux:
$ /usr/local/fms/tools/far -package -archive main -files Application.xml main.asc(此段作者没有使用过Linux系统,所以正确性由各位去验证吧)
此操作之后就会生成一个main.far文件,替换原先的文件。注意:每次修改了服务端程序之后需要将应用程序reload才能有效。
这里我就来给大家介绍一下如何简单的管理FMS服务器:
首先点击安装目录下的fms_adminConsole.htm,输入安装时设置的用户名和密码进入服务器管理界面。
管理界面的左下角有一个New Instance…的按钮,点击此可显示所有application下的应用程序的名称,单击选择应用程序。
最上方三个选项分别依次代表管理应用,管理用户以及管理服务器。分别有些什么内容各位可分别点击进去查看,都比较好理解就不多说了。以后我们写程序最常用的是View Applications ,每当有客户端连接服务器时,左边就会列出连接的是哪个应用程序,有多少连接,下图为连接applications文件夹下的sxw文件夹(sxw文件夹,因为每个文件夹对应一个应用程序,就是sxw应用程序),连接数为1,_definst_是实例名(实例名默认为 _definst_ ,每个文件夹可以
有若干实例,互相不影响。我们也可以重新命名实例名称)
选中某个应用程序或者客户端有连接,会看到当前打开的应用程序的状态,如下图所示:
Live Log 服务器端的trace就这里看了,右边依次是客户端情况,共享对象,流,执行的情况(占内存,cpu等),后边两个小按钮(reload和unload)每当服务器端main.asc修改后一定记得reload或者unload一下,否则不会生效,unload会把窗口关闭,有客户端连的时候还会自动打开。
7、创建可交互的FMS连接
以下说明Fms3中client端与server端通信的几种方式:
(1)客户端呼叫服务器
Flex源代码如下:source/CallFMS/Example_1/CallFMS.mxml
fontSize="12" creationComplete="initApp()"> import mx.controls.Alert; private var nc:NetConnection; private var fmsServer:String="rtmp://localhost/sxw"; private var rs:Responder; private function initApp():void { nc = new NetConnection(); nc.connect(fmsServer); nc.client=this; } private function onClick():void { rs = new Responder(onSuccess,onFailed); nc.call("sayHelloWorld",rs,"World"); nc.addEventListener(https://www.wendangku.net/doc/7d10478249.html,_STATUS,onStatus); nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR,onAsyncHandler); } private function onStatus(evt:NetStatusEvent):void { Alert.show(https://www.wendangku.net/doc/7d10478249.html,.code); } public function onAsyncHandler(evt:AsyncErrorEvent):void { } private function onSuccess(result:Object):void { Alert.show(result.toString(),"调用结果"); } private function onFailed(result:Object):void { Alert.show(result.description); Alert.show(result.code); } public function onBWDone():void {} ]]>
服务端源代码如下:source/CallFMS/Example_1/main.asc
application.onConnect = function(client)
{
client.sayHelloWorld=function(str)
{
return "I can say:Hello "+ str;
}
this.acceptConnection(client);
}
说明:Responder 类提供了一个对象,该对象在 NetConnection.call() 中使用以处理来自与特定操作成功或失败相关的服务器的返回值。它有2个参数:第1个是成功调用回调的方法,第2个参数是调用失败时回调的方法call () 方法
第1个参数:服务器端方法名
第2个参数:可选对象,用于处理服务器的返回值
第3个参数:传递给服务器端方法的值
(2)服务器端呼叫指定的客户端
Flex源代码如下:source/CallFMS/Example_2/CallFMS.mxml
import mx.controls.Alert;
private var netConnection:NetConnection;
private var appServer:String="rtmp://localhost/sxw";
private function init():void
{
netConnection = new NetConnection();
netConnection.connect(appServer);
netConnection.client=this;
}
public function asyncServerCall( msg:String ) : String {
Alert.show( msg );
return "I got your message Thanks Server!";
}
]]>
服务端源代码如下:source/CallFMS/Example_2/main.asc
var handlerObject = function() {};
handlerObject.prototype.onResult = function( result )
{
trace( result );
};
handlerObject.prototype.onStatus = function( info )
{
trace( "error: " + info.description );
trace( "error: " + info.code );
};
application.onConnect = function( client )
{
this.acceptConnection( client );
var msg = "Hello client, your IP is: " + client.ip;
client.call( "asyncServerCall", new handlerObject, msg );
};
说明:Client.call() 在Flash客户机上异步的执行一个方法,并把值从Flash客户机返回到服务器。
用法 clientObject.call(methodName, [resultObj, [p1, ..., pN]]) 第1个参数:客户端的方法名(此方法必须为public)
第2个参数:当发送者期待一个来自客户机的返回值时需要这个参数。如果参数被传递但没有返回值被期待的话,则传递值null。结果对象可以是你定义的任何对象,并且,为了有用起见,这个结果对象应该有两个方法-onResult和onStatus,这些方法会在结果到达时被调用。如果远端方法的调用是成功的,则resultObj.onResult事件会被触发;否则,resultObj.onStatus事件将被触