'AS3.0 Cookbook/비디오'에 해당되는 글 5건

  1. 2008.09.20 비디오 객체에 PC카메라 붙이기
  2. 2008.09.16 FMS에서 비디오 호출
  3. 2008.08.17 비디오의 제어 속성들 (6)
  4. 2008.08.17 비디오 재생하기
  5. 2008.08.17 비디오 프로그래밍 (2)
AS3.0 Cookbook/비디오2008. 9. 20. 19:28

비디오 객체는 사용자 PC의 카메라에서 퐐영된 정보를 받을 수 있다. 서버에서 전송되는 영상의 데이터를 attachNetStream()를 이용하여 읽는다면 PC카메라의 영상은 attachCamera()를 사용하여 전송되는 영상을 읽어 화면에 보여주게 된다. 따라서 attachCamera()에  Camera의 Delegator를 설정하면 된다.

Posted by 정윤수 버터백통

댓글을 달아 주세요

AS3.0 Cookbook/비디오2008. 9. 16. 18:34

FMS에서는 파일명의 확장자를 설정하지 않는다. 즉 play()에서 호출하는 것은 rtmp에 있는 파일명까지만 호출한다.
  
FMS는 일반 HTTP와 다르게 몇가지 설정을 더해주어야 한다.
1. NetConnection의 인코딩방식을 ObjectEncoding.AMF3    ( AMF0 , AMF3 , DEFAULT )으로 static 메서드에 설정한다.(기본은 AMF3를 사용한다 )

- NetConnection.defaultObjectEncoding= ObjectEncoding.AMF3;
- ObjectEncoding.AMF0 : ActionScript 1.0 및 2.0용 AMF를 사용하여 객체를 직렬화하도록 지정합니다.
- ObjectEncoding.AMF3 : ActionScript 3.0용 AMF를 사용하여 객체를 직렬화하도록 지정합니다.
- ObjectEncoding.DEFAULT : 현재 플레이어의 기본(최신) 형식을 지정합니다. 
                
  
2.  NetConnection 커넥션은 null이 아니고 서비스할 서버의 rtmp주소를 설정한다.
- NetConnection.connect( "rtmp://domain/" );
   
3. FMS에서 콜벡하는 함수 onBWDone()를 만들어 놓는다(단 파라미터는 비어 있도록 한다.)
- 함수는  onMetaData와 같이 public이거나 오브젝트에 포함하여 선언해두면 된다.
- private function onBWDone( ):void
     {
       
     }

Posted by 정윤수 버터백통

댓글을 달아 주세요

AS3.0 Cookbook/비디오2008. 8. 17. 13:02
비디오 파일을 제어하기 위해서는 몇가지 속성을 알아야한다. 이러한 속성은 대부분 NetStream()클래스를 통해서 얻게 된다.

우선 전체재생시간은 NetStream이 onMetaData() 콜벡호출시 duration이라는 값으로 알게 된다.
그리고 현재 재생시간을 알기 위해서는 NetStream의 time속성을 통해 현재 재생시간을 알 수 있다.
최초 재생할 파일을 선택하고 재생하는 것은 NetStream의 play()에서 하지만 이 후 정지와 다시 재생은 NetStream의 pause()resume()메서드를 통해 간단하게 구현할 수 있다.
게다가 NetStream에는 seek()라는 메서드를 제공하는 재생할 시간을 입력하면 그 시간과 가장 가까운 비디오 프레임을 재생하게 된다.

* seek시 가까운 프레임 헤더란?
비디오 파일은 시간 압축되어 있는 파일이다. 즉 모든 영상정보를 저장하는것이 아니고 특정 구간마다 거의 움직이지 않는 장면을 한개 저장하고 있다가 조금씩 움직이는 부분의 영상정보를 저장하여 보여준다. 즉 플래시 무비를 만들 때 배경은 1개의 프레임으로 1개의 레이어를 소비하지만 다른 움직이는 것을 여러개의 프레임을 가지고 있다. 이처럼 배경이나 큰 움직임이 있을때만 비디오 프레임이 갱신되고 이후에는 앞서 갱신된 프레임만 보여주기 때문에 정확한 seek위치가 나오질 않는다. 가령 비디오가 시작시 배경만 갱신되고 이후 특정부위만 움직일때 다시 갱신이 없다면 seek하면 제일 처음부터 재생된다는 것이다.

비디오의 사운드를 제어하기 위해서는 NetStream클래스의 속성인 soundTransform에 제어된 soundTransform를 대입한다. 이방법은 SoundChannel과 같은 방법으로 사용한다.

