Работа с камерами

Flash Player 9 и более поздних версий, Adobe AIR 1.0 и более поздних версий

В качестве источника видеоданных для отображения и манипулирования с помощью ActionScript можно использовать камеру, подключенную к компьютеру пользователя. Класс Camera представляет собой механизм, встроенный в ActionScript и предназначенный для работы с камерой компьютера или устройства.

На мобильных устройствах можно также использовать класс CameraUI . Класс CameraUI запускает отдельное приложение камеры, чтобы предоставить пользователю возможность захватывать неподвижные изображения и видео. По завершении захвата приложение может обращаться к данным изображения или видео посредством объекта MediaPromise .

Понимание класса Camera

Объект Camera позволяет подключить локальную камеру пользователя и передавать видео локально (на экран пользователя) или удаленно на сервер (такой как Flash Media Server).

С помощью класса Camera можно получить доступ к следующим типам информации о камере пользователя:

  • Какие камеры, из установленных на компьютере или устройстве пользователя, доступны

  • установлена ли камера;

  • разрешен или запрещен проигрывателю Flash Player доступ к камере пользователя;

  • какая камера активна в данный момент;

  • ширина и высота захватываемого видео.

Класс Camera включает несколько полезных методов и свойств для работы с камерами. Например, статическое свойство Camera.names содержит массив имен камер, в данный момент установленных на компьютере пользователя. Также для отображения имени текущей активной камеры можно использовать свойство name .

Примечание. При передачи видеопотока с камеры по сети всегда следует обрабатывать сетевые прерывания. Сетевые прерывания могут возникать по многим причинам, особенно на мобильных устройствах.

Отображение содержимого камеры на экране

Для подключения к камере может потребоваться не такой длинный код, как для загрузки видео с помощью классов NetConnection и NetStream. Класс Camera может также создавать трудности в связи с тем, что проигрыватель Flash Player требует, чтобы пользователь дал разрешение на подключение к камере, к ней можно будет получить доступ.

Следующий код демонстрирует, как с помощью класса Camera можно подключиться к локальной камере пользователя.

var cam:Camera = Camera.getCamera(); 
var vid:Video = new Video(); 
vid.attachCamera(cam); 
addChild(vid);
Примечание. Класс Camera не имеет собственного конструктора. Для создания нового экземпляра Camera используется статический метод Camera.getCamera() .

Разработка приложения для камеры

Создавая приложение, которое подключается к камере пользователя, код следует писать с учетом следующего.

  • Проверьте, установлена ли камера на компьютере пользователя в данный момент. Обработайте ситуацию, когда камера не доступна.

  • Только для проигрывателя Flash Player: проверьте, разрешил ли пользователь доступ к камере. По соображениям безопасности, проигрыватель открывает диалоговое окно «Параметры Flash Player», в котором пользователь может предоставить или запретить доступ к своей камере. В результате этого проигрыватель Flash Player не может подключиться к камере пользователя и передавать видеопоток, если не получит явного разрешения. Если пользователь выберет «Разрешить», приложение сможет подключиться к его камере. Если пользователь выберет «Запретить», приложение не сможет получить доступ к камере. В обоих случаях приложения должны вежливо реагировать на ответ пользователя.

  • В среде AIR проверьте, поддерживается ли класс Camera для профилей устройств, поддерживаемых вашим приложением.

  • Класс Camera не поддерживается в мобильных браузерах.

  • Класс Camera не поддерживается в приложениях AIR для мобильных устройств, которые используют режим визуализации с помощью графического процессора.

  • На мобильных устройствах одновременно активной может быть только одна камера.

Подключение к камере пользователя

Чтобы подключиться к камере пользователя, во-первых, нужно добавить новый экземпляр Camera, создав переменную типа Camera и присвоив ей значение, возвращенное методом Camera.getCamera() .

Во-вторых, необходимо создать новый объект Video и присоединить к нему объект Camera.

В-третьих, нужно добавить объект Video в список отображения. Выполнение действий 2 и 3 требуется по той причине, что класс Camera не расширяет класс DisplayObject и его объекты нельзя добавить в список отображения напрямую. Для отображения видео, захватываемого камерой, нужно создать новый объект Video, и вызвать метод attachCamera() .

Следующий код демонстрирует выполнение этих трех действий.

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

Обратите внимание, что если к компьютеру пользователя не подключена камера, приложение ничего не отображает.

В реальной ситуации приложение должно выполнять дополнительные действия. Дополнительные сведения см. в разделах « Проверка установки камер » и « Определение разрешений для доступа к камере ».

Проверка установки камер

Прежде чем пытаться использовать методы или свойства экземпляра Camera, необходимо убедиться, что к компьютеру пользователя подключена камера. Установку камеры можно проверить двумя способами.

  • Проверите статическое свойство Camera.names , которое содержит массив с именами доступных камер. Как правило, этот массив содержит одну или меньше строк, так как большинство пользователей одновременно устанавливают не больше одной камеры. Следующий код проверяет свойство Camera.names , чтобы узнать, есть ли у пользователя доступные камеры.

    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."); 
    }
  • Проверьте значение, возвращенное статическим методом Camera.getCamera() . Если камеры недоступны или не установлены, этот метод возвращает значение null , в противном случае он возвращает ссылку на объект Camera. Следующий код использует метод Camera.getCamera() , чтобы узнать, есть ли у пользователя доступные камеры.

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

