비디오 예제: 비디오 주크박스

Flash Player 9 이상, Adobe AIR 1.0 이상

다음 예제에서는 순서대로 재생할 비디오 목록을 동적으로 로드하는 간단한 비디오 주크박스를 만듭니다. 이를 통해 사용자가 여러 비디오 설명서를 찾아볼 수 있는 응용 프로그램이나 사용자가 요청한 비디오를 전달하기 전에 재생할 광고를 지정하는 응용 프로그램을 만들 수 있습니다. 이 예제에서는 ActionScript 3.0의 다음 기능을 설명합니다.

  • 비디오 파일의 재생 진행률에 따라 재생 헤드 업데이트

  • 비디오 파일의 메타데이터 수신 및 구문 분석

  • 넷스트림에서 특정 코드 처리

  • 동적으로 로드된 FLV 로드, 재생, 일시 정지 및 중지

  • 넷스트림의 메타데이터를 기반으로 표시 목록의 Video 객체 크기 조절

이 샘플에 대한 응용 프로그램 파일을 가져오려면 www.adobe.com/go/learn_programmingAS3samples_flash_kr를 참조하십시오. 비디오 주크박스 응용 프로그램 파일은 Samples/VideoJukebox 폴더에 있습니다. 이 응용 프로그램은 다음과 같은 파일로 구성됩니다.

File

설명

VideoJukebox.fla

또는

VideoJukebox.mxml

Flex(MXML) 또는 Flash(FLA) 형식의 기본 응용 프로그램 파일입니다.

VideoJukebox.as

응용 프로그램의 기본 기능을 제공하는 클래스입니다.

playlist.xml

비디오 주크박스로 로드할 비디오 파일이 나열된 파일입니다.

외부 비디오 재생 목록 파일 로드

외부 playlist.xml 파일은 로드할 비디오와 비디오 재생 순서를 지정합니다. XML 파일을 로드하려면 다음 코드와 같이 URLLoader 객체와 URLRequest 객체를 사용해야 합니다.

uldr = new URLLoader(); 
uldr.addEventListener(Event.COMPLETE, xmlCompleteHandler); 
uldr.load(new URLRequest(PLAYLIST_XML_URL));

이 코드는 VideoJukebox 클래스의 생성자 내에 있으므로 다른 코드가 실행되기 전에 먼저 파일이 로드됩니다. XML 파일 로드가 완료되면 다음 코드와 같이 곧바로 xmlCompleteHandler() 메서드가 호출되어 외부 파일을 XML 객체로 파싱합니다.

private function xmlCompleteHandler(event:Event):void 
{ 
    playlist = XML(event.target.data); 
    videosXML = playlist.video; 
    main(); 
}

playlist XML 객체에는 외부 파일에서 가져온 원시 XML이 포함되어 있고, videos XML은 해당 비디오 노드가 포함된 XMLList 객체입니다. 다음 코드에서 샘플 playlist.xml 파일을 확인할 수 있습니다.

<videos> 
    <video url="video/caption_video.flv" /> 
    <video url="video/cuepoints.flv" /> 
    <video url="video/water.flv" /> 
</videos>

마지막으로, xmlCompleteHandler() 메서드는 외부 FLV 파일 로드에 사용되는 NetConnection 및 NetStream 객체뿐만 아니라 표시 목록의 다양한 구성 요소 인스턴스를 설정하는 main() 메서드도 호출합니다.

사용자 인터페이스 만들기

사용자 인터페이스를 만들려면 Button 인스턴스 다섯 개를 표시 목록으로 드래그하여 각 인스턴스에 playButton, pauseButton, stopButton, backButton, forwardButton이라는 이름을 지정해야 합니다.

다음 코드와 같이 각 Button 인스턴스에 대해 click 이벤트에 대한 핸들러를 할당해야 합니다.

playButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
pauseButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
stopButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
backButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
forwardButton.addEventListener(MouseEvent.CLICK, buttonClickHandler);

buttonClickHandler() 메서드는 다음 코드와 같이 switch 문을 사용하여 클릭된 Button 인스턴스를 확인합니다.

