Neste exemplo vamos criar um aplicativo chamado confDemo do Flash Media Server. Este serviço é igual ao publicado sobre Wowza, porém reescrito para Flash Media Server..
Então vá até o FMS, na pasta FlashMediaServer3/applications e cria uma nova pasta com o nome de confDemo. dentro desta pasta crie um arquivo vazio com o nome de main.asc. Edite este arquivo (Não utilize o NOTEPAD do Windows recomendo o notepad++) e neste arquivos vamos criar os seguintes métodos:
/** * Se utilizar o Notepad++ altera a linguagem para Flash ActionScript para bser mais fácil de programar */
Vamos editar o main.asc que ganhará o seguinte conteúdo:
/** * Executado pelo primeiro usuário que conectar no aplicativo */ application.onAppStart = function() { application.nextId = 0; LocalClientData = new Array(); } /** * Executado quando o usuário conecta ao FMS * Responsável por receber a solicitação e autorizar * ou não seu acesso. */ application.onConnect = function(client, name) { if(name == null ) { var err = new Object(); err.message = "Sem permissão de acesso ao sistema!"; application.rejectConnection(client, err); } client.name = name; client.id = application.nextId++; application.acceptConnection(client); LocalClientData[client.id] = new Object(); LocalClientData[client.id].USER_ID = client.id LocalClientData[client.id].USER_NOME = name; enviarNovosUsuarios(); } /** * Executado quando o usuário se desconecta do sistema. * é utilizado apenas para notificar a saída */ application.onDisconnect = function(client) { application.nextId--; LocalClientData[client.id] = null; enviarNovosUsuarios(); } /** * Método responsável por enviar a todos os usrários * a lista de usuários conectados */ function enviarNovosUsuarios() { var lista = new Array(); for(var i=0; i < application.clients.length; i++) { lista[i] = new Object(); lista[i].USER_ID = application.clients[i].id lista[i].USER_NOME = LocalClientData[ application.clients[i].id ].USER_NOME; } for(var i=0; i < application.clients.length; i++) { application.clients[i].call("listaUsuarios",null, lista); } }
Sempre que alterar o main.asc terás que reiniciar o serviço do Flash Media Server ou recarregar a aplicação como na figura abaixo
Figura 01: Recarregando a aplicação
Agora que o serviço esta criado, vamos criar o aplicativo Flex que trabalhará com este serviço. Esta parte já deve ser mais fácil para a maioria dos leitores.
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" horizontalAlign="left" backgroundColor="#f6f6f6" backgroundGradientColors="[#f6f6f6, #bbbbbb]" creationComplete="init()" viewSourceURL="srcview/index.html"> <mx:Script> <![CDATA[ import mx.controls.Alert; // Conexão com o Servidor de Streaming private var netConnection:NetConnection; // NetStream responsável por apresentar o vídeo private var netStream_play:NetStream; // NetStream responsável por publicar o vídeo private var netStream_publish:NetStream; // Canal para o Chat private var sharedObject:SharedObject; // Componente para apresnetar o vídeo private var video:Video // Nome da publicação do vídeo private var streamingNome:String="publishVideo" /** * executa após carregar o aplicativo */ private function init():void { video=new Video(); video.height=uiCaixaDoVideo.height; video.width=uiCaixaDoVideo.width; } /** * Inicia a aplicação e faz a conexão */ private function conectar():void { if ( hostRTMP.text.length < 15 ) { Alert.show( "URL muito pequena!" ) return; } if ( nome.text.length < 3 ) { Alert.show( "Nome tem que ter mais de 3 caracteres!" ) return; } if ( netConnection != null ) netConnection=null; netConnection=new NetConnection(); netConnection.addEventListener( NetStatusEvent.NET_STATUS, netStatus ); netConnection.addEventListener( AsyncErrorEvent.ASYNC_ERROR, asyncError ) netConnection.connect( hostRTMP.text, nome.text ); netConnection.client=this; } /** * Método que recebe a lista de usuários enviado pelo Servidor de Streaming */ public function listaUsuarios( lista:Array ):void { datagridUsuarios.dataProvider=lista; } /** * Método que recebe o Status da conexão */ private function netStatus( e:NetStatusEvent ):void { switch ( e.info.code ) { case "NetConnection.Connect.Success": connectado() viewstack.selectedIndex=1; break; case "NetConnection.Connect.Closed": viewstack.selectedIndex=0; break; case "NetConnection.Connect.Rejected": viewstack.selectedIndex=0; break; case "NetConnection.Connect.Failed": viewstack.selectedIndex=0; break; default: viewstack.selectedIndex=0; } } /** * Chamado quando deu sucesso na conexão com o Servidor de Streaming */ private function connectado():void { sharedObject=SharedObject.getRemote( "chat", netConnection.uri, true ) sharedObject.addEventListener( SyncEvent.SYNC, OnSync ); sharedObject.addEventListener( AsyncErrorEvent.ASYNC_ERROR, asyncError ); sharedObject.connect( netConnection ); sharedObject.client=this; netStream_play=new NetStream( netConnection ) video.attachNetStream( netStream_play ); uiCaixaDoVideo.addChild( video ); netStream_play.play( streamingNome ); } /** * Método responsável por tratar os AsyncErrorEvent */ private function asyncError( e:AsyncErrorEvent ):void { trace( e ) } /** * Método responsável por tratar os SyncEvent */ private function OnSync( e:SyncEvent ):void { trace( e ) } /** * Trata o click do Botão Publicar WebCam * * Se marcado publica, ao desmarcar para a publicação. */ private function publicar():void { if ( btPublicar.selected ) { btPublicar.label="Parar publicação!" netStream_publish=new NetStream( netConnection ); netStream_publish.attachCamera( Camera.getCamera()); netStream_publish.attachAudio( Microphone.getMicrophone()); // nome que será publicado netStream_publish.publish( streamingNome ); } else { btPublicar.label="Publicar no servidor RTMP!" netStream_publish.close() netStream_publish=null } } /** * Envia o testo por Chat e limpa o campo. */ private function enviarMensagem():void { var msg:String="<p><b>" + nome.text + " diz:</b> " + mensagem.text + "</p>"; sharedObject.send( "recebemsg", msg ); mensagem.text=''; } /** * Recebe as mensagens postada no Chat */ public function recebemsg( msg:String ):void { areaMensagem.htmlText+=msg; areaMensagem.validateNow(); areaMensagem.verticalScrollPosition=areaMensagem.maxVerticalScrollPosition; } ]]> </mx:Script> <mx:ViewStack id="viewstack" width="100%" height="100%" creationPolicy="all"> <mx:VBox width="100%" height="100%" verticalAlign="middle" horizontalAlign="center"> <mx:Form> <mx:FormItem label="URL do servidor:" fontWeight="bold"> <mx:TextInput id="hostRTMP" text="rtmp://localhost/confDemo" width="200" fontWeight="normal"/> </mx:FormItem> <mx:FormItem label="Nome:" fontWeight="bold"> <mx:TextInput id="nome" width="200" fontWeight="normal"/> </mx:FormItem> <mx:FormItem> <mx:Button label="Conectar no Servidor de Streaming" click="conectar()" fontWeight="normal"/> </mx:FormItem> </mx:Form> </mx:VBox> <mx:VBox width="100%" height="100%"> <mx:HBox width="100%" height="100%"> <mx:VBox height="100%"> <mx:Canvas left="10" top="85" width="160" height="120" backgroundColor="#000000"> <mx:UIComponent width="100%" height="100%" id="uiCaixaDoVideo"/> </mx:Canvas> <mx:Button id="btPublicar" label="Publicar WebCam" click="publicar()" toggle="true"/> <mx:DataGrid id="datagridUsuarios" width="100%" height="100%"> <mx:columns> <mx:DataGridColumn headerText="Usuários" dataField="USER_NOME"/> </mx:columns> </mx:DataGrid> </mx:VBox> <mx:VBox height="100%" width="100%"> <mx:TextArea id="areaMensagem" width="100%" height="100%" borderStyle="none" alpha="0.63" editable="false"/> <mx:HBox width="100%"> <mx:TextInput id="mensagem" width="100%" enter="enviarMensagem()"/> <mx:Button label="Enviar" click="enviarMensagem()"/> </mx:HBox> </mx:VBox> </mx:HBox> </mx:VBox> </mx:ViewStack> </mx:Application>
Basicamente o funcionamento é o seguinte: Quando clicar o em conectar, é criado uma instancia do NetConnection e enviado junto o nome da pessoa que esta conectando. Assim que a classe que criamos receber esta conexão, ela replica a todas as todas as conexões enviando a lista de usuários conectados. Estalista é recebida pelo método listaUsuarios do Flex.
No Flash Media Server é verificado se foi enviado o nome e e aceita a conexão. Assim que a conexão for aceita, o Flex cria uma instancia do SharedObject e da play no canal publishVideo para quando alguém publicar um vídeo já estar instanciado.
A instancia do SharedObject é responsável pelo chat. para enviar uma mensagem, utiliza-se o método send, passando como parametro a o método que irá receber a resposta e a mensagem.
Quando clicamos em “publicar vídeo!”, uma instancia do NetStream é criada e publicamos no mesmo canal que foi dados play na lista acima.
Abaixo segue o exemplo finalizado, mais para testar terás que possuir um servidor de Server Media Server.
Código fonte aqui.
main.asc.