转 red5

flex4+red5实现文字聊天与视频邀请功能

为了工作需要学习red5,现将几天的工作成绩贴上来..

界面效果图:


FELX客户端代码:

 <s:TextInput x="130" y="37" width="175" id="nickName"/>
 <s:Button x="313" y="38" label="加入聊天室" click="connectAndJoinRoom();"/>
 <s:TextArea x="84" y="67" width="311" height="374" id="roomArea"/>
 <s:TextInput x="84" y="449" width="233" id="inputWhatYouWantSay"/>
 <s:Button x="325" y="450" label="发送" id="sendButton" click="sendMessage();" enabled="false"/>
 <s:Label x="84" y="43" text="昵称:"/>
 <s:TextArea x="403" y="290" width="516" id="systemInfo" editable="false"/>
 <s:Label x="403" y="273" text="调试窗口:" fontWeight="bold"/>
 <s:Label x="405" y="50" text="用户列表:" fontWeight="bold"/>
 <s:VideoDisplay x="601" y="67" width="153" height="153" id="localVideo"/>
 <s:Button x="735" y="231" label="申请视频交流" id="sendVideoBtn" enabled="false" click="inviteVideo()"/>
 <mx:DataGrid x="403" y="70" width="185" height="182" id="userList">
  <mx:columns>
   <mx:DataGridColumn headerText="用户名" dataField="label"/>
  </mx:columns>
 </mx:DataGrid>
 <s:VideoDisplay x="772" y="67" width="153" height="153" id="remoteVideo"/>
 <s:TextInput x="601" y="230" width="130" enabled="false" id="selectUser"/>
 <s:Button x="835" y="231" label="关闭视频窗" width="90" id="closeVideoBtn" enabled="false" click="closeStream()"/>
 <fx:Script>
  <![CDATA[
   import flash.events.NetStatusEvent;
   import flash.media.Camera;
   import flash.media.Microphone;
   import flash.media.Video;
   import flash.net.NetConnection;
   import flash.net.NetStream;
   import flash.net.Responder;
   import flash.net.SharedObject;
   
   import mx.collections.ArrayCollection;
   import mx.controls.Alert;
   import mx.events.CloseEvent;
   import mx.events.DataGridEvent;
   import mx.events.ListEvent;
   
   
   private var nc:NetConnection; 
   private var responder:Responder;
   private var randomUser:String;
   private var  listSO:SharedObject;
   private var userArr:Array;
   private var outNs:NetStream;
   private var inNs:NetStream;
   private var lVideo:Video;
   private var rVideo:Video;
   private var cam:Camera;
   private var mic:Microphone;
   private var videoUsers:Array;
   
   [Bindable]
   private var cards:ArrayCollection;
   
   
   internal function init():void{
    randomUser ="User" + Math.round(Math.random()*100000).toString();
    nickName.text = randomUser;
   }
   
   private function connectAndJoinRoom():void{   
    
    
     responder = new Responder(doTips);
     var _nickName:String = nickName.text;
     if(_nickName == ""){
        return;
     }else{
       if( nc == null ){
      initalNetConnection();
    }
     }
   }   
   
   private function initalNetConnection():void{
     nc = new NetConnection();
     nc.addEventListener(NetStatusEvent.NET_STATUS,connectStatus);
     nc.client = this;
     nc.connect("rtmp://10.0.0.100/helloWorld",nickName.text);    
   }
   
   internal function connectStatus(evt:NetStatusEvent):void{
    // Alert.show(evt.info.code);
     systemInfo.appendText("SystemInfo:"+evt.info.code+"\n");
     if(evt.info.code == "NetConnection.Connect.Success"){
        nc.call("jionChatRoom",null,nickName.text);
     _setListSO();
     sendButton.enabled = true;
     }
   }
   
   private function sendMessage():void{
     var sendString:String = inputWhatYouWantSay.text;    
     nc.call("sayToAll",null,sendString);
     inputWhatYouWantSay.text = "";
   }
   
   public function showJionInInfo(message:String):void{
    if(nickName.text != message.toString()){
      roomArea.appendText(message + "加入聊天室\n");
    }
   }
   
   public function showJionInInfos(message:String):void{
    roomArea.appendText(message + "\n");
   }
   
   public function showMessage(message:String):void{    
       roomArea.appendText(message + "\n"); 
   }
     
   internal function doTips():void{
     Alert.show("发送成功");
   }
   
   public function loginInfo(info:String):void{
    roomArea.appendText(info + "\n");
   }
   
   public function disconnectMessage(info:String):void{
    roomArea.appendText(info + "退出聊天室!\n");
   }
   
   internal function _setListSO():void{
    listSO = SharedObject.getRemote("listSO",nc.uri,false);
    listSO.connect(nc);
    listSO.addEventListener(SyncEvent.SYNC,syncHander);
    
    userList.addEventListener(ListEvent.ITEM_CLICK,clickHander);
   }
   
   internal function clickHander(evt:ListEvent):void{
      selectUser.text = evt.target.selectedItem.label;
      sendVideoBtn.enabled = true;
   }
   
   internal function syncHander(evt:SyncEvent):void{
      _showUserList();
   }
   
   internal function _showUserList():void{
      cards = new ArrayCollection();
      userArr = new Array();
      for(var tmp:String in listSO.data){
        userArr.push(listSO.data[tmp]);
      }
     
      for(var i:int = 0; i < userArr.length; i++){
        cards.addItem({label:userArr[i]});
      }
     
      userList.dataProvider = cards;     
     
   }
   
   
   
   internal function inviteVideo():void{
     
    var toUser:String = selectUser.text==null?"":selectUser.text;
    if(toUser!=""){
       nc.call("videoInvite",null,toUser);
    }else{
       Alert.show("请选择要视频的用户!");
    }
     
   }
   
   public function showInviteMessage(message:String):void{
    videoUsers=message.split(";");
    Alert.show(videoUsers[0]+"邀请你视频,是否同意?","是吗",Alert.YES|Alert.NO,this,alertClientHandel);
   }
   
   internal function alertClientHandel(evt:CloseEvent):void{
    if(evt.detail == Alert.YES){
     _publishVideo();
     _getVideo();
     nc.call("agreeVideoInvite",null,videoUsers[0],videoUsers[1]);
     closeVideoBtn.enabled = true;
     sendVideoBtn.enabled = false;
    }
   }
   
   internal function _publishVideo():void{
    outNs = new NetStream(nc);
    lVideo = new Video();
    lVideo.width = 153;
    lVideo.height = 153;
    cam = Camera.getCamera();
    if(cam != null){
     cam.setMotionLevel(50,100);
     cam.setMode(153,153,15,true);
     outNs.attachCamera(cam);
    }else{
       Alert.show("没有可使用的摄像头!");
    }
    
    mic = Microphone.getMicrophone();
    if(mic != null){
     mic.setUseEchoSuppression(true);
     outNs.attachAudio(mic);
    }else{
       Alert.show("没有可使用的麦克风!");
    }    
    localVideo.addChild(lVideo);
    outNs.publish(nickName.text,"live");
   }
   
   internal function _getVideo():void{
      lVideo = new Video();
      lVideo.width = 153;
      lVideo.height = 153;
      lVideo.attachCamera(cam);
      localVideo.addChild(lVideo);     
   }
   
   internal function _getOtherVideo(other:String):void{
      inNs = new NetStream(nc);
      rVideo = new Video(153,153);
      rVideo.attachNetStream(inNs);
      remoteVideo.addChild(rVideo);
      inNs.play(other);
      closeVideoBtn.enabled = true;
      sendVideoBtn.enabled = false;
   }
   
   public function showVideo(other:String):void{
    _publishVideo();
    _getOtherVideo(other);
    closeVideoBtn.enabled = true;
    sendVideoBtn.enabled = false;
   }
   internal function closeStream():void{
    // Alert.show("关闭视频流!");
     nc.call("discuzVideo",null,videoUsers[0],videoUsers[1]);
     closeVideoBtn.enabled = false;
     sendVideoBtn.enabled = true;
   }
   
   public function discuzVideo(str:String):void{
      Alert.show(str+"已断开视频!");
     
      outNs.close();
      inNs.close();
     
      closeVideoBtn.enabled = false;
      sendVideoBtn.enabled = true;
   }
   
  ]]>
 </fx:Script>

