首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 媒体动画 > flex >

flex + red5兑现视频会议

2012-07-19 
flex + red5实现视频会议????? 公司最近要在系统中加视频会议的功能,让我探索,我选择了最流行的red5来实现

flex + red5实现视频会议

????? 公司最近要在系统中加视频会议的功能,让我探索,我选择了最流行的red5来实现,网上有一对一聊天的demo,找不到多对多聊天的,也没有具体介绍系统搭建的过程,我通过自己的摸索,将实现的过程和大家一起分享。java的web项目添加flex支持在此不再详述,项目文件结构如图:


flex + red5兑现视频会议


flex + red5兑现视频会议
?
?
flex + red5兑现视频会议


?web.xml文件:

<?xml version="1.0" encoding="UTF-8"?><web-app   version="2.4"   xmlns="http://java.sun.com/xml/ns/j2ee"   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><!--    ** For use with servlet v2.5 replace the lines above with these    version="2.5"    xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"--><display-name>Red5ChartRoom</display-name><context-param><param-name>globalScope</param-name><param-value>default</param-value></context-param><context-param><param-name>parentContextKey</param-name><param-value>default.context</param-value></context-param><context-param><param-name>webAppRootKey</param-name><param-value>@webapp.root.key@</param-value></context-param><context-param><param-name>contextConfigLocation</param-name><param-value>WEB-INF/classes/*-web.xml</param-value></context-param><listener><listener-class>org.red5.server.war.WarLoaderServlet</listener-class></listener>    <listener>        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>    </listener><servlet><servlet-name>gateway</servlet-name><servlet-class>org.red5.server.net.servlet.AMFGatewayServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet><servlet-name>rtmpt</servlet-name><servlet-class>org.red5.server.net.rtmpt.RTMPTServlet</servlet-class><load-on-startup>2</load-on-startup></servlet> <!-- MessageBroker Servlet --> <servlet>  <display-name>MessageBrokerServlet</display-name>  <servlet-name>MessageBrokerServlet</servlet-name>  <servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>  <init-param>   <param-name>services.configuration.file</param-name>   <param-value>/WEB-INF/flex/services-config.xml</param-value>  </init-param>  <load-on-startup>11</load-on-startup> </servlet><servlet-mapping><servlet-name>gateway</servlet-name><url-pattern>/gateway</url-pattern></servlet-mapping>    <servlet-mapping>        <servlet-name>rtmpt</servlet-name>        <url-pattern>/fcs/*</url-pattern>    </servlet-mapping><servlet-mapping><servlet-name>rtmpt</servlet-name><url-pattern>/open/*</url-pattern></servlet-mapping><servlet-mapping><servlet-name>rtmpt</servlet-name><url-pattern>/idle/*</url-pattern></servlet-mapping><servlet-mapping><servlet-name>rtmpt</servlet-name><url-pattern>/send/*</url-pattern></servlet-mapping><servlet-mapping><servlet-name>rtmpt</servlet-name><url-pattern>/close/*</url-pattern></servlet-mapping> <servlet-mapping>  <servlet-name>MessageBrokerServlet</servlet-name>  <url-pattern>/messagebroker/*</url-pattern> </servlet-mapping> <welcome-file-list><welcome-file>login.html</welcome-file><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file></welcome-file-list><security-constraint><web-resource-collection><web-resource-name>Forbidden</web-resource-name><url-pattern>/WEB-INF/*</url-pattern></web-resource-collection><auth-constraint /></security-constraint><security-constraint><web-resource-collection><web-resource-name>Forbidden</web-resource-name><url-pattern>/persistence/*</url-pattern></web-resource-collection><auth-constraint /></security-constraint><security-constraint><web-resource-collection><web-resource-name>Forbidden</web-resource-name><url-pattern>/streams/*</url-pattern></web-resource-collection><auth-constraint /></security-constraint></web-app>