Так как класс Camera не расширяет класс DisplayObject, его экземпляр нельзя добавить в список отображения напрямую с помощью метода addChild() . Для отображения видео, захватываемого с камеры, необходимо создать новый объект Video и вызвать для него метод attachCamera() .

Следующий код присоединяет камеру, если она есть; в противном случае приложение ничего не показывает.

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

Камеры мобильных устройств

Класс Camera не поддерживается в среде выполнения Flash Player в браузерах для мобильных устройств.

В приложениях AIR для мобильных устройств можно получать доступ к одной или нескольким камерам на устройстве. На мобильных устройствах можно использовать камеры и спереди и сзади, но одновременно может отображаться вывод только одной из них. (В результате присоединения второй камеры первая отсоединяется.) Камера на передней панели устройства зеркально отображается по горизонтали на устройствах iOS, на устройствах Android этого не происходит.

Определение разрешений для доступа к камере

В собственной изолированной программной среде приложение AIR может получать доступ к любой камере без разрешения пользователя. Однако на платформе Android для программы должно быть указано разрешение Android CAMERA в дескрипторе программы.

Прежде чем проигрыватель Flash Player сможет показать вывод с камеры, пользователь должен дать ему явное разрешение на доступ к камере. Когда вызывается метод attachCamera() , проигрыватель Flash Player выводит окно «Параметры Flash Player», в котором пользователь может разрешить или запретить проигрывателю Flash Player доступ к камере и микрофону. Если пользователь нажимает кнопку «Разрешить», Flash Player отображает вывод камеры в экземпляре Video в рабочей области. Если пользователь нажимает кнопку «Запретить», Flash Player не может подключиться к камере, и объект Video ничего не показывает.

Если требуется узнать, предоставил ли пользователь доступ к камере проигрывателю Flash Player, можно прослушивать событие status камеры ( StatusEvent.STATUS ), как показано в следующем коде.

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" 
}

Функция statusHandler() вызывается сразу после того, как пользователь нажимает кнопку «Разрешить» или «Запретить». Определить, какую кнопку нажал пользователь, можно двумя способами:

  • Параметр event функции statusHandler() содержит свойство code со строкой «Camera.Muted» или «Camera.Unmuted». Если свойство имеет значение «Camera.Muted», пользователь нажал кнопку «Запретить» и проигрыватель Flash Player не может получить доступ к камере. Это демонстрируется на следующем примере.

    function statusHandler(event:StatusEvent):void 
    { 
        switch (event.code) 
        { 
            case "Camera.Muted": 
                trace("User clicked Deny."); 
                break; 
            case "Camera.Unmuted": 
                trace("User clicked Accept."); 
                break; 
        } 
    }
  • Класс Camera содержит свойство muted , которое предназначено только для чтения и указывает, запретил пользователь доступ ( true ) или разрешил ( false ) через панель «Конфиденциальность Flash Player». Это демонстрируется на следующем примере.

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

Отслеживая отправку события status, можно добавить код для обработки ответа пользователя на запрос доступа к камере, чтобы выполнить соответствующие действия. Например, если пользователь нажимает кнопку «Запретить», можно показать ему сообщение о том, что для участия в видеочате необходимо нажать кнопку «Разрешить», или удалить объект Video из списка отображения, чтобы освободить системные ресурсы.

В среде AIR объект Camera не отправляет события status, так как разрешение на использование камеры не является динамическим.

Обеспечение максимального качества видео с камеры

По умолчанию новые экземпляры класса Video имеют ширину 320 пикселов и высоту 240 пикселов. Чтобы обеспечить максимальное качество видео, необходимо всегда следить за тем, чтобы объект Video соответствовал размерам видео, возвращаемого объектом Camera. Ширину и высоту объекта Camera можно получить с помощью его свойств width и height , после чего нужно задать свойства width и height объекта Video в соответствии с полученными значениями, либо передать ширину и высоту камеры конструктору класса Video, как показано в следующем примере.

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

Так как метод getCamera() возвращает ссылку на объект Camera (или значение null , если камера недоступна), то его методы и свойства можно получить, даже если пользователь запрещает доступ к камере. Это позволяет задать размер экземпляра Video в соответствии с высотой и шириной камеры.

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); 
}

Сведения о полноэкранном режиме см. в пункте «Работа в полноэкранном режиме» раздела « Установка свойств рабочей области ».

Мониторинг состояния камеры

Класс Camera содержит несколько свойств, которые позволяют отслеживать текущее состояние объекта Camera. Например, следующий код отображает некоторые свойства экземпляра Camera с помощью объекта Timer и экземпляра TextField в списке отображения.

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"); 
}

Через каждую десятую долю секунды (100 миллисекунд) объект Timer отправляет событие timer , и функция timerHandler() обновляет текстовое поле в списке отображения.