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

Fique por dentro de nossas novidades, ideias e atualizações