Trabajo con cámaras

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

Una cámara conectada al ordenador del usuario puede servir de origen de datos de vídeo, que a su vez se pueden mostrar y manipular con ActionScript. La clase Camera es el mecanismo integrado en ActionScript para trabajar con una cámara de ordenador o de dispositivo.

En dispositivos móviles, es posible utilizar también la clase CameraUI . La clase CameraUI inicia una aplicación de cámara independiente para que el usuario pueda capturar imágenes fijas o vídeo. Cuando el usuario termina, la aplicación puede acceder a la imagen o al vídeo a través de un objeto MediaPromise .

Aspectos básicos de la clase Camera

El objeto Camera permite conectar la cámara local del usuario y difundir vídeo localmente (de vuelta al usuario) o de forma remota a un servidor (como Flash Media Server).

Mediante la clase Camera, se pueden utilizar los siguientes tipos de información sobre la cámara del usuario:

  • Las cámaras instaladas en el ordenador o el dispositivo del usuario que están disponibles

  • Si la cámara está instalada

  • Si Flash Player tiene permiso para acceder a la cámara del usuario

  • La cámara que está activa en ese momento

  • La anchura y la altura del vídeo que se captura

La clase Camera incluye varios métodos y propiedades útiles para utilizar objetos Camera. Por ejemplo, la propiedad Camera.names estática contiene un conjunto de nombres de cámara instalados en ese momento en el ordenador del usuario. Asimismo, se puede utilizar la propiedad name para mostrar el nombre de la cámara activa en ese momento.

Nota: al transmitir vídeo de cámara en la red, siempre se deben gestionar las interrupciones de red. Las interrupciones de red pueden suceder por varios motivos, especialmente en los dispositivos móviles.

Visualización del contenido de la cámara en pantalla

La conexión a una cámara puede requerir menos código que utilizar las clases NetConnection y NetStream para cargar un vídeo. Asimismo, la clase Camera puede plantear problemas rápidamente, ya que se necesita el permiso de un usuario para que Flash Player se conecte a su cámara antes de que poder acceder a ella.

En el código siguiente se muestra cómo se puede utilizar la clase Camera para conectarse a la cámara local de un usuario:

var cam:Camera = Camera.getCamera(); 
var vid:Video = new Video(); 
vid.attachCamera(cam); 
addChild(vid);
Nota: la clase Camera no tiene un método constructor. Para crear una nueva instancia de Camera, se utiliza el método Camera.getCamera() estático.

Diseño de la aplicación de cámara

Al programar una aplicación que se conecta a la cámara de un usuario, el código debe hacer lo siguiente:

  • Comprobar si el usuario tiene una cámara instalada en ese momento. Gestione el caso donde no haya cámaras disponibles.

  • Solo en Flash Player, compruebe si el usuario ha permitido el acceso a la cámara de forma explícita. Por motivos de seguridad, el reproductor muestra el cuadro de diálogo Configuración de Flash Player, en el que el usuario permite o deniega el acceso a su cámara. Esto impide que Flash Player se conecte a la cámara de un usuario y difunda un flujo de vídeo sin su permiso. Si el usuario permite el acceso haciendo clic en el botón correspondiente, la aplicación puede conectarse a la cámara. De lo contrario, la aplicación no podrá acceder a dicha cámara. Las aplicaciones siempre deben controlar ambas situaciones adecuadamente.

  • Solo para AIR, compruebe si la clase Camera se admite en los perfiles del dispositivo compatibles con la aplicación.

  • La clase Camera no se admite en los navegadores móviles.

  • La clase Camera no es compatible en las aplicaciones de AIR móviles que utilizan el modo de representación con GPU.

  • En dispositivos móviles, solo una cámara puede estar activa al mismo tiempo.

Conexión a la cámara de un usuario

El primer paso de la conexión a la cámara de un usuario consiste en crear una nueva instancia de cámara; se crea una variable de tipo Camera, que se inicializa al valor devuelto del método Camera.getCamera() estático.

El siguiente paso es crear un nuevo objeto Video y asociarle el objeto Camera.

El tercer paso consiste en añadir el objeto Video a la lista de visualización. Los pasos 2 y 3 son necesarios, ya que la clase Camera no amplía la clase DisplayObject y no se puede añadir directamente a la lista. Para mostrar el vídeo capturado de la cámara, se crea un nuevo objeto Video y se llama al método attachCamera() .

En el código siguiente se muestran estos tres pasos:

var cam:Camera = Camera.getCamera(); 
var vid:Video = new Video(); 
vid.attachCamera(cam); 
addChild(vid);

Se debe tener en cuenta que si un usuario no dispone de una cámara instalada, la aplicación no mostrará nada.

En situaciones reales, deben llevarse a cabo pasos adicionales para la aplicación. Consulte Comprobación de que las cámaras están instaladas y Detección de permisos para el acceso a una cámara para obtener más información.

Comprobación de que las cámaras están instaladas

