创建基于Android设备及FMS音视频应用

移动开发
我们知道,Flash与Flash Media Server( FMS )可以创建丰富的音视频交互应用。从Flash Player10开始支持P2P,并且可以方便的将Flash程序发布为基于Android系统的移动设备的应用。 下面我们将一个Flash音视频聊天程序,移植为基于Flash Media Server4的,支持P2P的音视频Android移动应用。

通过接下来的学习,我们将了解以下3个关键的知识点。

  1. 客户端如何创建P2P连接
  2. 运用Flash Media Server4 来实现P2P连接
  3. 运用最新的Flash CS5 AIR2.5插件来发布Android的移动设备应用程序

在原有的Flash程序中,客户端通过RTMP协议与Flash Media Server创建连接,在Flash Media Server端通过SharedObject来管理在线用户的列表,客户端之间的通信采用Netconnection的Call的方法来发送视频邀请相关的信息。

要求

你需要先安装下列产品:

Flash Professional CS5

Flash Media Server 4

Flash Professional CS5上的AIR 2.5 for Android开发插件

示例文件:

预备知识

  • ActionScript 3.0 中级编程水平
  • 会运用Flash Pro及Flash Media Server开发项目

客户端创建与FLASH MEDIA SERVER的RTMFP连接

要创建P2P的应用,首先我们需要与服务器端创建RTMFP(Real Time Media Flow Protocol)协议的连接。我们可以将原有代码中的RTMP协议直接修改为RTMFP,但是RTMFP协议是基于UDP协议的,并不是所有的网络环境都支持UDP协议。所以为了我们应用的可用性,我们依然保留RTMP连接方式。 在负责通信的Communicator类中,修改 connect函数为:

  1. public function connect(rtmp:Boolean=false) : void 
  2.     //为函数添加布尔参数,通过参数来切换连接FMS服务器的方式 
  3.     //默认情况下我们采用rtmfp的连接 
  4.     var url=(rtmp?"rtmp:" : "rtmfp:") + "//"+serverURL+"/vchat" 
  5.     nc.connect(url,userName); 
  6.   
  7.     // 判断当采用rtmfp协议连接时候,增添一个连接时间计数器 
  8.     // 通过这个计算器设置的连接超时来判断rtmfp连接是否成功 
  9.     if (!rtmp) 
  10.     { 
  11.         rtmfpTimer = new Timer(connectTimeout, 1); 
  12.         rtmfpTimer.addEventListener(TimerEvent.TIMER_COMPLETE,rtmfpTimeoutHandler) 
  13.         rtmfpTimer.start(); 
  14.     } 

添加事件侦听函数,这个函数在当RTMFP连接失败的时候,关闭原连接,创建RTMP连接。

  1. private function rtmfpTimeoutHandler(e:TimerEvent):void 
  2.     isRTMFP=false
  3.     rtmfpTimer.stop(); 
  4.     rtmfpTimer = null
  5.     nc.close(); 
  6.     connect(true); 

在原有Netconnection连接状态侦听函数 ncStatusHandler中添加代码:

  1. if (rtmfpTimer) 
  2.     rtmfpTimer.stop(); 
  3.     rtmfpTimer = null

这样当Netconnection连接有响应的时候,关闭计数器。

到此,我们已经将客户端的连接修改为兼容P2P的RTMFP连接方式。现在我们来看看Flash Media Server端的代码。

FLASH MEDIA SERVER 4中管理并分配P2P连接

当客户端与Flash Media Server 4成功创建RTMFP连接的时候,服务器会为每个客户端连接创建一个256位的唯一ID,通过这个ID,客户端之间就可以进行P2P连接。

要创建P2P方式的音视频流,我们就需要通过Flash Media Server 4将客户端各自对应的此唯一ID发送给通信对方。

在客户端与FMS连接成功时,FMS将此连接的唯一ID保存在名为farID的属性值中。打开示例中fms > vchat目录中的Flash Media Server端脚本main.asc,在其中onConnect函数里,我们将此唯一ID在保存在名为peerID的参数中 。

  1. application.onConnect = function(client, userName) 
  2.     …… 
  3.     clientclient.peerID=client.farID; 
  4.     …… 

