Se esta querendo aprender ou iniciar novos projetos em Flex, clique aqui

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:

  • 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 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.

Gostou? Não esqueça de curtir!

Ou compartilhe o link com seus amigos

7 comentários

Deixe uma resposta

  1. Fala Eduardo. Cara, preciso te perguntar uma coisa.
    Estou tentando desenvolver um serviço de atendimento online por aquí usando o seu exemplo e esbarrei em uma dúvida. Quero fazer uma tela listando os usuários na fila, mas quero trocar mensagens entre somente dois usuários, ou seja, o solicitante entra e fica aguardando algum atendente para lhe atender.
    Não sei se fui claro, mas terei n atendentes para n solicitantes, porém as mensagens serão enviadas somente ponta-ponta.
    Como faço então para trocar mensagens entre 2 pontas da lista, não mais que duas? Obrigado.

     
  2. 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

     
  3. @Eduardo Sim, você precisa de um FMS no servidor.

     
  4. 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!

     
  5. @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.

     
  6. 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!