Antes de intentar utilizar métodos o propiedades en una instancia de cámara, tal vez se desee comprobar que el usuario tiene una cámara instalada. Existen dos maneras de comprobar si el usuario tiene una cámara instalada:

  • Comprobar la propiedad estática Camera.names que contiene un conjunto de nombres de cámara disponibles. Normalmente, este conjunto tiene una cadena o ninguna, puesto que la mayoría de usuarios no disponen de más de una cámara instalada a la vez. En el código siguiente se muestra cómo se puede comprobar la propiedad Camera.names para ver si el usuario tiene cámaras disponibles:

    if (Camera.names.length > 0) 
    { 
        trace("User has at least one camera installed."); 
        var cam:Camera = Camera.getCamera(); // Get default camera. 
    } 
    else 
    { 
        trace("User has no cameras installed."); 
    }
  • Comprobar el valor devuelto del método estático Camera.getCamera() . Si no hay cámaras instaladas o disponibles, este método devuelve null ; de lo contrario, devuelve una referencia a un objeto Camera. En el código siguiente se muestra cómo se puede comprobar el método Camera.getCamera() para ver si el usuario tiene cámaras disponibles:

    var cam:Camera = Camera.getCamera(); 
    if (cam == null) 
    { 
        trace("User has no cameras installed."); 
    } 
    else 
    { 
        trace("User has at least 1 camera installed."); 
    }

Debido a que la clase Camera no amplía la clase DisplayObject, no se puede añadir directamente a la lista de visualización utilizando el método addChild() . Para mostrar el vídeo capturado de la cámara, se debe crear un nuevo objeto Video y llamar al método attachCamera() en la instancia de Video.

Este fragmento de código muestra cómo se puede conectar la cámara, si se dispone de ella; de lo contrario, la aplicación no mostrará nada.

var cam:Camera = Camera.getCamera(); 
if (cam != null) 
{ 
    var vid:Video = new Video(); 
    vid.attachCamera(cam); 
    addChild(vid); 
}

Cámaras de dispositivos móviles

La clase Camera no se admite en el motor de ejecución de Flash Player en navegadores para móvil.

En aplicaciones de AIR instaladas en dispositivos móviles es posible acceder a la cámara o a las cámaras en el dispositivo. En dispositivos móviles, puede usarse tanto la cámara trasera como la delantera, pero no al mismo tiempo. (Cuando se activa una, se desactiva la otra.) La cámara frontal se refleja horizontalmente en iOS, pero no en Android.

Detección de permisos para el acceso a una cámara

En el entorno limitado de la aplicación AIR, la aplicación puede acceder a cualquier cámara sin el permiso del usuario. Sin embargo, en Android, una aplicación debe especificar el permiso CAMERA de Android en el archivo descriptor de la aplicación.

Antes de que Flash Player pueda mostrar la salida de una cámara, el usuario debe permitir explícitamente a la aplicación que acceda a la cámara. Cuando se llama al método attachCamera() , Flash Player muestra el cuadro de diálogo Configuración de Flash Player, que pregunta al usuario si desea que Flash Player acceda a la cámara y al micrófono. Si el usuario hace clic en el botón Permitir, Flash Player muestra la salida de la cámara en la instancia de Video en el escenario. Si el usuario hace clic en el botón de rechazo, Flash Player no puede conectarse a la cámara y el objeto Video no muestra nada.

Si se desea saber si el usuario ha permitido o rechazado el acceso a la cámara, se puede detectar el evento status ( StatusEvent.STATUS ) de la cámara, tal y como se muestra en el código siguiente:

var cam:Camera = Camera.getCamera(); 
if (cam != null) 
{ 
    cam.addEventListener(StatusEvent.STATUS, statusHandler); 
    var vid:Video = new Video(); 
    vid.attachCamera(cam); 
    addChild(vid); 
} 
function statusHandler(event:StatusEvent):void 
{ 
    // This event gets dispatched when the user clicks the "Allow" or "Deny" 
    // button in the Flash Player Settings dialog box. 
    trace(event.code); // "Camera.Muted" or "Camera.Unmuted" 
}

La función statusHandler() se llama cuando el usuario hace clic en los botones para permitir o denegar el acceso. Se puede detectar el botón en el que ha hecho clic el usuario con uno de estos dos métodos:

  • El parámetro event de la función statusHandler() contiene una propiedad de código que incluye la cadena "Camera.Muted" o "Camera.Unmuted". Si el valor es "Camera.Muted", el usuario ha hecho clic en el botón para denegar el acceso y Flash Player no puede acceder a la cámara. Se puede ver un ejemplo de esto en el fragmento siguiente:

    function statusHandler(event:StatusEvent):void 
    { 
        switch (event.code) 
        { 
            case "Camera.Muted": 
                trace("User clicked Deny."); 
                break; 
            case "Camera.Unmuted": 
                trace("User clicked Accept."); 
                break; 
        } 
    }
  • La clase Camera contiene una propiedad de solo lectura denominada muted , que especifica si el usuario ha denegado el acceso a la cámara ( true ) o lo ha permitido ( false ) en el panel Privacidad de Flash Player. Se puede ver un ejemplo de esto en el fragmento siguiente:

    function statusHandler(event:StatusEvent):void 
    { 
        if (cam.muted) 
        { 
            trace("User clicked Deny."); 
        } 
        else 
        { 
            trace("User clicked Accept."); 
        } 
    }