private function buttonClickHandler(event:MouseEvent):void 
{ 
    switch (event.currentTarget) 
    { 
        case playButton: 
            ns.resume(); 
            break; 
        case pauseButton: 
            ns.togglePause(); 
            break; 
        case stopButton: 
            ns.pause(); 
            ns.seek(0); 
            break; 
        case backButton: 
            playPreviousVideo(); 
            break; 
        case forwardButton: 
            playNextVideo(); 
            break; 
    } 
}

그런 다음 Slider 인스턴스를 표시 목록에 추가하고 volumeSlider라는 인스턴스 이름을 지정합니다. 다음 코드에서는 Slider 인스턴스의 liveDragging 속성을 true로 설정하고 Slider 인스턴스의 change 이벤트에 대한 이벤트 리스너를 정의합니다.

volumeSlider.value = volumeTransform.volume; 
volumeSlider.minimum = 0; 
volumeSlider.maximum = 1; 
volumeSlider.snapInterval = 0.1; 
volumeSlider.tickInterval = volumeSlider.snapInterval; 
volumeSlider.liveDragging = true; 
volumeSlider.addEventListener(SliderEvent.CHANGE, volumeChangeHandler);

ProgressBar 인스턴스를 표시 목록에 추가하고 positionBar라는 인스턴스 이름을 지정합니다. 다음 코드와 같이 mode 속성을 manual로 설정합니다.

positionBar.mode = ProgressBarMode.MANUAL;

마지막으로 Label 인스턴스를 표시 목록에 추가하고 positionLabel이라는 인스턴스 이름을 지정합니다. Timer 인스턴스에서 이 Label 인스턴스의 값을 설정합니다.

Video 객체의 메타데이터 수신

Flash Player에서 로드된 각 비디오에 대한 메타데이터가 발견되면 NetStream 객체의 client 속성에 대해 onMetaData() 콜백 핸들러가 호출됩니다. 다음 코드에서는 Object를 초기화하고 지정된 콜백 핸들러를 설정합니다.

client = new Object(); 
client.onMetaData = metadataHandler;

metadataHandler() 메서드는 데이터를 코드 내에 이전에 정의되어 있던 메타 속성에 복사합니다. 그러면 전체 응용 프로그램에서 언제든지 현재 비디오의 메타데이터에 액세스할 수 있습니다. 다음으로 스테이지에 있는 Video 객체의 크기가 메타데이터에서 반환된 크기에 맞게 조절됩니다. 마지막으로 현재 재생 중인 비디오의 크기에 맞게 positionBar 진행률 막대 인스턴스가 이동되고 크기가 조절됩니다. 다음 코드에는 전체 metadataHandler() 메서드가 포함되어 있습니다.

private function metadataHandler(metadataObj:Object):void 
{ 
    meta = metadataObj; 
    vid.width = meta.width; 
    vid.height = meta.height; 
    positionBar.move(vid.x, vid.y + vid.height); 
    positionBar.width = vid.width; 
}

동적 비디오 로드

각 비디오를 동적으로 로드하기 위해 응용 프로그램에서 NetConnection 및 NetStream 객체를 사용합니다. 다음 코드는 NetConnection 객체를 생성하고 null 값을 connect() 메서드에 전달합니다. Flash Player는 null을 지정하여 Flash Media Server 등의 서버에 연결하는 것이 아니라 로컬 서버에 있는 비디오에 연결합니다.

다음 코드에서는 NetConnection 및 NetStream 인스턴스를 모두 만들고, netStatus 이벤트에 대한 이벤트 리스너를 정의하며, client 객체를 client 속성에 할당합니다.

nc = new NetConnection(); 
nc.connect(null); 
 
ns = new NetStream(nc); 
ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); 
ns.client = client;

비디오의 상태가 변경될 때마다 netStatusHandler() 메서드가 호출됩니다. 비디오가 재생을 시작하거나 중지하는 경우, 비디오를 버퍼링하는 경우 또는 비디오 스트림을 찾을 수 없는 경우 등이 여기에 해당합니다. 다음 코드에서는 netStatusHandler() 이벤트를 나열합니다.