在视频邀请的通信函数videoChat中添加如下代码:

  1. case "accept": 
  2.     var myPeerID="" 
  3.     var otherPeerID="" 
  4.     if(userList[myname].protocol=="rtmfp" && userList[othername].protocol=="rtmfp") 
  5.     { 
  6.         myPeerID=userList[myname].peerID 
  7.         otherPeerID=userList[othername].peerID 
  8.     } 
  9.     userList[othername].call("vc", null, stat, myname,myPeerID); 
  10.     userList[myname].call("vc", null, stat,othername,otherPeerID); 

上述代码表示,在一方接收另一方视频聊天邀请时,我们判断双方与FMS的连接 协议是否为RTMFP,如果是,将各自的对等ID传送给对方。

在修改完毕服务端脚本之后,不要忘记将vchat目录复制到Flash Media Server的applications子目录中。

客户端创建兼容P2P的音视频交互

现在我们回到客户端代码Communicator.as 编辑,在初始化发布音视频流函数initOutStream中,添加传递参数 peerID:String,用来接收FMS服务器发送的对方的peerID。

  1. initOutStream(user:String,peerID:String) 

然后添加代码:

  1. if(isRTMFP && peerID!="") 
  2.     outStreamDirect = new NetStream(nc, NetStream.DIRECT_CONNECTIONS); 
  3.     var c:Object = new Object(); 
  4.     c.onPeerConnect = function(peer:NetStream):Boolean 
  5.     { 
  6.         if (outStream) 
  7.         { 
  8.             outStream.close(); 
  9.             outStream = null
  10.         } 
  11.     outStreamDirect.attachAudio(Microphone.getMicrophone()); 
  12.     outStreamDirect.attachCamera(cam); 
  13.     return true; 
  14. outStreamDirect.client = c; 
  15. outStreamDirect.publish(mySteamName+"_direct"); 

上述代码中,我们首先判断自己与FMS服务器的连接以及对方是否为RTMFP协议,如果是,我们创建一个通过P2P直连的发布流 outStreamDirect,与原来的发布流区别,我们为这个新的发布流创建了新的名称"_direct"。

请注意这里我们同时保留了原来的基于FMS的发布流,这是因为,即使音视频聊天的双方都跟FMS服务器创建了RTMFP协议,由于不同网络环境,例如防火墙,路由器的限制等,都有可能让双方最终不能创建点对点的连接。所以,我们通过onPeerConnect这个方法来判断双方是否P2P连接成功。当 P2P连接成功时,关闭原有的基于RTMP协议的发布流outStream。

通过上述代码的修改,能保证我们的应用真正的适应各种网络环境的用户。

同样的方法,我们对于播放音视频流的函数initInStream,也采取同时播放原有流和P2P流的方式。

  1. if(isRTMFP && peerID!="") 
  2.     inStreamDirect=new NetStream(nc,peerID) 
  3.     inStreamDirect.addEventListener(NetStatusEvent.NET_STATUS, inStream_NetStatusHandler); 
  4.     inStreamDirect.play(user+"_direct"); 

请注意代码中新建的播放流inStreamDirect,指定了需要播放的对方的peerID,这个唯一ID就来自与刚才我们修改的FMS服务器端程序。

因为我们同时播放了2个流,所以我们为新建的P2P直连流添加如下的事件侦听函数 inStream_NetStatusHandler ,这样在P2P流成功播放的时候,将原有的RTMP协议流关闭,并且将当前显示的视频切换到这个流。

  1. private function inStream_NetStatusHandler(event:NetStatusEvent) : void 
  2.     if (event.info.code == "NetStream.Play.Start") 
  3.     { 
  4.         if(inStream) 
  5.         { 
  6.             inStream.close(); 
  7.             inStream = null
  8.         } 
  9.         VideoChat.instance._chatScreen.showUserVideo(inStreamDirect) 
  10.     } 

最后,为保证我们创建的这个Android应用在实际的移动设备运行过程中,用户点击返回键或程序关闭时断开与FMS服务器的连接,在主程序类VideoChat.as中添加代码

  1. if(Capabilities.cpuArchitecture=="ARM") 
  2.     NativeApplication.nativeApplication.addEventListener(Event.ACTIVATE, 
  3.     handleActivate, false, 0, true); 
  4.     NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, 
  5.     handleDeactivate, false, 0, true); 
  6.     NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, 
  7.     handleKeys, false, 0, true); 
  8. private function handleActivate(event:Event):void 
  9.     NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE; 
  10. private function handleDeactivate(event:Event):void 
  11.     communicator.onExit() 
  12.     NativeApplication.nativeApplication.exit(); 
  13. private function handleKeys(event:KeyboardEvent):void 
  14.     if(event.keyCode == Keyboard.BACK) 
  15.     { 
  16.         communicator.onExit() 
  17.         NativeApplication.nativeApplication.exit(); 
  18.     } 

