开发者社区> 范大脚脚> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Fms3和Flex打造在线多人视频会议和视频聊天(附原代码)

简介:
+关注继续查看

1.工作原理

NetStream.publish方法的应用
publish () 方法:将音频流、视频流和文本消息流从客户端发送到 Flash Media Server,并可选择在传输期间录制该流。 此方法仅供指定的流的发布者使用。
第1个参数:标识该流的字符串。
第2个参数:指定如何发布该流的字符串。 有效值为“record”、“append”和“live”。 默认值为“live”。 (这3个参数区别如下:)
如果传递“record”,Flash Player 将发布并录制实时数据,同时将录制的数据保存到名称与传递给 name 参数的值相匹配的新文件中。 该文件保存在服务器上服务器应用程序所在目录的子目录中。 如果该文件存在,则覆盖该文件。
如果传递“append”,Flash Player 将发布并录制实时数据,同时将录制的数据附加到名称与传递给 name 参数的值相匹配的文件中,该文件存储在服务器上包含服务器应用程序的目录的子目录中。如果未找到与 name 参数相匹配的文件,则创建一个文件。 
如果省略此参数或传递“live”,则 Flash Player 将发布实时数据而不进行录制。 如果存在名称与传递给 name 参数的值相匹配的文件,则删除它。

关于NetStream.publish方法还可以看我上篇文章
http://www.cnblogs.com/aierong/archive/2009/01/10/flex_fms_video_start.html

要实现视频会议就是使用的“live”这一类型

来看一下原理图,参加会议的用户将自己本地摄像头捕捉到的画面publish到fms,存放在fms端userList这个集合对象中,集合中存放的是每个用户名也就是他们发布视频的名字。每当用新用户加入或者退出会议的时候,fms就把这个userList广播给每个还在线的用户。用户取得userList只需播放其他几个用户的视频即可。怎么样原理很简单吧! 

 

2.准备工作
在fms安装目录下的application中,新建一个文件夹test_video2,然后启动fms服务器

 

3.开始代码
这次代码分2部分:服务器端的asc文件和客户端

asc文件中有2个重要的类:
Application类:Application类包含有关一个Flash Media Server应用程序实例的信息,它会一直维持这些信息直到这个应用程序实例被卸载。
Client类:Client类让你处理连接到一个Flash Media Server应用程序实例的每一个用户或说client。

Application类有几个重要事件如下:
Application.onAppStart 当这个应用程序被服务器装载时调用。
Application.onAppStop 当这个应用程序被服务器卸载时调用。
Application.onConnect 当一个客户机连接到这个应用程序时调用。
Application.onDisconnect 当一个客户机从这个应用程序断开连接时调用。

Application类有几个重要方法如下:
Application.acceptConnection() 接受一个来自客户机的至一个应用程序的连接。
Application.broadcastMsg() 向所有连接的客户机广播一条消息。
Application.disconnect() 从服务器断开一个客户机的连接。
Application.rejectConnection() 拒绝至一个应用程序的连接。

Client类有1重要方法如下:
Client.call() 在Flash客户机上异步的执行一个方法,并把值从Flash客户机返回到服务器。

 

4.先编写asc文件,打开写字板,键入下面代码,并保存为test_video2.asc,然后copy此文件到test_video2文件夹(asc文件要求和文件夹同名或者叫main.asc)
userList=[];

application.onAppStart=function()
{
 trace("fms服务器启动......");
}

application.onConnect = function(currentClient)
{
 application.acceptConnection(currentClient);
 if (userList.length>=3)
 {
  currentClient.call("showServerMsg",null,"已经达到最大用户数");
  application.rejectConnection(currentClient);
 }
 else
 {                 
  currentClient.communicateServer= function(value)
  {
   currentClient.username=value;
   trace(currentClient.username+"加入聊天室");
   userList.push(value);
   trace("当前用户列表"+userList);
   application.broadcastMsg("playOtherVideo",userList);
  }
 }
}

application.onDisconnect=function(currentClient)
{
 trace("用户"+currentClient.username+"离开聊天室");
 
 for(j=0;j<userList.length;j++)
 {
  if ( userList[j]==currentClient.username )
  {
   userList.splice(j,1);
  }
 }
 trace("当前用户列表"+userList);
 application.broadcastMsg("playOtherVideo",userList);
}

代码说明:
(1)application.broadcastMsg ("客户端方法名",参数..);是asc中一个比较重要的方法,他的作用是向所有连接着的客户端进行广播,调用客户端的函数。这个方法相当于循环遍历Application.clients数组并在每一个独立的客户机上调用Client.call(),但这个方法的效率更高(尤其是当连接的客户机数量很大时)。唯一的不同是当你调用broadcastMsg()时你不能指定一个响应对象,除此以外,两种语法是一样的。
(2)userList.splice(a,b)这个函数,它的作用是从a位置开始移除数组中的b个元素(asc用的是as1语法)
(3)代码中做了限制,只允许最多3人连接fms


5.打开Fb3,创建一个项目

 

6.在主mxml中拖动控件,界面如下:

具体代码如下:
<mx:Label x="10" y="10" text="你的画面"/>
<mx:VideoDisplay x="10" y="38" width="120" height="90" id="vd_myVideo"/>
<mx:TextInput x="152" y="38" text="输入你的名字" id="txt_username" width="116" focusIn="txt_username.text=''"/>
<mx:Button x="288" y="38" label="进入聊天室" id="btn_start"/>
<mx:VBox x="10" y="161" width="120" id="vb_otherVideo">
</mx:VBox>

 

