카메라 입력 캡처

Flash Player 9 이상, Adobe AIR 1.0 이상

ActionScript를 사용하여 표시하고 조작할 수 있는 비디오 데이터의 소스로 외부 비디오 파일뿐만 아니라 사용자의 컴퓨터에 연결된 카메라를 사용할 수 있습니다. Camera 클래스는 컴퓨터 카메라 사용을 위해 ActionScript에 내장된 메커니즘입니다.

Camera 클래스 이해

Camera 객체를 사용하면 사용자의 로컬 카메라에 연결하고 비디오를 로컬로 사용자에게 다시 브로드캐스팅하거나 원격으로 Flash Media Server 등의 서버에 브로드캐스팅할 수 있습니다.

Camera 클래스를 사용하여 사용자 카메라에 대한 다음과 같은 정보에 액세스할 수 있습니다.

  • 사용자의 컴퓨터에 설치된 카메라 중 사용할 수 있는 카메라

  • 카메라 설치 여부

  • 사용자의 카메라에 대한 Flash Player의 액세스 허용 여부

  • 현재 활성화된 카메라

  • 캡처 중인 비디오의 폭 및 높이

Camera 클래스에는 Camera 객체를 사용하는 데 유용한 몇 가지 메서드와 속성이 있습니다. 예를 들어 정적 Camera.names 속성에는 사용자 컴퓨터에 현재 설치되어 있는 카메라 이름 배열이 포함됩니다. name 속성을 사용하여 현재 활성화된 카메라의 이름을 표시할 수도 있습니다.

참고: 네트워크를 통해 카메라 비디오를 스트리밍할 때는 항상 네트워크 중단을 처리할 수 있어야 합니다. 네트워크 중단은 특히 휴대 장치에서 여러 가지 이유로 발생할 수 있습니다.

화면에 카메라 내용 표시

카메라에 연결하는 데 필요한 코드는 NetConnection 및 NetStream 클래스를 사용하여 비디오를 로드할 때보다 더 적을 수 있습니다. 그러나 Flash Player를 사용할 경우 카메라에 액세스할 수 있게 Flash Player를 카메라에 연결하려면 사용자가 이를 허용해야 하므로 Camera 클래스가 복잡해질 수 있습니다.

다음 코드에서는 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 설정] 대화 상자를 표시하여 사용자가 카메라 액세스를 허용하거나 거부하도록 합니다. 이 대화 상자는 Flash Player에서 사용자의 허용 없이 카메라에 연결하여 비디오 스트림을 브로드캐스팅할 수 없게 합니다. 사용자가 [허용]을 클릭하면 응용 프로그램에서 사용자의 카메라에 연결할 수 있으며, [거부]를 클릭하면 응용 프로그램에서 사용자의 카메라에 액세스할 수 없습니다. 응용 프로그램에서 두 경우를 모두 적절하게 처리해야 합니다.

  • Camera 클래스가 응용 프로그램에서 지원하는 장치 프로파일에 대해 지원되는지 확인합니다(AIR의 경우만 해당).

  • Camera 클래스는 휴대 장치 브라우저에서는 지원되지 않습니다.

  • Camera 클래스는 GPU 렌더링 모드를 사용하는 휴대 장치 AIR 응용 프로그램에서는 지원되지 않습니다.

  • iOS에서는 한 번에 하나의 카메라만 활성화됩니다. Android에서는 정방향 카메라만 액세스할 수 있습니다.

사용자의 카메라에 연결

사용자의 카메라에 연결하는 첫 번째 단계는 Camera 유형의 변수를 만든 다음 이 변수를 정적 Camera.getCamera() 메서드의 반환 값으로 초기화하여 새 Camera 인스턴스를 만드는 것입니다.

다음 단계는 새 Video 객체를 만들고 이 객체에 Camera 객체를 연결하는 것입니다.

세 번째 단계는 표시 목록에 Video 객체를 추가하는 것입니다. Camera 클래스는 DisplayObject 클래스를 확장하지 않아 표시 목록에 직접 추가할 수 없으므로 2단계와 3단계를 수행해야 합니다. 카메라에 캡처된 비디오를 표시하려면 새 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 객체를 만들고 Video 인스턴스에 대해 attachCamera() 메서드를 호출해야 합니다.

