资料记录:flex+red5+blazeds实现视频通话demo
刚实习几个月,最近要做一个视频聊天的功能,组长让我用flex做。虽然是很老的技术,资料也少,但还是努力去做了。真正做了以后发现反而没有想象中的难,主要就baidu、整理、分析、实验。
demo环境:flex4.6 64位,tomcat6,myeclipse 10 64位,chrome。
以下是参考资料部分:
http://jingyan.baidu.com/article/495ba841f56c2738b30ede9f.html flex插件安装
http://wenku.baidu.com/view/46367d126c175f0e7cd137ba.html flex整合myeclipse
http://blog.csdn.net/dianfusoft/article/details/8062930 flex嵌入jsp
注意部分:
1:flex安装版本与myeclipse对齐,32位对32位,64位对64位,否则重装myeclipse(作死实验了好几遍)。
2:需要将red5和blazeds的三个war包拷贝到tomcat服务器webapp下。
3:三个链接里的东西整合后配置文件可能重名,如web.xml,需挑出各自的部分组合起来。
4:flex取值可以从后台用远程对象+事件监听取,也可以用import导入ExternalInterface后用ExternalInterface.call("test")直接调外部的js方法。
5:flex嵌入jsp只能用flex3,所以语法必须用flex3的语法,即mx标签,嵌入无需安装flex(不过编写的时候没有语法提示)。
连接red5地址自主修改,rtmp://10.250.196.113/oflaDemo
初始化时调用initValue,根据远程对象从后台取值(因为是demo所以写死了),remoting-config.xml中配置
取到值一个作为本地流名字,一个作为远程流名字,另一端就是反一下,其余的一样
上传下载流是根据流的名字的,red5的流保存在stream文件夹里
因为执行快慢的关系,我把初始化连接放在了myFlex_resultHandler(event)里,保证取到值后再初始化
连接初始化initConnection里添加监听,监听到连接成功后执行后续代码
后续代码主要看注释吧,毕竟还算详细
最重要的点是如果想关闭摄像头、麦克风的话必须把所有attach置为空
如attachCamera(null),camera = null之类,关不掉说明有遗漏
我这里因为是嵌入到jsp(jsp页面功能只有播放),直接关闭页面就可以了
csdn上传文件限制60m,而且一直提示资源名字不对,需要的资源自己搜一下
以下是代码:
doctor.mxml
1 <?xml version="1.0" encoding="utf-8"?> 2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 3 xmlns:fx="http://ns.adobe.com/mxml/2006" 4 layout="absolute" 5 backgroundColor="white" 6 initialize="initValue();"> 7 <mx:RemoteObject id="myFlex" destination="mytest"> 8 <mx:method name="getMa" result="myFlex_resultHandler(event)"/> 9 </mx:RemoteObject> 10 <mx:Script> 11 <![CDATA[ 12 import mx.controls.Alert; 13 import mx.rpc.events.ResultEvent; 14 import flash.external.ExternalInterface; 15 //定义一个连接 16 public var netConnection:NetConnection; 17 //定义远程视频 18 public var remoteVideo:Video; 19 //定义本地视频流 20 public var outStream:NetStream = null; 21 public var netStreamName:String; 22 //定义远程视频流 23 public var remoteStream:NetStream = null; 24 public var remoteStreamName:String; 25 //定义一个摄像头 26 public var camera:Camera; 27 //定义一个麦克风 28 public var microphone:Microphone; 29 30 //rtmp服务器url 31 private var rtmpUrl:String = "rtmp://10.250.196.113/oflaDemo"; 32 //定义帧数 33 public var keyFrameInterval:int = 48; 34 //播放速率 35 public var keyFps:int = 8; 36 public var keyRate:int = 10; 37 public var keyQuality:int = 85; 38 public var bufferTime:int = 500; 39 public var encodeType:int = 2; 40 public var gain:int = 60; 41 42 protected function myFlex_resultHandler(event:ResultEvent):void{ 43 var ma:Object = event.result as Object; 44 netStreamName = ma.doctor as String; 45 remoteStreamName = ma.patient as String; 46 initConnection(); 47 } 48 49 public function initValue():void{ 50 //调用外部js方法 51 //Alert.show(ExternalInterface.call("test").b as String); 52 myFlex.getMa(); 53 } 54 55 public function initConnection():void{ 56 //初始化连接 57 netConnection = new NetConnection(); 58 //为连接添加状态监听器 59 netConnection.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler); 60 //为连接添加安全错误监听器 61 netConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler); 62 //连接到服务器 63 netConnection.connect(rtmpUrl); 64 } 65 66 private function netStatusHandler(event:NetStatusEvent):void{ 67 if (event.info.code == "NetConnection.Connect.Success"){ 68 //本地输出流 69 outStream = new NetStream(netConnection); 70 remoteStream = new NetStream(netConnection); 71 //得到当前摄像头 72 camera = Camera.getCamera(); 73 //当前摄像头可用 74 if(camera){ 75 //设置摄像头参数 76 camera.setMode(480,360,(Number(keyFps))); 77 camera.setQuality(480*360*keyFps/8,keyQuality); 78 camera.setKeyFrameInterval(keyFrameInterval); 79 //得到当前麦克风 80 microphone = Microphone.getMicrophone(); 81 //设置麦克风 82 //microphone.rate = keyRate; 83 //microphone.setUseEchoSuppression(true); 84 doIt(); 85 }else{ 86 Alert.show("没有找到摄像头"); 87 return; 88 } 89 }else{ 90 Alert.show("连接服务器失败!"); 91 } 92 } 93 94 private function securityErrorHandler(event:SecurityErrorEvent):void{ 95 Alert.show("securityErrorHandler: " + event); 96 } 97 98 public function doIt():void{ 99 //本地视频流获取摄像头和麦克风 100 outStream.attachCamera(camera); 101 outStream.attachAudio(microphone); 102 //本地视频流上传 103 outStream.publish(netStreamName,"record"); 104 105 //得到远程流 106 remoteStream.play(remoteStreamName); 107 //根据远程流获取视频 108 remoteVideo = new Video(); 109 remoteVideo.attachNetStream(remoteStream); 110 remoteVideo.width = 480; 111 remoteVideo.height = 360; 112 113 //将视频放到控件上 114 itsVideo.addChild(remoteVideo); 115 //本地视频播放 116 myVideo.attachCamera(camera); 117 } 118 119 ]]> 120 </mx:Script> 121 <mx:TitleWindow id="p" headerHeight="8" x="0" y="0" width="500" height="380" layout="absolute"> 122 <mx:VideoDisplay id="itsVideo" width="480" height="360"/> 123 <mx:VideoDisplay x="360" y="270" id="myVideo" width="120" height="90"/> 124 </mx:TitleWindow> 125 </mx:Application>
patient.mxml
1 <?xml version="1.0" encoding="utf-8"?> 2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 3 xmlns:fx="http://ns.adobe.com/mxml/2006" 4 layout="absolute" 5 backgroundColor="white" 6 initialize="initValue();"> 7 <mx:RemoteObject id="myFlex" destination="mytest"> 8 <mx:method name="getMa" result="myFlex_resultHandler(event)"/> 9 </mx:RemoteObject> 10 <mx:Script> 11 <![CDATA[ 12 import mx.controls.Alert; 13 import mx.rpc.events.ResultEvent; 14 //定义一个连接 15 public var netConnection:NetConnection; 16 //定义远程视频 17 public var remoteVideo:Video; 18 //定义本地视频流 19 public var outStream:NetStream = null; 20 public var netStreamName:String; 21 //定义远程视频流 22 public var remoteStream:NetStream = null; 23 public var remoteStreamName:String; 24 //定义一个摄像头 25 public var camera:Camera; 26 //定义一个麦克风 27 public var microphone:Microphone; 28 29 //rtmp服务器url 30 private var rtmpUrl:String = "rtmp://10.250.196.113/oflaDemo"; 31 //定义帧数 32 public var keyFrameInterval:int = 48; 33 //播放速率 34 public var keyFps:int = 8; 35 public var keyRate:int = 10; 36 public var keyQuality:int = 85; 37 public var bufferTime:int = 500; 38 public var encodeType:int = 2; 39 public var gain:int = 60; 40 41 protected function myFlex_resultHandler(event:ResultEvent):void{ 42 var ma:Object = event.result as Object; 43 netStreamName = ma.patient as String; 44 remoteStreamName = ma.doctor as String; 45 initConnection(); 46 } 47 48 public function initValue():void{ 49 myFlex.getMa(); 50 } 51 52 public function initConnection():void{ 53 //初始化连接 54 netConnection = new NetConnection(); 55 //为连接添加状态监听器 56 netConnection.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler); 57 //为连接添加安全错误监听器 58 netConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler); 59 //连接到服务器 60 netConnection.connect(rtmpUrl); 61 } 62 63 private function netStatusHandler(event:NetStatusEvent):void{ 64 if (event.info.code == "NetConnection.Connect.Success"){ 65 //本地输出流 66 outStream = new NetStream(netConnection); 67 remoteStream = new NetStream(netConnection); 68 //得到当前摄像头 69 camera = Camera.getCamera(); 70 //当前摄像头可用 71 if(camera){ 72 //设置摄像头参数 73 camera.setMode(480,360,(Number(keyFps))); 74 camera.setQuality(480*360*keyFps/8,keyQuality); 75 camera.setKeyFrameInterval(keyFrameInterval); 76 //得到当前麦克风 77 microphone = Microphone.getMicrophone(); 78 //设置麦克风 79 //microphone.rate = keyRate; 80 //microphone.setUseEchoSuppression(true); 81 doIt(); 82 }else{ 83 Alert.show("没有找到摄像头"); 84 return; 85 } 86 }else{ 87 Alert.show("连接服务器失败!"); 88 } 89 } 90 91 private function securityErrorHandler(event:SecurityErrorEvent):void{ 92 Alert.show("securityErrorHandler: " + event); 93 } 94 95 public function doIt():void{ 96 //本地视频流获取摄像头和麦克风 97 outStream.attachCamera(camera); 98 outStream.attachAudio(microphone); 99 //本地视频流上传 100 outStream.publish(netStreamName,"record"); 101 102 //得到远程流 103 remoteStream.play(remoteStreamName); 104 //根据远程流获取视频 105 remoteVideo = new Video(); 106 remoteVideo.attachNetStream(remoteStream); 107 remoteVideo.width = 480; 108 remoteVideo.height = 360; 109 110 //将视频放到控件上 111 itsVideo.addChild(remoteVideo); 112 //本地视频播放 113 myVideo.attachCamera(camera); 114 } 115 116 ]]> 117 </mx:Script> 118 <mx:TitleWindow id="p" headerHeight="8" x="0" y="0" width="500" height="380" layout="absolute"> 119 <mx:VideoDisplay id="itsVideo" width="480" height="360"/> 120 <mx:VideoDisplay x="360" y="270" id="myVideo" width="120" height="90"/> 121 </mx:TitleWindow> 122 </mx:Application>
remoting-config.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <service id="remoting-service" 3 class="flex.messaging.services.RemotingService"> 4 5 <adapters> 6 <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/> 7 </adapters> 8 9 <default-channels> 10 <channel ref="my-amf"/> 11 </default-channels> 12 13 <destination id="mytest"> 14 <properties> 15 <source>test.Accptech</source> 16 </properties> 17 </destination> 18 19 </service>
doctor.jsp
1 <%@ page language="java"contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@taglib uri="FlexTagLib"prefix="mm"%> 4 <!DOCTYPE html PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 5 <html> 6 <head> 7 <meta http-equiv="Content-Type"content="text/html; charset=UTF-8"> 8 <title>心理咨询</title> 9 <style type="text/css"> 10 </style> 11 <script type="text/javascript"> 12 function test(){ 13 return {a:'yes',b:'no'}; 14 } 15 </script> 16 </head> 17 <body> 18 <div id="chatPanel"> 19 <mm:mxml source="../mxml/doctor.mxml" width="500" height="380"> 20 </mm:mxml> 21 </div> 22 </body> 23 </html>
patient.jsp
1 <%@ page language="java"contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@taglib uri="FlexTagLib"prefix="mm"%> 4 <!DOCTYPE html PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 5 <html> 6 <head> 7 <meta http-equiv="Content-Type"content="text/html; charset=UTF-8"> 8 <title>心理咨询</title> 9 <style type="text/css"> 10 </style> 11 <script type="text/javascript"> 12 13 </script> 14 </head> 15 <body> 16 <div id="chatPanel"> 17 <mm:mxml source="../mxml/patient.mxml" width="500" height="380"> 18 </mm:mxml> 19 </div> 20 </body> 21 </html>
test.jsp
1 <%@ page language="java"contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 4 <html> 5 <head> 6 <meta http-equiv="Content-Type"content="text/html; charset=UTF-8"> 7 <title>测试</title> 8 <style type="text/css"> 9 </style> 10 <script type="text/javascript"> 11 function bo(){ 12 window.open('doctor.jsp','心理咨询','width=530,height=435,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,status=no'); 13 } 14 function po(){ 15 window.open('patient.jsp','心理咨询','width=530,height=435,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,status=no'); 16 } 17 </script> 18 </head> 19 <body> 20 <div style="width:600px;height:500px"> 21 <input type="button" value="视频聊天-医生" onclick="bo()"/> 22 <input type="button" value="视频聊天-病人" onclick="po()"/> 23 </div> 24 </body> 25 </html>
代码部分就到此为止,测试步骤:
打开两个http://localhost:8088/flexweb/jsp/test.jsp,一个作为医生端,一个作为病人端,注意端口
偷懒只写了一个jsp,里面有两个按钮
一个页面点左按钮,另一个页面点右按钮,再允许使用摄像头就可以了
因为流名称写死了每次用需要将red5里stream文件夹下流文件清空
谷歌浏览器样子还不错,ie有点丑
现在是两端都是自己