private function netStatusHandler(event:NetStatusEvent):void 
{ 
    try 
    { 
        switch (event.info.code) 
        { 
            case "NetStream.Play.Start": 
                t.start(); 
                break; 
            case "NetStream.Play.StreamNotFound": 
            case "NetStream.Play.Stop": 
                t.stop(); 
                playNextVideo(); 
                break; 
        } 
    }  
    catch (error:TypeError)  
    { 
        // Ignore any errors. 
    } 
}

이전 코드에서는 Info 객체의 코드 속성을 평가하여 코드를 "NetStream.Play.Start", "NetStream.Play.StreamNotFound" 또는 "NetStream.Play.Stop"으로 필터링합니다. 다른 코드는 모두 무시됩니다. 넷스트림이 시작되면 코드에서 재생 헤드를 업데이트하는 Timer 인스턴스를 시작합니다. 넷스트림이 없거나 중지되면 Timer 인스턴스가 중지되고 응용 프로그램에서 재생 목록의 다음 비디오를 재생하려고 합니다.

Timer가 실행될 때마다 positionBar 진행률 막대 인스턴스는 ProgressBar 클래스의 setProgress() 메서드를 호출하여 현재 위치를 업데이트하고, positionLabel Label 인스턴스에는 현재 비디오의 경과 시간 및 총 시간이 업데이트됩니다.

private function timerHandler(event:TimerEvent):void 
{ 
    try 
    { 
        positionBar.setProgress(ns.time, meta.duration); 
        positionLabel.text = ns.time.toFixed(1) + " of " meta.duration.toFixed(1) + " seconds"; 
    }  
    catch (error:Error) 
    { 
        // Ignore this error. 
    } 
}

비디오 볼륨 제어

동적으로 로드된 비디오에 대해 NetStream 객체의 soundTransform 속성을 설정하여 볼륨을 제어할 수 있습니다. 비디오 주크박스 응용 프로그램을 활용하면 volumeSlider Slider 인스턴스 값을 변경하여 볼륨 수준을 수정할 수 있습니다. 다음 코드에서는 NetStream 객체의 soundTransform 속성으로 설정되어 있는 SoundTransform 객체에 Slider 구성 요소 값을 할당하여 볼륨 수준을 변경하는 방법을 보여 줍니다.

private function volumeChangeHandler(event:SliderEvent):void 
{ 
    volumeTransform.volume = event.value; 
    ns.soundTransform = volumeTransform; 
}

비디오 재생 제어

응용 프로그램의 나머지 부분은 비디오가 비디오 스트림의 끝에 도달하거나 사용자가 이전 또는 다음 비디오를 건너뛸 때 비디오 재생을 제어합니다.

다음 메서드에서는 현재 선택된 인덱스의 XMLList에서 비디오 URL을 검색합니다.

private function getVideo():String 
{ 
    return videosXML[idx].@url; 
}

playVideo() 메서드는 NetStream 객체의 play() 메서드를 호출하여 현재 선택되어 있는 비디오를 로드합니다.

private function playVideo():void 
{ 
    var url:String = getVideo(); 
    ns.play(url); 
}

playPreviousVideo() 메서드는 현재 비디오 인덱스를 감소시키고, playVideo() 메서드를 호출하여 새 비디오 파일을 로드하며, 진행률 막대를 표시합니다.

private function playPreviousVideo():void 
{ 
    if (idx > 0) 
    { 
        idx--; 
        playVideo(); 
        positionBar.visible = true; 
    } 
}

마지막 메서드인 playNextVideo()는 비디오 인덱스를 증가시키고 playVideo() 메서드를 호출합니다. 현재 비디오가 재생 목록의 마지막 비디오인 경우, Video 객체에 대해 clear() 메서드가 호출되고 진행률 막대 인스턴스의 visible 속성이 false로 설정됩니다.

private function playNextVideo():void 
{ 
    if (idx < (videosXML.length() - 1)) 
    { 
        idx++; 
        playVideo(); 
        positionBar.visible = true; 
    } 
    else 
    { 
        idx++; 
        vid.clear(); 
        positionBar.visible = false; 
    } 
}