Flex4 实现视频通话完整实例 一 客户端
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
currentState="loginState"
pageTitle="欢迎来到登录页面"
creationComplete="application1_creationCompleteHandler(event)">
<s:layout>
<s:VerticalLayout horizontalAlign="center" verticalAlign="middle"/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.collections.ArrayList;
import mx.controls.Alert;
import mx.events.CloseEvent;
import mx.events.FlexEvent;
/**
* 声明共享对象
*/
private var listSO:SharedObject;
/**
* 声明用户数组
*/
private var userArr:Array;
/**
* 本地登录的用户名
*/
private var localUserName:String;
/**
* 声明网络连接对象并实例化
*/
private var conn:NetConnection=new NetConnection();
/**
* 声明用户列表的数据源
*/
[Bindable]
private var userList:ArrayCollection;
/**
* 正在进行视频的用户的集合
*/
private var videoUsers:Array;
/**
* 声明自己的网络流
*/
private var selfNS:NetStream;
/**
* 声明对方的网络流
*/
private var otherNS:NetStream;
/**
* 声明自己的视频对象
*/
private var selfVideo:Video;
/**
* 声明对方的视频对象
*/
private var otherOneVideo:Video;
/**
* 访问的网址
*/
private var rtmpUrl:String="rtmp://localhost/VideoMeeting_Server";
protected function btnLogin_clickHandler(event:MouseEvent):void
{
localUserName=this.txtLoginName.text;
var pwd:String=this.txtPwd.text;
if(localUserName==""){
Alert.show("登录名不能为空!");
return;
}else{
conn.client=this;
//Alert.show("this:"+this);
conn.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);
conn.connect(rtmpUrl,this.localUserName);
}
}
public function statusHandler(e:NetStatusEvent):void{
Alert.show(e.info.code);
if(e.info.code=="NetConnection.Connect.Success"){
this.currentState="chatState";
this.localUserName=this.txtLoginName.text;
//修改网页标题
if(ExternalInterface.available){
ExternalInterface.call("changeTitle",this.localUserName);
}
//设置用户列表对象
setUserListSo();
//刷新用户列表对象
this.refreshUserList(this.localUserName);
this.txtYouSay.setFocus();
}
}
public function result_getOnLoadUser(msg:String):void{
this.chatMsg.text+="【"+msg+"】"+"加入聊天室!\n";
}
/**
* 创建用户列表共享对象
*/
public function setUserListSo():void{
this.listSO=SharedObject.getRemote("listSO",conn.uri,false);
this.listSO.connect(conn);
this.listSO.addEventListener(SyncEvent.SYNC,syncHandler);
}
public function syncHandler(evt:SyncEvent):void{
showUserList();//重新加载用户列表
}
/**
* 显示用户列表对象
*/
public function showUserList():void{
this.userList=new ArrayCollection([{label:"All"}]);
this.userArr=new Array();
for(var tmp:String in this.listSO.data){
this.userArr.push(this.listSO.data[tmp]);
}
for(var i:int=0;i<this.userArr.length;i++){
if(this.userArr[i]==this.localUserName){
this.userList.addItem({label:"当前用户:"+this.userArr[i]});
continue;
}
this.userList.addItem({label:this.userArr[i]});
}
//将数据绑定到组合框和DataGrid上
this.combo_userList.selectedIndex=0;
this.combo_userList.dataProvider=this.userList;
this.dg_userList.dataProvider=this.userList;
}
/**
* 刷新用户列表
*/
private function refreshUserList(message:String):void{
//Alert.show("message:"+message);
conn.call("getOnLoadUser",null,message);
}
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
this.txtLoginName.setFocus();
}
/**
* 显示指定消息内容
*/
public function showMessage(message:String):void{
this.chatMsg.text+=message+"\n";
}
protected function txtSend_clickHandler(event:MouseEvent):void
{
var youSay:String=this.txtYouSay.text;
var sayToName:String=this.combo_userList.selectedItem.label;
if(sayToName=="当前用户:"+this.localUserName){
Alert.show("请不要自言自语!");
return;
}
conn.call("chat",null,sayToName,youSay);
Alert.show("发送成功!");
this.txtYouSay.text="";
this.txtYouSay.setFocus();
}
/**
* 开始视频邀请
*/
protected function txtVideo_clickHandler(event:MouseEvent):void
{
var otherName:String=this.combo_userList.selectedItem.label;
conn.call("videoInvite",null,otherName);
Alert.show("视频邀请已发送出去!");
this.txtYouSay.setFocus();
}
/**
* 视频被邀请方调用的方法
*/
public function showInviteMessage(message:String):void{
this.videoUsers=message.split(";");
Alert.show(this.videoUsers[0]+":"+this.videoUsers[1]);
Alert.show(this.videoUsers[0]+"正在邀请和你进行视频,是否同意?","提示信息",
Alert.YES|Alert.NO,this,alertClientHandler);
}
private function alertClientHandler(evt:CloseEvent):void{
if(evt.detail==Alert.YES){
this.publishVideo();
this.getVideo();
conn.call("agreeVideoInvite",null,this.videoUsers[0],this.videoUsers[1]);
}else{
conn.call("denyVideoInvite",null,this.videoUsers[0],this.videoUsers[1]);
}
}
/**
* 显示自己的视频
*/
private function publishVideo():void{
this.selfNS=new NetStream(conn);
//this.selfNS.bufferTime=15;
var cam:Camera=Camera.getCamera();
if(cam==null){
Alert.show("对不起,没有摄像头设备!");
return;
}else{
cam.setLoopback(true);
cam.setMotionLevel(50,100);
cam.setMode(320,240,15,true);
this.selfNS.attachCamera(cam);
}
var microphone:Microphone=Microphone.getMicrophone();
if(microphone==null){
Alert.show("没有可用的麦克风!");
return;
}else{
microphone.setUseEchoSuppression(true);
this.selfNS.attachAudio(microphone);
}
this.selfNS.publish("somes"+this.txtLoginName.text,"live");
this.selfVideo=new Video();
this.selfVideo.width=this.self_VD.width;
this.selfVideo.height=this.self_VD.height;
this.selfVideo.attachCamera(cam);
this.self_VD.addChild(this.selfVideo);
}
/**
* 对方视频显示
*/
private function otherVideoShow():void{
this.otherNS=new NetStream(conn);
//this.otherNS.bufferTime=15;
this.otherOneVideo=new Video();
this.otherOneVideo.width=this.other_OneVD.width;
this.otherOneVideo.height=this.other_OneVD.height;
this.otherOneVideo.attachNetStream(this.otherNS);
this.other_OneVD.addChild(this.otherOneVideo);
}
/**
* 被邀请方获得对方视频
*/
private function getVideo():void{
this.otherVideoShow();
this.otherNS.play("somes"+this.videoUsers[0]);
}
/**
* 邀请方获得对方视频
*/
private function getOtherVideo(other:String):void{
this.otherVideoShow();
this.otherNS.play("somes"+other);
}
/**
* 邀请方的提示信息(对方拒绝视频后自己调用的方法)
*/
public function msgTip(msg:String):void{
Alert.show(msg);
}
/**
* 邀请方收到被邀请方同意后调用的方法
*/
public function showVideo(other:String):void{
this.publishVideo();
this.getOtherVideo(other);
}
public function disConnectMessage(message:String):void{
this.chatMsg.text+=message+"退出聊天室!"+"\n";
}
]]>
</fx:Script>
<s:states>
<s:State name="chatState"/>
<s:State name="loginState"/>
</s:states>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<mx:Form includeIn="loginState" width="315" height="150" textAlign="center">
<mx:FormHeading label="欢迎来到登录窗口" width="269"/>
<mx:FormItem label="请输入登录名:" width="273">
<s:TextInput width="168" id="txtLoginName"/>
</mx:FormItem>
<mx:FormItem label="请输入密 码:">
<s:TextInput width="167" id="txtPwd"/>
</mx:FormItem>
<mx:FormItem width="267">
<s:Button label="登录" id="btnLogin" click="btnLogin_clickHandler(event)"/>
</mx:FormItem>
</mx:Form>
<s:HGroup width="599" height="479" verticalAlign="middle" includeIn="chatState">
<s:Panel width="380" height="480" title="聊天信息" y="-2">
<s:HGroup x="0" y="0" width="378" height="447">
<s:VGroup width="229" height="100%">
<s:TextInput width="240" height="321" editable="false" id="chatMsg"/>
<s:HGroup width="229" height="186">
<s:TextInput width="145" height="116" id="txtYouSay"/>
<s:VGroup width="77" height="107" paddingTop="30" gap="16">
<s:Button label="发送" id="txtSend" click="txtSend_clickHandler(event)"/>
<s:Button label="视频" id="txtVideo" click="txtVideo_clickHandler(event)"/>
</s:VGroup>
</s:HGroup>
</s:VGroup>
<s:VGroup width="142" height="100%" paddingLeft="10" paddingTop="10">
<s:Label text="用户列表"/>
<s:DropDownList id="combo_userList" width="119"></s:DropDownList>
<s:Label text="用户列表"/>
<mx:DataGrid width="123" height="366" id="dg_userList">
<mx:columns>
<mx:DataGridColumn headerText="用户名" dataField="label"/>
</mx:columns>
</mx:DataGrid>
</s:VGroup>
</s:HGroup>
</s:Panel>
<s:VGroup width="217" height="478" y="-1" paddingLeft="10">
<s:Label text="我的视频" paddingLeft="10" paddingTop="10"/>
<s:VideoDisplay width="198" height="222" id="self_VD"/>
<s:Label text="对方视频"/>
<s:VideoDisplay width="196" height="212" id="other_OneVD"/>
</s:VGroup>
</s:HGroup>
</s:Application>
!!!!服务器端配置见 Flex4 实现视频通话完整实例 二 服务器端