또한 사용자 네트워크가 느린 경우를 생각하여 NetStream에는 bufferTime이라는 속성이 있다. 이는 최초 재생시 또는 중간에 끊김 이후 재생시 설정한 시간동안 데이터를 받고 해당시간이 되면 재생하도록 하는 버퍼타임을 설정한다.

위에서 언급한 속성과 메서드만 있으면 재생/정지 , 프로그래시브바 , skip등 많은 일들을 할 수 있고 이 모든 것은 NetStream()을 통해서 이루어 진다. 아마 어도비에서도 각 클래스를 분담해서 작업했겠지만 사운드도 이처럼 조금 더 제어 클래스에 집중화 되었더라면 하는 아쉬움이 남는다...



위 무비는 재생이 끝나면 Video의 clear()메서드를 통해 화면을 지웠다. 따라서 아래의 무비처럼 재생 종료 후 영상이 남지 않는다. clear()는 removeChild()와 달리 비디오의 현재 재생화면만 지울 뿐 디스플레이 리스트에서 지워지는 것이 아니기 때문에 언제라도 play()가 이루어 지면 화면을 보여주게 된다. 시시콜콜한 소린 왜 했는가면 책(오라일리)에서 이 둘을 같은 개념으로 설명했기에 차이점을 짚어보고 싶었다...
Posted by 정윤수 버터백통

