让TitleWindow不能被拖动
让TitleWindow不能被拖动
var win:PWindow=PWindow(PopUpManager.createPopUp(this,PWindow));
win.isPopUp=false;//设置这个属性就可以了哦
让TitleWindow不能被拖动
var win:PWindow=PWindow(PopUpManager.createPopUp(this,PWindow));
win.isPopUp=false;//设置这个属性就可以了哦
(翻译能力有限,仅供个人学习参考,看得懂就好-_-||)
Learning Flash Media Server 3中文版-第6章广播和服务端带宽控制
6.2.切换摄像头
一个在电视演播室工作的任何人都知道,制作人切换摄影机,大部分演出,约有3个不同摄影机拍摄。因此,在从一个摄影机切换到另一个,是设立自己的全球视讯广播公司的一个关键技能。
6.2.1. 选择一个摄像头
像在本书中讨论的多大数改变一样,AS3.0中的一个关键的改变是改变了取得一个摄像头的方法,在以前的as版本中,可以用一个整数作为参数来取得一个摄像头。现在在AS3.0中,用一个字符串。新的方式,仍然使用一个整数类型,当作一个字符串来做这事情。意思就是“4”代替 4 。这个数字是摄像头在设置窗口中的位置。在最上面的是”0”,每一个摄像头是参照其在清单中的相对位置。因此,第五个摄像头是“ 4 ”就像一个基于0的数组。以下一行显示了取得在名单中的第5个摄像头:
var cam2:Camera=Camera.getCamera(“4″);
Camera类的实例:cam2 ,现在是设置窗口的第5个摄像头。 (实际上,使用第5个设置) 。
您可能还记得,如果没有使用参数,摄像头默认为最后选定的摄像头。例如,如果您最近使用的摄像头位置是”5”,下面的会设置为6(如果6在名单中):
var cam1:Camera=Camera.getCamera();
此举意味cam1将取得第六摄像头,而不是在Flash Player设置窗口的第一个-在位置”0” 。
6.2.2. 切换两个摄像头
看看如何切换摄像头,以下应用程序最少需要2个像头。如果你只能有一个摄像头,借用一个或使用一个虚拟网路摄影机,您可以在网上找到。 (一个有趣的摄像头驱动程序对你的屏幕作为一个摄像头,提供您一个好屏幕捕获工具,它可用于Windows :http://www.hmelyoff.com/index.php?section=8)
按以下步骤来建立应用程序:
4. 建立一个CameraSwitch.as
5. 在CameraSwitch.as中输入以下代码:
Example 6-1. CameraSwitch.as
Code View:
package{import flash.media.Camera;import flash.media.Microphone;import flash.media.Video;import flash.display.Sprite;import flash.net.NetConnection;import flash.net.NetStream;import flash.events.MouseEvent;import fl.controls.Button;public class CameraSwitch extends Sprite{private var cam1:Camera;private var cam2:Camera;private var btn1:Button;private var btn2:Button;private var mic:Microphone;private var vid:Video;public function CameraSwitch (){vid=new Video(320,240);vid.x=100,vid.y=30;addChild (vid);mic=Microphone.getMicrophone();cam1=Camera.getCamera();cam1.setMode (320,240,15);cam2=Camera.getCamera("4");cam2.setMode (320,240,15);btn1=new Button();btn1.width=70;btn1.x=vid.x;btn1.y=vid.y+vid.height+10;btn1.label="Camera 1";addChild (btn1);btn1.addEventListener (MouseEvent.CLICK,camOne);btn2=new Button();btn2.width=70btn2.x=btn1.x+100;btn2.y=vid.y+vid.height+10;btn2.label="Camera 2";addChild (btn2);btn2.addEventListener (MouseEvent.CLICK,camTwo);}private function camOne (e:MouseEvent){vid.attachCamera (cam1);}private function camTwo (e:MouseEvent){vid.attachCamera (cam2);}}}
在测试程序之前,请检查您的Flash Player的设置窗口,并且确保列表中至少两个设备。如果您只有两个设备,确定哪一个是默认的,然后输入字符串数字等。(例如,如果您只有两个设备和第一个是默认的[“0”] ,然后设置cam2为”1” )。
在接下来的Studio应用程序。如果您只有一个单一的摄像头,你大概不会想添加了第二个摄像头。不过,如果您想要把您的studio成为一个更强大的应用程序,那么只需合并Example 6-1的代码。
(翻译能力有限,仅供个人学习参考,看得懂就好-_-||)
Learning Flash Media Server 3中文版-第6章广播和服务端带宽控制
制作一个全世界的广播系统的想法,看起来似乎有点雄心勃勃,但使用FMS3 ,它其实很容易。所有您需要做的只是发出一个包含音频和视频的流,使用” Studio”模块,并有一个“TV”模块set to pick it up。你甚至可以设置带宽分配,所以Studio模块使用更多的客户端到服务器之间的带宽,TV模块是有利的,所以大部分的带宽分配是从服务器到客户端。
此外,您可以在live和录制之间切换和从远程位置取得报告。你走出去,并聘请一名新闻队伍之前,记得每一个客户端连接到应用程序,FMS3生成一个新的流。 FMS3既有的带宽和连接客户端的限制,所以根据您的fms3版本,您将可以服务更多或更少的客户。但是,您可以创建一个广播的应用程序,优化带宽,使您可以服务一样多的客户同时,尽可能的仍提供服务器端的最佳A / V。
(翻译能力有限,仅供个人学习参考,看得懂就好-_-||)
Learning Flash Media Server 3中文版-第5章双向音频-视频通信
从一个双向聊天应用到多个参加会议的应用是大概的缩放和带宽调整。对服务器端,唯一的要求是,再添加两个元素到数组和更改名称。不过,在实际应用中工作,您需要看看对带宽的要求。
5.6.1. 2 等于2:4等于12
在本章开始之前,图5-1显示了流的数量是如何增长的:双向A/V聊天是2个流,4向A/V聊天是12个流。与流的数量增长,减少对带宽是必不可少的。首先,看看影片发送整个网际网路的尺寸。在Deux应用程序中,相机设置为240 × 180 ,产生大约43.2千比特(千位)像素。乘以帧速度15fps和流(2),应用程序产生大约1.3兆比特( mbits )每秒。这还不包括音频,但现在, 1.3 mbits可被用来作为4路会议的目标带宽。 (音频的一个好的地方是,在大多数的会议,同一时间只有一人会谈,所以在双向或者4向中,其大小可能不会有很大的不同)。
使用1.3 mbits作为目标带宽,首先考虑的是要传输的视频的大小。在Deux应用程序中,两个参与者两旁都有很多空白。切割出额外的水平空间,使得议长清晰可见,和您释放了大量的未使用的bits整个网际网路。 4路会议的应用程序,命名为Quad,削减相机宽度从240至80 。为了更好地集中发言者,高度从180削减到100 。现在,不是一个240 × 180的矩阵,而是80 × 100的矩阵了 。其次,降低fps,从15降到12。做这个简单的算术,bits的数量应该是1.15 mbits –实际上少于2人的聊天。检查下列步骤:
当你完成这些计算,你能够建立一个站点,是不太可能冻结起来并给予客户一个坏的经验
5.6.2.布置客户和他们的流
与4人在一个会议,给他们一个参考框架,帮助他们有一个整体会议意识。为此,应用程序有背景框,就是视频出现的地方。因此,举例来说,如果有两个用户在网站上,他们可以看到后面两个用户出现在哪里。logo是放置在应用程序的中间,暗示在一个圆桌,人人的地位平等。然而,由于观看是在一个垂直平面(电脑显示器) ,人在最上方的位置可能会出现比别人更强大,人在底部在是处于最低的地位。
所幸的是,因为这是一个虚拟会议,放置可以把每个人都在最上方的位置,由用户自己的有利位置。简单地通过发送所有本地视频到最上方的位置,每个用户都可以看到他或她自已在顶部,被其余人环绕着。
要获得此效果,并正确的分发所有的流, switch语句再度派上用场。以下代码段显示了一切是如何分布式的:
Code View:
switch (streamSelect){case "left" :outStream="left";inStream1="right";inStream2="top";inStream3="bottom";break;case "right" :outStream="right";inStream1="left";inStream2="top";inStream3="bottom";break;case "top" :outStream="top";inStream1="left";inStream2="right";inStream3="bottom";break;case "bottom" :outStream="bottom";inStream1="left";inStream2="top";inStream3="right";break;}
作为与Deux应用程序,在switch语句中,案例的所有的数据是由服务器端脚本提供的。而不是只二个:left 和 right,现在streamSelect的值观是left, right, top, 和 bottom。这些名称对不同流的位置不产生影响。而他们只是四个方便的名字。后面的代码段显示了如何分布流:
//Publish local videonetOut=new NetStream(nc);netOut.attachAudio (mic);netOut.attachCamera (cam);vidOut.attachCamera (cam);netOut.publish (outStream, "live");//Play streamed videonetIn1=new NetStream(nc);vidBottom.attachNetStream (netIn1);netIn1.play (inStream1);netIn2=new NetStream(nc);vidLeft.attachNetStream (netIn2);netIn2.play (inStream2);netIn3=new NetStream(nc);vidRight.attachNetStream (netIn3);netIn3.play (inStream3);
名为vidOut是在顶部位置的video对像,和名为netOut的是从本地客户端的摄像机和麦克风中即将流出的流。其他传入的流分配给左,右,和下而的视频对象,流的名字,是switch语句中产生的。
5.6.3.建立会议应用程序
现在准备开始建立,按以下步骤来建立,首先放置对像在舞台上:
2. 使用图5-8作为一个指南,使用矩形工具在舞台上画4个80 X 100的矩形,位置如图5-8所示。
图5-8. Placement of backdrops
5. 在Quad.as中输入以下代码
Example 5-4. Quad.as
Code View:
package{import flash.display.Sprite;import flash.display.MovieClip;import flash.events.NetStatusEvent;import flash.net.NetConnection;import flash.net.NetStream;import flash.media.Camera;import flash.media.Microphone;import flash.media.Video;import flash.net.Responder;public class Quad extends Sprite{private var nc:NetConnection;private var good:Boolean;private var netOut:NetStream;private var netIn1:NetStream;private var netIn2:NetStream;private var netIn3:NetStream;private var cam:Camera;private var mic:Microphone;private var responder:Responder;private var vidOut:Video;private var vidBottom:Video;private var vidLeft:Video;private var vidRight:Video;private var outStream:String;private var inStream1:String;private var inStream2:String;private var inStream3:String;public function Quad (){var rtmpNow:String="rtmp://192.168.0.11/quad";nc=new NetConnection;nc.connect (rtmpNow);nc.addEventListener (NetStatusEvent.NET_STATUS,getStream);}private function getStream (e:NetStatusEvent):void{good=e.info.code == "NetConnection.Connect.Success";if (good){responder=new Responder(streamNow);nc.call ("streamSelect",responder);}}private function streamNow (streamSelect:String):void{setCam ();setMic ();setVid ();switch (streamSelect){case "left" :outStream="left";inStream1="right";inStream2="top";inStream3="bottom";break;case "right" :outStream="right";inStream1="left";inStream2="top";inStream3="bottom";break;case "top" :outStream="top";inStream1="left";inStream2="right";inStream3="bottom";break;case "bottom" :outStream="bottom";inStream1="left";inStream2="top";inStream3="right";break;}//Publish local videonetOut=new NetStream(nc);netOut.attachAudio (mic);netOut.attachCamera (cam);vidOut.attachCamera (cam);netOut.publish (outStream, "live");//Play streamed videonetIn1=new NetStream(nc);vidBottom.attachNetStream (netIn1);netIn1.play (inStream1);netIn2=new NetStream(nc);vidLeft.attachNetStream (netIn2);netIn2.play (inStream2);netIn3=new NetStream(nc);vidRight.attachNetStream (netIn3);netIn3.play (inStream3);}private function setCam ():void{cam=Camera.getCamera();cam.setMode (80,100,12);cam.setQuality (0,80);cam.setKeyFrameInterval(12);}private function setMic ():void{mic=Microphone.getMicrophone();mic.rate=11;mic.setSilenceLevel (12,2000);}private function setVid ():void{vidOut=new Video(80,100);addChild (vidOut);vidOut.x=235;vidOut.y=43;vidLeft=new Video(80,100);addChild (vidLeft);vidLeft.x=89;vidLeft.y=145;vidRight=new Video(80,100);addChild (vidRight);vidRight.x=379;vidRight.y=145;vidBottom=new Video(80,100);addChild (vidBottom);vidBottom.x=235;vidBottom.y=253;}}}
6. 在你的服务端applications目录中建立一个名为Quad的目录
7. 打开Deux.asc文件,改变第一行
vidStreams=["bottom", "top",right","left"];
8. 把Deux.asc另存为Quad.asc,放置在Quad目录中
9. 发布Quad.fla为html,swf,一旦你把这些文件放置在你的Web服务器上,你已经设置好你的在线会议了。
邀请3位有摄像机和麦克风连的朋友连接到您的应用程序。每一个进入在线会议,他们将看到别人和仍未出现人的绿色背景。如果有人离开会议时,您会看到在视频窗口该人的最后一张图像,直到有一个新进来的人。图5-9显示了4个来自四个不同国家的人在聊天应用程序上。这视图显示了本地用户在最上方的位置,不过,其他三人也看到自己在最上方的位置。
图5-9. Four-way conference in four countries
这个应用程序的目的,一直保持简单。您可以添加不同的增强,如使用video.clear()方法来清除萤幕,在旅客已离开了会议后。
5.7.继续前进到更多的服务端应用程序
现在,您已经看到如何在客户端与音频和视频工作(服务器端的一些小帮忙),下一步是在对服务器端与音频和视频工作。第6章:广播和服务器端的带宽控制 ,介绍了另一种类型的A/V应用-广播,更好地形容为一个到多个的应用。主要焦点,会介绍了FMS3服务器端的综合体。首先开始一些简单的服务器端使用。但正如您将很快地看到,一旦你开始使用服务器端脚本,您将有更多的选择和控制您建立的应用程序。
-_-||本章终于完了~~
(翻译能力有限,仅供个人学习参考,看得懂就好-_-||)
Learning Flash Media Server 3中文版-第5章双向音频-视频通信
虽然两个模块的聊天室应用程序是很容易就建立和良好的工作,其唯一目的是显示创建一个双向聊天需要最少的代码。更好的选择是一个双向的聊天室有一个单一的模块,并且可以告诉哪种方式来设定流。最佳方法是将其写入服务器端脚本。一个FMS3应用程序的概念是最好的赞赏,当你考虑一个脚本,所有用户使用相同的应用得到不同的信息。您熟悉变量在一个非FMS应用程序改变,但是使用非服务端数据,像数据库。但是,如果别人使用相同的应用,你这样做不会影响其他人使用相同的应用。例如线上游戏,没有服务器端组件。你的分数将不会影响玩同样游戏的其他人的分数。换个方式来考虑这个应用程序不是一个共享的。
在第3章, “非持久客户端远程共享对像”,你学习了共享对象和看到几个用户如何通过一个共同的应用连接,可能会影响他人。没有服务器端脚本应用在这些应用程序中,因为客户端脚本的沟通通过FMS而不需要一个脚本在服务器上。这一章向您介绍服务器端脚本追踪,不管一个或两个用户在一时间内都使用相同的应用程序。脚本与在前面讨论的两个模块的应用程序部分有很大的共通点,接下来这个应用程序只使用一个。因为由两个模块所做的工作现在由服务器端脚本来操作了,您只需要一个单一的模块。
在开始服务端脚本之前,你必须转变一下你的思想:不是使用ActionScript 3.0的,对Flash Media Server 3.0,基本上是您使用的ActionScript 1.0与少数的类。 (如果您不熟悉的ActionScript 1.0 ,把该脚本想像为一个略加修改的JavaScript ) 。这意味着数据没有类型(没有指定数据类型)和您可以使用prototype(原型)来创建类。
无论如何,这第一个脚本是只会做一件事。使用一个数组与两个要素,它将使用array.pop()方法来提供两个字符串中的一个,left和right。当客户端离开,使用array.push()来把元素放置回去 。了解这一切是如何工作的,您首先需要了解两个主要服务器端的类,Application和Client。
服务端ActionScript有大概-15个类。其中三个类一个可以处理XML和两个处理SOAP。实际上,你需要花大部分的时候在其它4个类上:Application, Client, SharedObject 和 Stream。在这个例子中,你只需要前面两个。
顾名思义,Application类处理整个应用程序。每个应用程序,不管有多少客户端连接,都有一个单一的应用程序对象。是什么使这个类不寻常的是,这是自动实例作为应用。所以,当你写SSAS代码,您不必创建一个对象,它自动为您创建。因此,使用这个类,您只需这样写:
application.doSomething...
剩下的章节会探究服务端代码,将会进入到更多的服务端类中,同样也会涉及到Application类的更多的属性,方法,和事件,
Application 事件
· onAppStart
· onConnect
· onDisconect
Application 方法
· rejectConnection
· acceptConnection
客户端只要连接到该应用程序就可以触发应用程序事件。第一个客户端打开应用程序触发onAppStart事件。随后使用者(客户)将不会影响这一事件,只要在应用程序运行时-其中最后客户离开了应用程序 20分钟后,-事件并不触发。
每个连接连接到应用程序都会触发onConnect事件。每个新连接都是通过RTMP来连接的,这个连接可以用Application方法来接受或者拒绝,acceptConnection或者rejectConnection
每当一个客户端断开,客户从客户数组中移除。您也可以使用Application.onDisconnect事件来查找哪个客户断开了。这出现在服务器端脚本中。
像Application类,Client类也自动建立一个它的实例。每一个在应用程序中的客户,都变成应用程序的客户数组中的一部分,每个客户是一个数组元素。例如,假设Nancy, Pete and Juan都连接到相同的应用程序中,Nancy是第一个连接,Juan是最后一个连接。如下所示:
Nancy = application.clients[0];
Pete = application.clients[1];
Juan= application.clients[2];
注意Application的客户属性是带个s:clinets(您可以节省大量的调试时间,记住这一点。)像服务器端脚本显示,Client的实例名称是currentClient 。有点像下面这样:
currentClient = new Client();
然而,这并不是Client的实例名称如何生效。相反,客户端从它连接到服务器的事件函数得到其参考的名字。图5-4显示正确的命名程序。
图5-4. Naming Client instance
currentClient实例对所有客户都有用处,但是紧记,每个连接到应用程序的用户都是Application.clients数组的一部分。像所有类一样,这个实例也可以使用内置的属性,方法和事件。可是,你也可以建立你自已的属性和方法和其它任何类一样。在这章中的应用程序中,属性和方法是为application创建的。脚本中包含用户的方法和属性:
用户的方法写成:
currentClient.streamSelect = function();
添加到currentClient实例的属性叫cliNow,它指定为vidStreams数组的值
currentClient.cliNow=vidStreams.pop();
在脚本顶部中的数组,只有两个元素出现:”right”和”left”。 在streamSelect方法中返回给客户端currentClient.clinow属性的值。
建立一个服务端脚本,产生一个只有两个参与的客户端名称和拒绝其它的客户端,跟随以下步骤:
Example 5-2. deux.asc
Code View:
//Two-element arrayvidStreams=["right","left"];//应用程序第一次启动application.onAppStart = function(){trace("The deux is out of the deck");};//A currentClient (user) attempts to connectapplication.onConnect = function(currentClient){//如果数组是空的话就拒绝连接//(当前有两个用户正在使用应用程序)if (vidStreams.length <= 0){application.rejectConnection(currentClient);}//Store array element in currentClient propertycurrentClient.cliNow=vidStreams.pop();application.acceptConnection(currentClient);currentClient.streamSelect = function(){trace("Stream "+currentClient.cliNow+" used");//Sent the property to Client objectreturn currentClient.cliNow;};};application.onDisconnect = function(currentClient){//When currentClient leaves put the element back in arrayvidStreams.push(currentClient.cliNow);}
3. 在Flash Media Server 3目录下的application目录下建立一个deux的目录
4. 保存deux.asc在deux目录下。或者你也可以把它重命名为main.asc,根据你的喜好。(我比较喜欢命名为应用程序的名称,如果我所有都命名为main.asc,一个不注意被覆盖或者移动,就非常难找了)
在开始写客户端脚本之前,你需要明白这个服务端脚本到底是在什么。无论何时,一个客户端连接到应用程序时,它从数组中删除一个元素,然后通过客户端脚本返回它给客户端。该脚本发送字符串,以确定流出的流和进来的流用什么名称。一旦这两个元素的数组是空的,它不会允许任何其他客户端连接。当一个客户端离开,它把元素放回数组中,然后现在不同的客户端可以加入聊天室了。如果双方当事人离开,两个更多的客户可以使用它。除其他事项外,此脚本保证一个私人的线上影音聊天室。(当然,除非你自已对谈自己) 。
一旦你完成了服务端脚本,现在你可以来设置客户端脚本了。你可以对前面制作的两个模块的应用程序进行简单的修改,把它转换为一个模块的聊天室
为了保证流声音和视频正确地输出,您只需要从服务器端脚本得到一个唯一的字符串。该服务器端脚本返回两个字符串中的一个,用来命名流的名称-left和right。AS3.0 的Responder类用来捕捉服务器端的信息,这样您可以使用它在客户端脚本中。
Responder类有处理返回的数据工作的参数,同样也可以处理错误,这个应用程序焦点只在第一个参数上,所以这个例子没有使用处理错误(后面的例子中会使用到)。图5-5显示了呼叫服务端和回应者角色正在捕捉返回的数据:
Figure 5-5. Responder instance and call to server
在图5-5中,Responder实例指定了一个回调函数用来捕捉呼叫服务端所返回的。NetConnection.call() [nc.call("streamSelect",responder);] 方法包含了服务端的函数名称,前面的呼叫指向到了下面这行(这行在服务端脚本中):
currentClient.streamSelect = function();
一旦发出呼叫和指定回应函数,回调函数要求一个用来捕捉从服务端来的数据的参数。图5-6显示了回调函数是怎么样设置的和每个部分做什么。
图5-6. Responder instance and call to server
在5-6中,回调函数的参数是用来捕捉从服务端发出的东西的关键,因为它包含返回字符串的值。现在,这脚本使用这个值作为唯一的流名称。回调函数包含下面的switch语句:
switch (streamSelect){case "left" :outStream="left";inStream="right";break;case "right" :outStream="right";inStream="left";break;}
Switch语句使用返回的值(在streamSelect中)来决定如何命名流。如果返回的值是”left”,流出的流就命名为”left”,进来的流就命名为”rigth”。反之亦然。
这个程序可能似乎相当复杂,只是在命名一对流名称上。但使用这个脚本请记住,,两个来自全球各地的用户可以成功地协调沟通。此外,这种协调可以安全的只使用一个单一的模块。
客户端文件包含一个与应用程序相同名称的logo。这个logo是一个影片,放置在库中,按以下步骤来建立fla文件和as文件:
1. 建立一个Deux.fla
3. 在舞台中央建立一个文本内容为:Deux,坐标为:x=250, y=30.
4. 在文档类中输入Deux
6. 在Deux.as中输入以下代码:
Code View:
package{import flash.display.Sprite;import flash.display.MovieClip;import flash.events.NetStatusEvent;import flash.net.NetConnection;import flash.net.NetStream;import flash.media.Camera;import flash.media.Microphone;import flash.media.Video;import flash.net.Responder;public class Deux extends Sprite{private var nc:NetConnection;private var good:Boolean;private var netOut:NetStream;private var netIn:NetStream;private var cam:Camera;private var mic:Microphone;private var responder:Responder;private var vidOut:Video;private var vidIn:Video;private var outStream:String;private var inStream:String;public function Deux (){var rtmpNow:String="rtmp://192.168.0.11/deux";nc=new NetConnection;nc.connect (rtmpNow);nc.addEventListener (NetStatusEvent.NET_STATUS,getStream);}private function getStream (e:NetStatusEvent):void{good=e.info.code == "NetConnection.Connect.Success";if (good){responder=new Responder(streamNow);nc.call ("streamSelect",responder);}}private function streamNow (streamSelect:String):void{setCam ();setMic ();setVid ();switch (streamSelect){case "left" :outStream="left";inStream="right";break;case "right" :outStream="right";inStream="left";break;}//Publish local videonetOut=new NetStream(nc);netOut.attachAudio (mic);netOut.attachCamera (cam);vidOut.attachCamera (cam);netOut.publish (outStream, "live");//Play streamed videonetIn=new NetStream(nc);vidIn.attachNetStream (netIn);netIn.play (inStream);}private function setCam ():void{cam=Camera.getCamera();cam.setMode (240,180,15);cam.setQuality (0,85);}private function setMic ():void{mic=Microphone.getMicrophone();mic.rate=11;mic.setSilenceLevel (12,2000);}private function setVid ():void{vidOut=new Video(240,180);addChild (vidOut);vidOut.x=25;vidOut.y=110;vidIn=new Video(240,180);addChild (vidIn);vidIn.x=vidOut.x+260;vidIn.y=110;}}}
当你运行这个程序,你会看到比Easy应用程序更完美。不管如何,当前的两个用户会看到同样的东西。图5-7显示了当应用程序运行正确时,预期你可以看到的。
图5-7. Two-way chat with one module
通过使用一个单一的模块,您可以使用一个单一的文件名称。此应用程序可以与世界各地一起测试。即使它是一个简单的应用,它也可以用来与世界各地沟通。
为了制作一个简单的双向A/V聊天应用程序,需要两个模块。紧记FMS3应用程序只是简单的表现在你使用的RTMP URL为简单的名称,你可以在一个应用程序中有多个模块。换句话说就是,应用的名称是在服务端的目录的名称。
总而言之,你将要开始制作这个应用程序。这个应用程序的名称将会很简单。你将会有两个模块,Easy1和Easy2。每个模块会通过存储在服务端的应用程序,连接到FMS3。对于这个应用程序,每个模块将会写成用来接受其它人发送的流。如你所见,一个简单的换来做所有真实的工作。所以任务真正地包括写一个模块,然后复制它,做一些修改。图5-2展示了两个视频将出现的区域,和它们的实例名:
图5-2. Video instances
开始之前,回顾一下需要的以下类和对像:
Classes
NetConnection
NetStream
NetStatusEvent
Camera
Microphone
Video
按以下步骤来制作这个聊天应用程序:
1. 建立一个Easy1.fla
2. 用文本工具添加一个文本,内容为Easy #1,x=205, y=223
3. 在文档类中输入Easy1
4. 建立一个Easy1.as与Easy1.fla同一目录
Code View:
package{import flash.display.Sprite;import flash.events.NetStatusEvent;import flash.net.NetConnection;import flash.net.NetStream;import flash.media.Camera;import flash.media.Microphone;import flash.media.Video;public class Easy1 extends Sprite{private var nc:NetConnection;private var good:Boolean;private var rtmpNow:String;private var nsIn:NetStream;private var nsOut:NetStream;private var cam:Camera;private var mic:Microphone;private var vidLocal:Video;private var vidStream:Video;public function Easy1 (){rtmpNow="rtmp://your.web.com/easy";nc=new NetConnection();nc.connect (rtmpNow);nc.addEventListener (NetStatusEvent.NET_STATUS,checkCon);setCam ();setMic ();setVideo ();}private function checkCon (e:NetStatusEvent):void{good=e.info.code == "NetConnection.Connect.Success";if (good){nsOut=new NetStream(nc);nsOut.attachAudio (mic);nsOut.attachCamera (cam);nsOut.publish("left","live");nsIn=new NetStream(nc);nsIn.play("right");vidStream.attachNetStream(nsIn);}}private function setCam(){cam=Camera.getCamera();cam.setKeyFrameInterval (9);cam.setMode (240,180,15);cam.setQuality (0,80);}private function setMic(){mic=Microphone.getMicrophone();mic.gain=85;mic.rate=11;mic.setSilenceLevel(15,2000);}private function setVideo(){vidLocal=new Video(cam.width,cam.height);addChild(vidLocal);vidLocal.x=15; vidLocal.y=30;vidLocal.attachCamera(cam);vidStream=new Video(cam.width,cam.height);addChild(vidStream);vidStream.x=(vidLocal.x+ cam.width +10); vidStream.y=vidLocal.y;}}}
6. 确保rtmpNow="rtmp://your.web.com/easy"反射你自已的FMS URL,不管它是在你本机,LAN IP地址或者远程服务器的URL
这已经完成了第一个模块,测试它,你会在左边窗口中看到你自已。下一步将简单的改变第一个模块。
8. Easy1.fla另存为Easy2.fla
public class Easy2 extends Sprite....public function Easy2()
12.在checkCon函数中,改变以下两行:
nsOut.publish("left","live");->nsOut.publish("right","live");....nsIn.play("right"); ->nsIn.play("left");
13.保存Easy2.as文件。现在你的两个模块应用程序已经完成。
步骤12显示了应用程序中的关键几行,Easy1发布一个叫left的流和播放一个叫right的流。Easy2刚好与Easy1相反,所以每个模块的用户可以播放另一个人的流。
测试这个应用程序,理论上你需要两个摄像头和两台电脑。一个用户运行Easy1.html,另一个用户运行Easy2.html。不管在LAN或者网上的远程服务器,两个模块都要能访问到FMS3服务器。图5-3中当你运行两个模块时你应该看到的。
图5-3. Two-way Audio-Video chat
如果可以在远端访问你的IP地址,那么你将可以与世界上的任何人聊天。
第2章和第3章介绍了NetStream类,但是它们没有详细的介绍它。本章中开始研究NetStream类用在现场流中,然后加入到最简单地例子中。使用NetStream类,目的是捕捉从视频和麦克风传来的音频和视频输入,然后发送他们给另一个人看和听。这个程序调用以下NetStream方法:
在看产生一个双向A/V连接顺序中所必需的,流通过NetConnection连接到服务器,用来建立一个在用户和应用程序之间的连接。发布流的时候需要添加要发布在的摄像头和麦克风。流发送到FMS3服务器,然后服务器发送它到连接上的客户端。下面的代码片断展示了这些步骤:
//Stream OutnsOut=new NetStream(nc);nsOut.attachAudio (mic);nsOut.attachCamera (cam);nsOut.publish("left","live");
下面这些代码所做的事情:
现在在您已经有了发布的模块,设立一个播放的模块来捕获和播放被送往的流。您不想捕捉你刚发布的相同的流,所以您将需要有一个除了”left”的流名称。播放流将被称为”right”,要紧记,它代表了当前的接受者。(其他接受者播放”right”和接收“left” )为了捕捉进来的流,你需要把流附加到Video对像上。流包含音频和视频被处理为一个单一的单元—一个视频。您不必把声音对象附加到一个对像上,当你发送视频时。因此,你把流附加到视频对象上使用attachVideo ()方法。一旦流正在发送到正确的位置(嵌入式视频对象),所有你需要做的是就是播放流,如以下代码段所示:
//Stream InnsIn=new NetStream(nc);nsIn.play("right");vidStream.attachNetStream(nsIn);
阅读和显示进来的流的顺序,然后将是:
有更多方法创造一个双向的A / V应用程序,但核心这样做的是与NetStream类方法工作。一旦您直接在您的心目中获得该命令,其余的相当容易。
有时可以把NetStreamod类作为一个包mule。您与不同的东西把它载入,并将按其方式发送它。一旦流到达它的目的地,它卸载其捆绑将收到的视频和音频。像包mule,每一个目的地,需要不同的流。因此,如果您是发出了一个捆绑到九龙,悉尼,日本横滨,孟买,和利马,您需要5个mule,每个mule为每个目的地。至于开发者所关心的,您将只需要建立只有一个单一的NetStream实例,以传送相同的视频和音频到所有那些地方。即使您建立一个单一的实例, FMS3为每一个生成一个单独的流。这很重要,请注意,因为每一个地方接收流,你要付出带宽的代价。 (可以想像购买您的每个包mules是一个在带宽bucks为航线机票支付)
在除了发出bundles,您也想要接收bundles。您发送音频和视频和您想要接收音频和视频。因此,对于每一个您想要接收的对像,您将需要一个NetStream实例。带宽-告诉这可以得到昂贵的迅速。图5-1显示了2个连接和4个连接之间的差别 。
图5-1. Connections and streams
两个连接需要两个流,但是四个连接需要12个流。你可以用以下公式来计算需要几个流:
S=c2 – c
S代表所产生的流的数量,c代表有几个连接
图5-1显示了2个连接只产生两个流(2x 2 = 4; 4 – 2 = 2),4个连接产生12个流(4 x 4 = 16; 16 – 4 = 12)
你可以看到,作为连接数量的增加数值,有多少流增加指数。例如,如果您双重的连接数从4至8,流数量的增加,从12至56-以上翻4倍的流和对带宽的影响。
面对面的沟通的梦想,通过一些像一个电视/电话组合一直围绕在至少过去50年。不过,许诺在远程位置的这种个人之间的沟通,只在最近普遍的实现。开放的Socket技术和高速互联网,如面对面的音频/视频((A/V )的通信,在网络上变得简单而且越来越普遍。
这一章着眼于,使用FMS3创造一种双向音频/视频应用的基本要素-无论是FMIS3或Development FMS3 。FMSS不能用于交互式应用程序。应用程序在这一章中所有使用的类和对象在前几章简要的讨论过了,特别是在第3章中, “设置您的摄像机和话筒”=研究了摄像头,麦克风和视频对象,和NetStream类。在开始之前,您可能要回故之前第3章的内容,使您不太可能迷失在本讨论中。