?red5ChartRoom-web.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:lang="http://www.springframework.org/schema/lang"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd                           http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd"><bean id="web.context.chatroom" ref="red5.scopeResolver"></property><property name="clientRegistry" ref="global.clientRegistry"/><property name="serviceInvoker" ref="global.serviceInvoker"/><property name="mappingStrategy" ref="global.mappingStrategy"/></bean><bean id="web.scope" init-method="register"><property name="server" ref="red5.server"/><property name="parent" ref="global.scope"/><property name="context" ref="web.context.chatroom"/><property name="handler" ref="web.handler.chatroom"/><property name="contextPath" value="/Red5ChatRoom"/><property name="virtualHosts" value="*,localhost,localhost:8080,127.0.0.1:8080"/></bean><bean id="web.handler.chatroom" name="code"># Socket policypolicy.host=0.0.0.0policy.port=843# HTTPhttp.host=0.0.0.0http.port=5080https.port=8443# RTMPrtmp.host=0.0.0.0rtmp.port=1935rtmp.io_threads=16rtmp.connect_threads=4rtmp.send_buffer_size=271360rtmp.receive_buffer_size=65536rtmp.ping_interval=1000rtmp.max_inactivity=60000rtmp.tcp_nodelay=true# RTMPSrtmps.host=0.0.0.0rtmps.port=8443rtmps.ping_interval=5000rtmps.max_inactivity=60000rtmps.max_keep_alive_requests=-1rtmps.max_threads=20rtmps.acceptor_thread_count=2rtmps.processor_cache=20# RTMPS Keystore Passwordrtmps.keystorepass=password# RTMPTrtmpt.host=0.0.0.0rtmpt.port=8088rtmpt.ping_interval=5000rtmpt.max_inactivity=60000rtmpt.max_keep_alive_requests=-1rtmpt.max_threads=20rtmpt.acceptor_thread_count=2rtmpt.processor_cache=20# MRTMPmrtmp.host=0.0.0.0mrtmp.server=localhostmrtmp.port=9035mrtmp.event_threads_core=4mrtmp.event_threads_max=32# event threads queue: -1 unbounded, 0 direct (no queue), n bounded queuemrtmp.event_threads_queue=0mrtmp.event_threads_keepalive=60mrtmp.send_buffer_size=271360mrtmp.receive_buffer_size=65536mrtmp.ping_interval=5000mrtmp.max_inactivity=60000mrtmp.tcp_nodelay=true# Debug proxy (needs to be activated in red5-core.xml)proxy.source_host=127.0.0.1proxy.source_port=1936proxy.destination_host=127.0.0.1proxy.destination_port=1935# JMXjmx.rmi.port.registry=9999jmx.rmi.port.remoteobjects=jmx.rmi.host=127.0.0.1jmx.rmi.ssl=falsered5.config_root=red5.config_rootred5.root=E\:apache-tomcat-6.0.33

?

java代码