7.导入包和定义变量如下:
import mx.controls.Label;
 
import mx.controls.Alert;
 
private var netConnection:NetConnection;
private var outNetStream:NetStream;
private var camera:Camera;
private var microphone:Microphone;
private var responder:Responder;
private var appServer:String="rtmp://192.168.0.249/test_video2";
private var username:String="";

代码说明:
outNetStream就是你要发布给fms的视频流,通俗的说就是你的画面 
responder 如果client端调用server端as1代码中的某个方法需要有回调函数的话就要定义这个responder,后面会有具体说明 
username 每个用户的用户名,也就是发布时候给视频取得名字

 

8.creationComplete="init()",页面初始化代码
private function init():void
{
 netConnection = new NetConnection();
 netConnection.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler);
 netConnection.connect(appServer);
 netConnection.client=this;
 initMedia();
}
  
private function initMedia():void
{
 camera = Camera.getCamera();
 camera.setMode(120,90,15);
 camera.setQuality(0,90);
 vd_myVideo.attachCamera(camera);
 microphone=Microphone.getMicrophone();
}

private function netStatusHandler(evt:NetStatusEvent):void
{
 trace(evt.info.code);
   
 if ( evt.info.code=="NetConnection.Connect.Success" )
 {
  btn_start.addEventListener(MouseEvent.CLICK,startCommunicate);
 }
 else
 {
  Alert.show("fms连接失败"+evt.info.code);
 }
}
代码比较简单,不明白可以看我上篇
http://www.cnblogs.com/aierong/archive/2009/01/10/flex_fms_video_start.html

 

9.实现按钮事件
private function startCommunicate(evt:MouseEvent):void
{
 username=txt_username.text;
 responder=new Responder(communicateStataHandler);
 netConnection.call("communicateServer",responder,username);
}

private function communicateStataHandler(str:String):void
{
 outMyVideo();
 btn_start.enabled=false;
}

private function outMyVideo():void
{
 /* 发布视频 */
 outNetStream = new NetStream(netConnection);
 outNetStream.attachCamera(camera);
 outNetStream.attachAudio(microphone);
 outNetStream.publish(username,"live");
}
代码说明:
Responder 类提供了一个对象,该对象在 NetConnection.call() 中使用以处理来自与特定操作成功或失败相关的服务器的返回值。 
netConnection.call调用asc文件中的communicateServer,调用成功后,回调communicateStataHandler方法

 

10.showServerMsg方法实现
public function showServerMsg(msg:String):void
{
 Alert.show(msg);
}
代码说明:
供asc文件中调用

 

11.playOtherVideo方法实现:
public function playOtherVideo(newUserList:Array):void
{
 vb_otherVideo.removeAllChildren();
  
 for(var i:int=0;i<newUserList.length;i++)
 {
  if ( newUserList[i]!=username )
  {
   var vd:VideoDisplay = new VideoDisplay();
   var video:Video = new Video();
   video.width=120;
   video.height=90;
   var inNetStream:NetStream= new NetStream(netConnection);
   video.attachNetStream(inNetStream);
   inNetStream.play(newUserList[i]);
   var label:Label= new Label();
   label.text=newUserList[i]+"的画面";
     
   vd.addChild(video);
   vd.width=120;
   vd.height=90;
   vb_otherVideo.addChild(label);
   vb_otherVideo.addChild(vd);       
  }
 }
}
代码说明:
asc文件中application.broadcastMsg方法调用,向所有连接的客户机广播

 

12.运行程序,图片如下,其中有一人没视频摄像头

 

13.代码下载
http://files.cnblogs.com/aierong/Video2.rar
您收到代码后,请回到文章下面留言告之一下!要是没收到,我可以再发!

提供代码是为了互相学习,一起探讨!请大家多交流!
1.要是对代码有什么疑问,可以在文章的评论区留言,我会尽我所能答复您!
2.要是您在运行代码的过程中发现bug,或者是您有什么好的建议和意见,也可以在文章的评论区留言给我,我会及时更正!

 


评论区使用提示:
评论区留言(使用高级评论)是可以贴图片的,要是有难以描述的问题,可以贴图片和文字一起说明
谢谢!


本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/p/4151463.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
FFMPEG音频视频开发: VS2010+QT4.8.5引用FFMPEG库
FFMPEG音频视频开发: VS2010+QT4.8.5引用FFMPEG库
51 0
CSS3 flex的使用方法
display:flex; align-items://水平对齐方式 justify-content://垂直对齐方式 flex://盒子所占大小(如果你盒子里面只有两个div,那么你设置其中之一个flex,那么另外一个会自动填充)
539 0
1.4. 桢缓存 The Frame Buffer
1.4. 桢缓存 The Frame Buffer OpenGL is an API for drawing graphics, and so the fundamental purpose for OpenGL is to transform data provided by an...
717 0
linux下的framebuffer显示图片
<p>void  showbmp2()<br>  {<br>      int x,y;<br>      unsigned char *p;<br>      int index=0; <br>      struct fb_var_screeninfo vinfo;  <br>      struct fb_fix_screeninfo finfo;  </p> <p> 
1690 0
+关注
3656
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载