댓글을 달아 주세요

  1. 도움을 좀 요청 드려도 될까요?
    현재 flvPlayer를 만들고 있는데.. 다른건 다 됐는데..
    저 재생 슬라이더 처리를 못하고 있습니다. 현재 onMetaData 와 onCuePoint를 적용은 했는데..
    핸들처리가 안되는 듯한..

    ㅋ.. 질문이 이해가 가시나요? ㅠ.ㅠ

    2009.05.27 15:01 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • package
      {
      import flash.display.Sprite;
      import flash.events.Event;
      import flash.events.MouseEvent;
      import flash.events.NetStatusEvent;
      import flash.geom.Rectangle;
      import flash.media.Video;
      import flash.net.NetConnection;
      import flash.net.NetStream;
      import flash.net.ObjectEncoding;

      [SWF(width="550" , height="400")]
      public class Video_seek_And_NetStatus extends Sprite
      {
      private var netc:NetConnection;
      private var nets:NetStream;
      private var video:Video;

      private var thumb:Sprite;
      private var track:Sprite;
      private var progress:Sprite;
      private var buffer:Sprite;
      private var jump:Sprite;

      private var cur:Number;
      private var duration:Number;
      private var isDown:Boolean;

      private var meta:Object = new Object();
      public function Video_seek_And_NetStatus()
      {
      super();

      meta.onBWDone = onBWDone;
      meta.onMetaData = onMeta;
      meta.onCuePoint = onCue;

      NetConnection.defaultObjectEncoding= ObjectEncoding.DEFAULT;
      netc = new NetConnection();
      netc.client = meta;
      netc.addEventListener( NetStatusEvent.NET_STATUS, netStatusHandler )
      netc.connect( "rtmp://211.48.55.233/upload/" );
      }


      private function netStatusHandler( e:NetStatusEvent ):void
      {
      switch (e.info.code) {
      case "NetConnection.Connect.Success":
      trace("Success")
      nets = new NetStream( netc );
      nets.client = meta;
      nets.addEventListener(NetStatusEvent.NET_STATUS , onStatus );
      video = new Video(500 , 375);
      video.opaqueBackground = true;
      video.attachNetStream( nets );
      addChild( video );
      nets.play("sample1");
      seekPoint();
      break;
      case "NetStream.Play.StreamNotFound":
      trace("Stream not found");
      break;
      }
      }

      private function seekPoint( ):void
      {
      progress = new Sprite();
      track = new Sprite();
      track.graphics.lineStyle(1);
      track.graphics.drawRect( 10, video.height +10 - 2.5 , 450 , 5 );
      track.graphics.endFill();

      thumb = new Sprite();
      thumb.graphics.lineStyle(1);
      thumb.graphics.beginFill( 0xFFFFFF );
      thumb.graphics.drawRect( 5 , video.height +10 -5 , 10 , 10 );
      thumb.graphics.endFill();

      buffer = new Sprite();

      jump = new Sprite();
      jump.graphics.beginFill( 0 , 0 );
      jump.graphics.drawRect( 10, video.height +10 - 2.5 , 450 , 5 );
      jump.graphics.endFill();

      addChild( progress );
      addChild( track );
      addChild( buffer );
      addChild( jump );
      addChild( thumb );

      addEventListener(Event.ENTER_FRAME , onEnter );
      thumb.addEventListener(MouseEvent.MOUSE_DOWN , onDown );
      jump.addEventListener( MouseEvent.MOUSE_DOWN , onJump );
      stage.addEventListener(MouseEvent.MOUSE_UP , onUp );

      }


      private function onEnter( e:Event ):void
      {
      if( duration > 0 ){
      if( isDown ){
      nets.seek( (duration * thumb.x) / track.width );
      }else{
      thumb.x = (nets.time / duration) * track.width;
      }

      //빨간색으로 재생중인 구간을 보여줌
      progress.graphics.clear();
      progress.graphics.beginFill( 0xFF0000 );
      progress.graphics.drawRect( 10, video.height +10 - 2.5 , track.x + thumb.x , 5 );
      progress.graphics.endFill();
      }
      }

      private function onJump( e:MouseEvent ):void
      {
      isDown = true;
      nets.pause();
      thumb.x = mouseX - 5 - 2.5;
      nets.seek( (duration * thumb.x) / track.width );
      }

      private function onDown( e:MouseEvent ):void
      {
      isDown = true;
      var rect:Rectangle = new Rectangle( 0 , 0 , track.width , 0 );
      thumb.startDrag( false , rect );
      nets.pause();
      }

      private function onUp( e:MouseEvent ):void
      {
      isDown = false;
      thumb.stopDrag();
      nets.resume();
      }
      private var statusCode:String;
      private function onStatus( e:NetStatusEvent ):void
      {
      statusCode = e.info.code;
      trace("************* onStatus *************")
      for( var data:String in e.info ){
      trace( data , " : " , e.info[data] )
      }
      trace("************* End *************")
      //비디오가 끝나는 시점
      if( e.info.code == "NetStream.Play.Stop" ){
      video.clear();

      }
      }
      private function onMeta( data:Object ):void
      {
      trace("onMeta" , data.duration);
      duration = data.duration;
      }

      private function onCue( data:Object ):void
      {
      trace("onCue");
      }
      private function onBWDone( ):void
      {
      trace("onBWDone");
      }
      }
      }

      제가 사용한 코드입니다.
      보시면 seekPoint()에서 트랙을 그리고
      onEnter()에서 클릭시 nets.seek()라는 녀석이 있습니다. 매개변수는 전체 재생시간과 트랙에서의 핸들러 위치를 용해 구한 값을 설정합니다...클릭이 아닐시에는 그냥 현재 재생되는 시간에 맞게 핸들러의 x를 이동시킵니다...
      여기저기 함수가 있어서 통채로 올렸습니다..
      원하시는 답이 되었는지 모르겠네요...;;

      2009.05.28 00:24 신고 [ ADDR : EDIT/ DEL ]
  2. 흠.. 일단 전 타이머를 이용해서 해결을 하긴 했는데..
    좀 아니다 싶네요..

    그리고 이것과 비슷한 소스를 보긴 했는데..
    생각처럼 적용이 안되더라고요..

    알려주신 소스로 다시 한번 공부 좀 해 보겠습니다.
    친절한 답변 감사드립니다. ^^

    2009.05.28 10:33 신고 [ ADDR : EDIT/ DEL : REPLY ]
  3. 안녕하세요.. 다시 찾아 왔습니다. ^^
    질문이 좀 있어서요..

    addChild( track );
    요부분부터 진도를 못나가고 있습니다.
    track가 어떻게 쓰인건지 설명 좀 부탁 드려요 될까요?
    어찌 어찌 적용은 하고 있는데..

    저 부분에서

    TypeError: Error #1034: 유형 강제 변환에 실패했습니다. flash.display::Sprite@4c95281을(를) mx.core.IUIComponent(으)로 변환할 수 없습니다.

    이런 에러 메시지가.. ㅜ.ㅜ

    2009.06.10 17:58 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 플렉스 MXML에 코딩하시나 보군요~ 뭐 위의 코드는 플래시클래스이구요~ track은 단순히 재생바입니다... 바의 길이는 디자인상 고정이고.. 핸들러의 이동속도가 전체 재생시간과 바의 길이에 비례하여 이동속도를 구하여야 하구요...에러나는 코드는 플렉스UI컴포넌트를 Sprite로 사용하려고 하여 발생한것 같습니다...

      2009.06.11 09:27 신고 [ ADDR : EDIT/ DEL ]
  4. 아~ 이 소스는 플래시였군요... 그래서..
    도움 감사드립니다. ^^
    에구.. 언제 완벽히 끝낼 수 있을런지.. ^^

    2009.06.11 10:06 신고 [ ADDR : EDIT/ DEL : REPLY ]

AS3.0 Cookbook/비디오2008. 8. 17. 12:43
비디오를 재생하기 위해서는 앞서 설명했듯이 NetConnectionNetStream 그리고 Video클래스를 통해 플래시 플레이어에서 보여주게 된다.