RED5服务器端代码:

package org.d5.sayHello;
import org.red5.server.adapter.ApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.service.IServiceCapableConnection;
import org.red5.server.api.Red5;
import org.red5.server.api.so.ISharedObject;
import org.red5.server.api.IScope;
import java.util.Set;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;

public class Application extends ApplicationAdapter{
 private IScope appScope;
 private String userName;
 private ISharedObject listSO;
 private Map<String,IConnection> onlineList = new HashMap<String,IConnection>();
 private String errorInfo;
 public  String login(){
    System.out.println("Login successs...");
    return "Say Hello World";
    }
 /**
  *
  *
  */
 public boolean appStart(IScope app){
  return true;
 }
   /**
    * 每个新的客户端来连接时调用
    * 这是我们覆盖了父类的实现
    */
   public boolean appConnect(IConnection con,Object[] pareams){
    System.out.println("new client connectting chat room");
    errorInfo = pareams[0].toString()+"登陆成功!";
    String userId = con.getClient().getId();
   
   if(!super.appConnect(con, pareams)){
     return false;
    }  
    if(pareams != null){
      userName = (String)pareams[0];
      errorInfo = userName + "进入聊天室!";
    }
    
    if(onlineList.get(userName) != null){
     errorInfo = userName + "请不要重复登陆!";
           return false;
    }

    onlineList.put(userName, con);
  appScope = Red5.getConnectionLocal().getScope();
  this.createSharedObject(appScope,"listSO",false);
     listSO = this.getSharedObject(appScope, "listSO");
     listSO.setAttribute(userId, userName);
   
    if(con instanceof IServiceCapableConnection){
     IServiceCapableConnection sc = (IServiceCapableConnection)con;
     sc.invoke("loginInfo",new Object[]{errorInfo});
    }   
    return true;
   } 
   /**
   * 当客户端断开连接的时候调用!
   * 这里我们覆盖了父类的实现。
   */
   @SuppressWarnings("unchecked")
   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;
        sc.invoke("disconnectMessage",new Object[]{user});
       }
       }   
   }
   /**
   * 加入聊天室,必须带上用户名,假如用户名为空,则不能发送消息,也不能收到消息。
   * @param params 客户端调用服务器端的参数。
   */
   @SuppressWarnings("unchecked")
   public void jionChatRoom(Object[] params){
   String nickName = params[0].toString();
   if(null == nickName || "".equals(nickName)){
   return;
   }else{
   IConnection conn = Red5.getConnectionLocal();
   conn.setAttribute("nickName", nickName);
   }
   //发通知给聊天室的所有的人,有新人加入了。
   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("showJionInInfo",new Object[]{nickName});
       }
      }
   }
   /**
   * 给聊天室的所有人发送消息
   * @param params
   */
   @SuppressWarnings("unchecked")
   public void sayToAll(Object[] params){
   IConnection conn = Red5.getConnectionLocal();
   String nickName = conn.getAttribute("nickName").toString();
   String sayWhat = params[0].toString();
  
   //发消息给聊天室的所有人
   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("showJionInInfos",new Object[]{nickName+":"+sayWhat});
    }
   }  
   } 
   /**
    * 视频邀请
    */
   public void videoInvite(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();
    if("".equals(sayToName)){
     System.out.print("你的邀请不合法!!");
    }else{
     IConnection tempConn = onlineList.get(sayToName);
     if(tempConn instanceof IServiceCapableConnection){
     IServiceCapableConnection sc = (IServiceCapableConnection) tempConn;    
     sc.invoke("showInviteMessage", new Object[]{clientName+";"+sayToName});
     }
    }
   }
   /**
    * 同意邀请后调用的邀请方法
    */
    public void agreeVideoInvite(Object[] params){
     //IConnection conn = Red5.getConnectionLocal();
     //邀请者
     String inviteUserName = params[0] == null?"":params[0].toString().trim();
     //被邀请者
     String otherUserName = params[0] == null ?"":params[1].toString();
     if("".equals(inviteUserName)){  //发送消息给聊天室的所有人
      System.out.print("出错了");
     }else{
      IConnection tempconn = onlineList.get(inviteUserName);
      if(tempconn instanceof IServiceCapableConnection){
          IServiceCapableConnection sc = (IServiceCapableConnection) tempconn;    
          sc.invoke("showVideo", new Object[]{otherUserName});
      }
     }
    }
    /**
     * 关闭视频提示
     */
    public void discuzVideo(Object[] params){
     String inviteUserName = params[0] == null?"":params[0].toString().trim();
     //被邀请者
     String otherUserName = params[0] == null ?"":params[0].toString();
      IConnection tempconn = onlineList.get(otherUserName);
      if(tempconn instanceof IServiceCapableConnection){
          IServiceCapableConnection sc = (IServiceCapableConnection) tempconn;    
          sc.invoke("discuzVideo", new Object[]{inviteUserName});
      }
    }   
}

猜你喜欢

转载自antjava2010.iteye.com/blog/1295745