다음 코드에서는 카메라가 있는 경우 카메라를 연결하는 방법을 보여 줍니다. 카메라가 없는 경우 응용 프로그램은 아무 것도 표시하지 않습니다.

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

카메라 액세스 허용 여부 확인

AIR 응용 프로그램 샌드박스에서 응용 프로그램은 사용자가 허용하지 않아도 카메라에 액세스할 수 있습니다. 그러나 Android에서는 응용 프로그램이 응용 프로그램 설명자에 Android CAMERA 권한을 지정해야 합니다.

사용자가 Flash Player에서 카메라에 액세스할 수 있도록 명시적으로 허용해야 Flash Player에서 카메라 출력을 표시할 수 있습니다. attachCamera() 메서드가 호출되면 Flash Player가 [Flash Player 설정] 대화 상자를 표시하여 사용자에게 Flash Player에서 카메라 및 마이크에 액세스하도록 허용할 것인지 여부를 선택하도록 요청합니다. 사용자가 [허용] 버튼을 클릭하면 Flash Player는 스테이지의 Video 인스턴스에 카메라의 출력을 표시합니다. 사용자가 [거부] 버튼을 클릭하면 Flash Player에서 카메라에 연결할 수 없으며 Video 객체가 아무 것도 표시하지 않습니다.

사용자가 카메라에 대한 액세스를 허용했는지 여부를 확인하려면 다음 코드와 같이 카메라의 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() 함수가 호출됩니다. 다음 두 메서드 중 하나를 사용하여 사용자가 클릭한 버튼을 확인할 수 있습니다.

  • statusHandler() 함수의 event 매개 변수에는 "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."); 
        } 
    }

전달할 상태 이벤트를 확인하여 카메라 액세스에 대한 사용자 허용 또는 거부를 처리하고 이에 맞게 정리하는 코드를 작성할 수 있습니다. 예를 들어 사용자가 [거부] 버튼을 클릭할 경우 비디오 채팅에 참여하려면 [허용]을 클릭해야 한다는 메시지를 사용자에게 표시하거나, 표시 목록의 Video 객체를 삭제하여 사용 가능한 시스템 리소스를 늘릴 수 있습니다.

AIR에서는 카메라를 사용하기 위한 권한이 동적이지 않기 때문에 Camera 객체에서 status 이벤트를 전달하지 않습니다.

비디오 품질 최대화

기본적으로 Video 클래스의 새 인스턴스 크기는 폭 320픽셀 x 높이 240픽셀입니다. 비디오 품질을 최대화하려면 항상 Video 객체 크기를 Camera 객체에서 반환하는 비디오 크기에 맞춰야 합니다. Camera 클래스의 widthheight 속성을 사용하여 Camera 객체의 폭과 높이를 구할 수 있습니다. 그런 다음, 다음 코드 예제와 같이 Video 객체의 widthheight 속성을 Camera 객체 크기에 일치하도록 설정하거나, 카메라의 폭과 높이를 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을 반환), 사용자가 카메라에 대한 액세스를 거부한 경우에도 카메라의 메서드 및 속성에 액세스할 수 있습니다. 그러면 카메라의 기본 높이와 폭을 사용하여 비디오 인스턴스의 크기를 설정할 수 있습니다.

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

전체 화면 모드에 대한 자세한 내용은 Stage 속성 설정의 전체 화면 모드 단원을 참조하십시오.

재생 조건 모니터링

Camera 클래스에는 Camera 객체의 현재 상태를 모니터링할 수 있는 몇 가지 속성이 있습니다. 예를 들어 다음 코드에서는 Timer 객체와 표시 목록의 텍스트 필드 인스턴스를 사용하여 카메라의 여러 속성을 표시합니다.

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

매 1/10초(100밀리초)마다 Timer 객체의 timer 이벤트가 전달되고 timerHandler() 함수가 표시 목록의 텍스트 필드를 업데이트합니다.