同时在 Communicator类中添加onExit函数

  1. public function onExit():void 
  2.     nc.close() 
  3.     nc=null

这样,当用户点击返回键或者退出程序的时候,自动关闭与FMS的连接。

到此为止,我们已经将客户端与FMS4配合支持P2P音视频流的相关代码修改完毕。接下来我们将这个程序发布为基于Android移动设备的应用。

运用最新的FLASH PRO AIR2.5插件发布ANDROID移动端应用

由于原始代码是基于Flash Professional的,所以要方便的发布一个基于Android的移动设备应用,我们可以从Adobe实验室中下载最新的AIR 2.5 for Flash Pro CS5 插件,下载地址:http://labs.adobe.com/technologies/flashpro_extensionforair/

在安装好这个插件之后,打开Flash发布设置,选择AIR Android,点击打开设置选项。

在通用设置(General)面板中,我们可以设置应用是否全屏,发布名称等。

在部署(Deployment)面板中,创建你的应用程序证书,在发布之后选项中,如果你的电脑连接了Android的移动设备,可以勾选发布后自动安装此应用到设备上,并且可以自动运行。

在访问权限(Permissions)面板中设置此应用的访问权限,因为我们做的这个应用需要连接网络及使用摄像头,所以需要选择Internet和Camera选项。

发布我们最终修改好的程序,现在你可以通过Android移动设备进行音视频通讯了。:

下图为程序在Samsung Galaxy Tab上运行得效果。

关于作者

黄竣 (peter huang)

Adobe Platform Evangelist 国内最早一批Flash开发者之一,Rich Interactive Entertainment(RIE®)创始人。从事近10年的互联网互动应用及Flash游戏的开发,对Flash游戏、视频及移动应用开发具有丰富的经验。目前是Adobe平台技术传教士,致力于Flash技术在游戏,视频方面的应用及推广。

责任编辑:佚名 来源: Adobe
相关推荐

2024-10-15 13:30:03

2022-06-20 05:59:35

5G技术音视频技术安卓系统

2024-02-28 08:22:07

2015-12-17 17:19:09

通信研究院

2023-03-03 15:40:43

抖音视频编码器

2022-08-29 10:39:32

FFmpeg多媒体框架开源

2023-04-10 07:49:43

云渲染平台RTC

2018-04-23 10:24:05

2022-09-21 11:48:40

端到端音视频测试用户体验

2022-06-28 17:51:23

声网物联网云平台

2015-12-01 13:51:52

Webrtc

2021-11-04 16:05:08

鸿蒙HarmonyOS应用

2022-08-20 07:56:48

FFmpeg数字音频流浏览器

2022-01-24 20:40:26

HarmonyOS音视频鸿蒙

2017-12-22 22:13:22

语音视频SDK延迟

2022-07-01 10:59:28

英特尔

2017-09-13 16:12:12

2017-09-19 11:00:09

音视频技术
点赞
收藏

51CTO技术栈公众号