var netc:NetConnection = new NetConnection();
일반서버에는 보통 null값을 사용하여 서버를 열게 됩니다.
netc.connect( null );

NetConnection의 delegate가 선언되면 이를 관리할 NetStream을 생성하고
NetConnection을 생성자에 입력합니다.

var nets:NetStream = new NetStream( netc );   
- 콜백 메서드가 호출되는 객체를 반드시 지정합니다.
- 보통은 같은 클래스에 넣어서 this로 경로를 지정하고(스코프를 맞추기 위해...)
- 콜벡하는 객체에는 최소한onMetaData(Object)함수가 있어야 하고
- flv에 cuePoint가 설정되어있다면 플레이어는 onCuePoint(Object)를 호출한다.
  따라서 콜벡경로에 같이 만들어 두는 것이 좋다

var meta:Object = new Object();
meta.onMetaData = onMeta;
meta.onCuePoint = onCue;
nets.client = meta;

   
비디오 클래스를 통해 디스플레이 리스트에 등록하여 가시적으로 보여주게 한다.
var video:Video = new Video(500 , 375);

video에서 사용할 데이터(NetStream)를 연결한다.
video.attachNetStream( nets );
addChild( video );

비디오 클래스의play()는 사운드의 play처럼 사용하고자 하는 데이터를 열기도 하지만 동시에 재생을 한다.
video.play( "재생할 URL" )

이처럼 설정이 끝나면 위에서 선언한 콜벡함수들을 정의해야 한다.
private function onMeta( data:Object ):void
{
비디오의 전체 재생시간을 알려준다.
  trace( data.duration );
}

FLV파일에 큐포인트가 등록되어 있다면 아래 함수가 실행한다.

private function onCue( data:Object ):void
{
   trace("onCue");
}




   
Posted by 정윤수 버터백통

댓글을 달아 주세요

AS3.0 Cookbook/비디오2008. 8. 17. 11:40
AS3에서는 Video클래스를 제공하여 FLV파일을 제생할 수 있게 한다. 단 FMS서버가 아닌 경우 대부분 프로그래시브한 FLV를 재생한다.

비디오를 재생하기 위해서는 몇가지 클래스와 콜벡함수에 대한 처리를 해주어야 한다.
우선 비디오파일이 있는 서버와의 길을 만들기 위한 NetConnection이 필요하고 이를 관리하고 제어(비디오파일)하는 NetStream 클래스를 만들어야 한다.
이 두개의 클래스로서 외부 비디오 파일과의 연결은 준비가 된 것이다.

NetConnection을 통해 흘러오는 비디오데이터를 NetStream 이 재생을 하게되는데 실제로 화면에 보여주기 위해서는 DisplayObject를 상속받은 녀석이 있어야 한다. 그것이 Video클래스이다.

다른 로더나 사운드관련 클래스들 처럼 서버와의 통신전문 클래스인 NetConnection, 실제 파일의 움직임을 관리하는 NetStream, 이들을 통해 불러들인 데이터를 담아 보여주는 Video클래스 이렇게 3개의 클래스가 기본적으로 설정되어 있어야 하며, 비디오 파일이 NetStream을 통해 흘러들어올 때 콜벡함수 onMetaData()를 호출하게 된다. 이는 자신의 총 재생시간을 duration이라는 변수값으로 호출하기 때문에 클래스에 onMetaData를 설정해 두어야 한다. 그리고 만약 FLV에 큐포인트가 설정되어있다면 onCuePoint()함수도 설정해 두어야 한다.

onMetaData의 정보
width  :  비디오파일의 폭
height  :  비디오파일의 높이
videodatarate  :  비디오 데이터 속도
cuePoints  :  큐포인트의 배열
framerate  :  재생속도
videocodecid  :  비디오 인코딩에 사용된 코덱 버전

duration  :  전체 재생시간
audiodatarate  :  오디오의 kbps(초당 킬로바이트) 속도

canSeekToEnd  :  FLV 파일이 점진적 다운로드 무비 클립의 파일끝까지 검색할 수있는 불리언값
audiodelay  :  영상과 오디오간의 지연시간을 보정한 시간


CuePoint로 설정할 수 있는 값은 4개로 한정되어있다.
name  :  큐포인트 이름
type  :  인코딩시 선택된 event나 navigation
parameters  :  변수와 값
time  :  큐포인트 위치의 시간

parameters에값이 있다면 해당 변수명으로 한 depths 더 들어간다.


* 참고로 앞서 비디오 파일 통신을 설명한 바 있다. 참고자료 보기
Posted by 정윤수 버터백통

댓글을 달아 주세요

  1. 케이

    좋은 자료 감사합니다 퍼갈께요^^

    2008.10.08 23:22 [ ADDR : EDIT/ DEL : REPLY ]