Compartilhando Câmera e Chat com o Flash Media Server
Neste exemplo vamos criar um aplicativo chamado confDemo do Flash Media Server. Este serviço é igual ao publicado sobre Red5, porém reescrito para Flash Media Server..
O Flash Media Server é muito mais fácil de criar serviços do que o Red5, pois apenas precisamos saber programar em AS2.
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:
- application.onAppStart
É invocado quando o primeiro usuário se conectar na aplicação. Ou seja, quando a aplicação for iniciada; - application.onConnect
Invocado quando um novo usuário se conectar; - application.onDisconnect
Invocado quando o usuário sair da aplicação. Neste processo deve se excluir o usuário da lista de conectados; - enviarNovosUsuarios
usado para notificar todos os usuários quais os usuários atualmente conectado.
/** * 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 Red5
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 pleo Red5
*/
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 Red5
*/
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 Red5" 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 e confDemo.zip.
Você pode seguir todas as respostas a esta entrada através do RSS 2.0 feed. Você pode deixar um comentário, ou colocar um link em seu site.


Eduardo, no FMS eu tenho que clicar em New Instance para o confDemo??? Qual a versão do FMS você usa. Eu estou achando mais fácil de trabalhar com o FMS do que com o RED5. Abraço!
@Renan Não é necessário criar a instância. Apenas deposite o conteúdo do Zip na pasta application do FMS http://code.mxml.com.br/245/confDemo.zip
Os testes eu fiz na versão 3.5 do FMS e realmente o FMS é melhor de trabalhar e mais estável.
Olá! Primeiro parabéns pelo blog! Muito útil!
Como faço pra jogar isso tudo pro servidor? Preciso do FMS no servidor WEB?
Sou meio leigo ainda e não consigo conectar localmente… a tela de login no “Flash Media Administration Console” aparece toda hora. Tem alguma dica pra isso?
Obrigado!
@Eduardo Sim, você precisa de um FMS no servidor.
Parabéns pelo post. É excelente.
Sabe me dizer se da para reescrever para windows media server também? E se é possível em um determinado momento gravar este vídeo transmitido on-line, por um terceiro?
Lucien Jospin
Windows Media não