为了工作需要学习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});
}
}
}