Al buscar el evento de estado que se va a distribuir, se puede escribir código que controle la aceptación o el rechazo del acceso a la cámara por parte del usuario y llevar a cambio la limpieza correspondiente. Por ejemplo, si el usuario hace clic en el botón para denegar el acceso, se puede mostrar un mensaje al usuario que indique que debe hacer clic en el botón para permitir el acceso si desea participar en un chat de vídeo. Asimismo, se puede asegurar de que el objeto Video esté eliminado de la lista de visualización para liberar recursos de sistema.

En AIR, un objeto Camera no distribuye eventos de estado, ya que el permiso para utilizar la cámara no es dinámico.

Aumento de la calidad de vídeo de la cámara

De forma predeterminada, las nuevas instancias de la clase Video son de 320 píxeles de ancho x 240 píxeles de alto. Para aumentar la calidad de vídeo, siempre debe asegurarse de que el objeto Video coincide con las mismas dimensiones que el vídeo que devuelve el objeto Camera. Se puede obtener la anchura y la altura del objeto Camera mediante las propiedades width y height de la clase Camera. Asimismo, se pueden establecer las propiedades width y height del objeto Video para que se correspondan con las dimensiones de los objetos Camera. También es posible pasar la anchura y la altura al método constructor de la clase Video, tal como se muestra en el fragmento siguiente:

var cam:Camera = Camera.getCamera(); 
if (cam != null) 
{ 
    var vid:Video = new Video(cam.width, cam.height); 
    vid.attachCamera(cam); 
    addChild(vid); 
}

Puesto que el método getCamera() devuelve una referencia a un objeto Camera (o null si no hay cámaras disponibles), se puede acceder a los métodos y las propiedades de la cámara aunque el usuario deniegue el acceso a ella. Esto permite establecer el tamaño de la instancia de vídeo con la altura y la anchura nativas de la cámara.

var vid:Video; 
var cam:Camera = Camera.getCamera(); 
 
if (cam == null) 
{ 
    trace("Unable to locate available cameras."); 
} 
else 
{ 
    trace("Found camera: " + cam.name); 
    cam.addEventListener(StatusEvent.STATUS, statusHandler); 
    vid = new Video(); 
    vid.attachCamera(cam); 
} 
function statusHandler(event:StatusEvent):void 
{ 
    if (cam.muted) 
    { 
        trace("Unable to connect to active camera."); 
    } 
    else 
    { 
        // Resize Video object to match camera settings and  
        // add the video to the display list. 
        vid.width = cam.width; 
        vid.height = cam.height; 
        addChild(vid); 
    } 
    // Remove the status event listener. 
    cam.removeEventListener(StatusEvent.STATUS, statusHandler); 
}

Para obtener información sobre el modo de pantalla completa, consulte la sección sobre este tema en Configuración de las propiedades de Stage .

Supervisión del estado de la cámara

La clase Camera contiene varias propiedades que permiten controlar el estado actual del objeto Camera. Por ejemplo, el código siguiente muestra varias de las propiedades de la cámara mediante un objeto Timer y una instancia de campo de texto en la lista de visualización:

var vid:Video; 
var cam:Camera = Camera.getCamera(); 
var tf:TextField = new TextField(); 
tf.x = 300; 
tf.autoSize = TextFieldAutoSize.LEFT; 
addChild(tf); 
 
if (cam != null) 
{ 
    cam.addEventListener(StatusEvent.STATUS, statusHandler); 
    vid = new Video(); 
    vid.attachCamera(cam); 
} 
function statusHandler(event:StatusEvent):void 
{ 
    if (!cam.muted) 
    { 
        vid.width = cam.width; 
        vid.height = cam.height; 
        addChild(vid); 
        t.start(); 
    } 
    cam.removeEventListener(StatusEvent.STATUS, statusHandler); 
} 
 
var t:Timer = new Timer(100); 
t.addEventListener(TimerEvent.TIMER, timerHandler); 
function timerHandler(event:TimerEvent):void 
{ 
    tf.text = ""; 
    tf.appendText("activityLevel: " + cam.activityLevel + "\n"); 
    tf.appendText("bandwidth: " + cam.bandwidth + "\n"); 
    tf.appendText("currentFPS: " + cam.currentFPS + "\n"); 
    tf.appendText("fps: " + cam.fps + "\n"); 
    tf.appendText("keyFrameInterval: " + cam.keyFrameInterval + "\n"); 
    tf.appendText("loopback: " + cam.loopback + "\n"); 
    tf.appendText("motionLevel: " + cam.motionLevel + "\n"); 
    tf.appendText("motionTimeout: " + cam.motionTimeout + "\n"); 
    tf.appendText("quality: " + cam.quality + "\n"); 
}

Cada 1/10 de segundo (100 milisegundos) se distribuye el evento timer del objeto Timer y la función timerHandler() actualiza el campo de texto de la lista de visualización.