package com.chinahrt.chat;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import org.python.antlr.PythonParser.return_stmt_return;import org.red5.server.adapter.ApplicationAdapter;import org.red5.server.api.IConnection;import org.red5.server.api.IScope;import org.red5.server.api.Red5;import org.red5.server.api.service.IServiceCapableConnection;import org.red5.server.api.so.ISharedObject;import org.red5.server.api.stream.IBroadcastStream;/** * createBy ZYN * * createTime 2011-9-16 下午03:33:15 * * desc 视频聊天服务器 * */public class VedioChatApplication extends ApplicationAdapter {private IScope appScope;private String userName;//共享存贮在线用户private ISharedObject listSO;private Map<String,IConnection> onlineList = new HashMap<String,IConnection> ();//在线用户表//程序运行//程序运行时志向 public boolean appStart(IScope app) {   if (!super.appStart(app)) {       return false;   }   appScope = app;   return true; } @Override public boolean appConnect(IConnection arg0, Object[] arg1) {   /**    *  用户首次连接server 时触发,检查用户是否重复登录,将用户添加到在线用户表中    */   String userId=arg0.getClient().getId();   if(!super.appConnect(arg0, arg1)){    return false;   }   if (arg1 != null ) {    userName = (String) arg1[0];   }   if(onlineList.get(userName) != null){    rejectClient("请不要重复登录");    return false;   }   onlineList.put(userName, arg0);   listSO = getSharedObject(appScope, "listSO", false);   listSO.setAttribute(userId, userName);   System.out.println("The user:"+userName+","+userName+" logined successfully");   return true; } /**   * 通知所有人当前用户登录   * @param params   */ public void getOnloadUser(Object[] params) {     String clientName = params[0].toString();    if(null == clientName || "".equals(clientName)) {      return ;    }   //给所有客户端数据    IScope scope = Red5.getConnectionLocal().getScope();    Iterator it = scope.getConnections().iterator();    for (;it.hasNext();) {     Set connections = (Set)it.next();     IConnection tempConn = (IConnection)connections.iterator().next();     if (tempConn instanceof IServiceCapableConnection) {      IServiceCapableConnection sc = (IServiceCapableConnection) tempConn;      sc.invoke("result_getOnloadUser", new Object[]{clientName});     }    } } //聊天   public void sayToAll(Object[] params) {    IConnection conn = Red5.getConnectionLocal();    String user_id = conn.getClient().getId();    String clientName =(String) listSO.getAttribute(user_id);    System.out.println("************发言者是:"+clientName);    String sayToName=params[0]==null?"":params[0].toString().trim();      String sayWhat=params[1]==null?"":params[1].toString().trim();    if("".equals(sayToName)||"All".equals(sayToName))// 发消息给聊天室的所有人.    {     IScope scope = Red5.getConnectionLocal().getScope();     Iterator it = scope.getConnections().iterator();      for (;it.hasNext();) {       Set connections = (Set)it.next();       IConnection tempConn = (IConnection)connections.iterator().next();      if (tempConn instanceof IServiceCapableConnection) {          IServiceCapableConnection sc = (IServiceCapableConnection) tempConn;       // 调用客户端showMessage方法。          sc.invoke("showMessage", new Object[]{clientName+" to All:"+sayWhat});       }    }    }else{      IConnection tempConn=onlineList.get(sayToName);          if (tempConn instanceof IServiceCapableConnection) {       IServiceCapableConnection sc = (IServiceCapableConnection) tempConn;           sc.invoke("showMessage", new Object[]{clientName+" to "+sayToName+":"+sayWhat});       }      IServiceCapableConnection sc = (IServiceCapableConnection) conn;      sc.invoke("showMessage", new Object[]{clientName+" to "+sayToName+":"+sayWhat});    }   } // 用户断开连接的时候触发   public void appDisconnect(IConnection conn) {    String dis_user_id = conn.getClient().getId();    String user = (String) listSO.getAttribute(dis_user_id);    // 根据ID删除对应在线纪录    onlineList.remove(user);    // 删除用户列表共享对象的对应属性    listSO.removeAttribute(dis_user_id);    IScope scope = Red5.getConnectionLocal().getScope();     Iterator it = scope.getConnections().iterator();      for (;it.hasNext();) {      Set connections = (Set)it.next();      IConnection tempConn = (IConnection)connections.iterator().next();      if (tempConn instanceof IServiceCapableConnection) {          IServiceCapableConnection sc = (IServiceCapableConnection) tempConn;        // 服务器端调用客户端flash方法。          sc.invoke("disconnectMessage", new Object[]{user});       }     }   } }

?flex端代码

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"><mx:Script><![CDATA[import mx.collections.ArrayCollection;import mx.containers.HBox;import mx.controls.Alert;private var listSO:SharedObject;private var userArr:Array;private var conn:NetConnection;private var localUsername:String;[Bindable]private var cam:Camera;[Bindable]private var mic:Microphone;[Bindable]public var cards:ArrayCollection;public var videoUsers:Array;[Bindable]public var videoControlArr:Array;private var stm:NetStream;[Bindable]private var video_self:Video;protected function login(event:MouseEvent):void{localUsername = txt_name.text;if(localUsername== ""){Alert.show("用户名不能为空");}else{if(conn == null){conn = new NetConnection();conn.client = this;conn.addEventListener(NetStatusEvent.NET_STATUS,_statusHandler);conn.connect("rtmp://192.168.1.61/Red5ChatRoom",localUsername);}}}//状态监听private function _statusHandler(evt:NetStatusEvent):void{if(evt.info.code == "NetConnection.Connect.Success"){this.currentState = "chat";Alert.show("连接成功");video_clickHandler();this.showJoinInInfo(localUsername);_setListSO();}if(evt.info.code == "NetConnection.Connect.Failed"){Alert.show("连接失败");}if(evt.info.code == "NetConnection.Connect.Closed"){Alert.show("连接关闭");}}public function showJoinInInfo(message:String):void{conn.call("getOnloadUser",null,message);}public function result_getOnloadUser(str:String):void{txt_chatmsg.text += str + "加入聊天室" + "\n";}//创建用户列表共享对象private function _setListSO():void{listSO = SharedObject.getRemote("listSO",conn.uri,false);listSO.connect(conn);listSO.addEventListener(SyncEvent.SYNC,_listSOSyncHandler);}//用户列表共享对象被更新之后的事件private function _listSOSyncHandler(evt:SyncEvent):void{_showUserList();//更新用户列表}private function _showUserList():void{cards = new ArrayCollection([{label:"All"}]);userArr = new Array();//用户数组更新for(var tmp:String in listSO.data){userArr.push(listSO.data[tmp]);}//添加到arrayCollectionfor(var i:int = 0; i<userArr.length;i++){cards.addItem({label:userArr[i]});}//将数组添加到列表数组中显示出来userList.dataProvider = cards;users.dataProvider = cards;addVideo(cards);}public function showMessage(message:String):void{txt_chatmsg.text += message + "\n";}protected function sendMessage(event:MouseEvent):void{var sendString:String = txt_yousay.text;var sendTo:String = userList.selectedItem.label;txt_yousay.text = "";conn.call("sayToAll",null,sendTo,sendString);}//断线通知public function disconnectMessage(disUser:String):void{txt_chatmsg.text += disUser+"退出聊天室\n";}//进入视频会议public function video_clickHandler():void{stm = new NetStream(conn);cam = Camera.getCamera();if(cam==null){Alert.show("没有可以使用的摄像头");return;}else{Security.showSettings(SecurityPanel.PRIVACY);cam.addEventListener(StatusEvent.STATUS,statusHandler);cam.addEventListener(ActivityEvent.ACTIVITY,activityHandler);cam.setLoopback(true);cam.setMotionLevel(50,100);cam.setMode(1280,960,15,true); stm.attachCamera(cam);}mic = Microphone.getMicrophone();mic.addEventListener(StatusEvent.STATUS,micOnstatu);if(mic == null){Alert.show("没有可以使用的麦克风");}else{mic.setUseEchoSuppression(true);stm.attachAudio(mic);}stm.play("chinahrt-"+txt_name.text);stm.publish("chinahrt-"+txt_name.text,"live");video_self = new Video();video_self.width = 320;video_self.height = 240;video_self.attachCamera(cam);my_video.addChild(video_self);}private function micOnstatu(e:StatusEvent):void{mic.setLoopBack(true);mic.gain = 66;mic.rate = 11;mic.setUseEchoSuppression(true);mic.setSilenceLevel(1,-1);}private function statusHandler(e:StatusEvent):void{}private function activityHandler(e:ActivityEvent):void{}private function addVideo(cards:ArrayCollection):void{label1.text = "我的("+localUsername+")";myBox.removeAllChildren();var otherPerson:ArrayCollection = new ArrayCollection();for(var i:int=0;i<cards.length;i++){var o:Object = cards.getItemAt(i);if(o["label"]!=localUsername&&o["label"]!="All"){otherPerson.addItem(o);}}//Alert.show(otherPerson.length+"");var yushu:int = 0;var yushu:int= otherPerson.length%3;var rowNum:int = 0;var rowNum:int = otherPerson.length/3;if(yushu!=0){rowNum += 1;}if(yushu==0){for(var i:int=0;i<rowNum;i++){var hbox:HBox = new HBox();myBox.addChild(hbox);for(var ii:int=0;ii<3;ii++){var vbox:VBox = new VBox();hbox.addChild(vbox);var label:Label = new Label;label.text = otherPerson.getItemAt(i*3+ii)["label"];vbox.addChild(label);var videoDisplay:VideoDisplay = new VideoDisplay();videoDisplay.live = true;videoDisplay.width = 320;videoDisplay.height = 240;vbox.addChild(videoDisplay);var video:Video = new Video();video.width = 320;video.height = 240;var netStream:NetStream = new NetStream(conn);video.attachNetStream(netStream);netStream.play("chinahrt-"+label.text);videoDisplay.addChild(video);}}}else{for(var i:int=0;i<rowNum-1;i++){var hbox:HBox = new HBox();myBox.addChild(hbox);for(var ii:int=0;ii<3;ii++){var vbox:VBox = new VBox();hbox.addChild(vbox);var label:Label = new Label;label.text = otherPerson.getItemAt(i*3+ii)["label"];vbox.addChild(label);var videoDisplay:VideoDisplay = new VideoDisplay();videoDisplay.live = true;videoDisplay.width = 320;videoDisplay.height = 240;vbox.addChild(videoDisplay);var video:Video = new Video();video.width = 320;video.height = 240;var netStream:NetStream = new NetStream(conn);video.attachNetStream(netStream);netStream.play("chinahrt-"+label.text);videoDisplay.addChild(video);}}var hbox:HBox = new HBox();myBox.addChild(hbox);for(var i:int=0;i<yushu;i++){var vbox:VBox = new VBox();hbox.addChild(vbox);//myBox.addChild(vbox);var label:Label = new Label();label.text = otherPerson.getItemAt((rowNum-1)*3+i)["label"];vbox.addChild(label);var videoDisplay:VideoDisplay = new VideoDisplay();videoDisplay.live = true;videoDisplay.width = 320;videoDisplay.height = 240;vbox.addChild(videoDisplay);var video:Video = new Video();video.width = 320;video.height = 240;var netStream:NetStream = new NetStream(conn);//Alert.show(otherPerson.getItemAt((rowNum-1)*3+i)["label"]);video.attachNetStream(netStream);netStream.play("chinahrt-"+label.text);videoDisplay.addChild(video);}}}]]></mx:Script><mx:states> <mx:State id="chatState" name="chat"> <mx:SetProperty target="{form1}" name="width" value="0"/> <mx:SetProperty target="{form1}" name="height" value="0"/> <mx:SetProperty target="{form1}" name="x" value="0"/> <mx:SetProperty target="{form1}" name="y" value="0"/> <mx:AddChild position="lastChild"> <mx:Panel x="10" y="10" width="381" height="370" layout="absolute" title="聊天信息"> <mx:TextArea x="10" y="10" width="215" height="235" id="txt_chatmsg"/> <mx:ComboBox x="233" y="34" width="118" id="userList"></mx:ComboBox> <mx:Label x="233" y="11" text="用户列表"/> <mx:DataGrid x="233" y="64" height="256" id="users" width="118"> <mx:columns> <mx:DataGridColumn headerText="用户名" dataField="label"/> </mx:columns> </mx:DataGrid> <mx:TextInput x="10" y="253" height="67" width="150" id="txt_yousay"/> <mx:Button x="168" y="253" label="发送" width="57" click="sendMessage(event)"/> <!--<mx:Button x="168" y="298" label="进入视频会议" width="57" click="video_clickHandler(event)"/>--> </mx:Panel> </mx:AddChild> <mx:AddChild position="lastChild"> <mx:VideoDisplay live="true" x="10" y="410"  width="320" height="240" id="my_video"/> </mx:AddChild> <mx:AddChild position="lastChild"> <mx:Label id="label1" x="10" y="390" text="我的"/> </mx:AddChild> <!--<mx:AddChild position="lastChild"> <mx:VideoDisplay live="true"  x="399" y="224"  width="320" height="240" id="other_video"/> </mx:AddChild> <mx:AddChild position="lastChild"> <mx:Label x="399" y="198" text="对方的"/> </mx:AddChild> --><mx:AddChild position="lastChild"><mx:VBox id="myBox" x="399" y="10"/></mx:AddChild></mx:State> </mx:states> <mx:Form x="10" y="10" width="283" height="126" id="form1"> <mx:FormItem label="用户名:"> <mx:TextInput id="txt_name"/> </mx:FormItem> <mx:FormItem> <mx:Button label="登陆" click="login(event)"/> </mx:FormItem> </mx:Form> </mx:Application>

?

1 楼 xiaoyayahappy 2011-12-07   饿,终于找到这篇文章了,我在搭建的过程中发生点小问题,不知道是否可以与阁下讨论下。。 2 楼 zyn010101 2011-12-09   xiaoyayahappy 写道饿,终于找到这篇文章了,我在搭建的过程中发生点小问题,不知道是否可以与阁下讨论下。。
zyn010101@163.com,你发邮件给我吧
3 楼 zdb_cn 2012-04-25   求源码。。。。。。。。。。 4 楼 zyn010101 2012-04-25   zdb_cn 写道求源码。。。。。。。。。。
代码已经全部贴上去了... 5 楼 bingfengfzl 2012-05-31   楼主可以吧你这个 demo发给我吗,我最近也在学习flex + red5,你这个程序能不能连接IP摄像头的? 6 楼 bingfengfzl 2012-05-31   bingfengfzl@163.com

热点排行