리자

[펌] RED5 파헤치기

RED5의 RTMP 프로토콜을 이용하면 NetStream의 데이타를 flv로 저장할 수 있습니다.

먼저 RED5의 샘플에서 제공되는 as2.0 소스를 보여드리겠습니다.

/*
Author: John Grden
email: neoRiley@gmail.com

This sample is a basic recorder.  It saves the stream to the webapps/oflaDemo/streams folder and plays
it back once you click the stop button.
*/

import mx.utils.Delegate;

// create basic netConnection object
var nc:NetConnection = new NetConnection();

// connect to the local Red5 server
nc.connect("rtmp://localhost/oflaDemo");

// create the netStream object and pass the netConnection object in the constructor
var ns:NetStream = new NetStream(nc);

// get references to the camera and mic
var cam:Camera = Camera.get();
var mic:Microphone = Microphone.get();

// setup some simple settings with the cam and mic for quality
setupCameraMic();

// we store the last saved recording so we can play it back when stop is clicked
var lastVideoName:String = "";

// listen for the button clicks
playButton.addEventListener("click", Delegate.create(this, playClick));
stopButton.addEventListener("click", Delegate.create(this, stopClick));

function playClick():Void
{
        // This FLV is recorded to webapps/oflaDemo/streams/ directory
        // attach cam and mic to the NetStream Object
        ns.attachVideo(cam);
        ns.attachAudio(mic);

        // attach the cam to the videoContainer on stage so we can see ourselves
        videoContainer.attachVideo(cam);

        // create a random number to store a unique name
        lastVideoName = "red5RecordDemo_" + random(getTimer());
        ns.publish(lastVideoName, "record");

        // disable the playbutton
        playButton.enabled = false;

        // enable the stop button
        stopButton.enabled = true;
}

function stopClick():Void
{
        // close the netStream object
        ns.close();

        // clear the videoContainer
        videoContainer.attachVideo(null);
        videoContainer.clear();

        // enable the playbutton
        playButton.enabled = true;

        // disable the stop button
        stopButton.enabled = false;

        // play the recording back
        playLastVideo();
}

function playLastVideo():Void
{
        // attach the netStream object to the video object
        videoContainer.attachVideo(ns);

        // play back the recorded stream
        ns.play(lastVideoName);
}

function setupCameraMic():Void
{
        // setup cam
        cam = Camera.get();
        // setting dimensions and framerate
        cam.setMode(320, 240, 30);
        // set to minimum of 70% quality
        cam.setQuality(0,70);

        // setup mic
        mic = Microphone.get();
        mic.setRate(44);
}


소스 분석까지 할 것도 없는 소스긴 한데
비디오를 안해보신분들은 모를 수도 있으니까 한마디 하자면

var nc:NetConnection = new NetConnection();

// connect to the local Red5 server
nc.connect("rtmp://localhost/oflaDemo");

// create the netStream object and pass the netConnection object in the constructor
var ns:NetStream = new NetStream(nc);

사실 이거면 as2.0에서는 끝나는겁니다.
나머지는 부수적인 것들입니다.

NetConnection객체를 만들고 접속을 시도합니다. 여기서는 rtmp 프로토콜로 접속을 하게 됩니다.
끊기전까지는 계속 연결이 유지 되는 프로토콜입니다.
그리고 NetStream의 생성자에 NetConnection 만 물려주면 이제 끝나는겁니다.
스트림으로 데이타가 오고갈 수 있는 상태가 된거죠.
여기 부수적으로 캠을 붙이고, 저장하기 위해 publish라는걸 하고 뭐 그게 답니다.

만약 비디오쪽 코딩을 해본적이 없는 관계로 내용을 잘 모르셔도, 이 소스 대로만 하면 문제가 없습니다.
분석할만한 것도 없는 그냥 API의 나열입니다.

문제는 as3.0 입니다.

플래시 레퍼런스에도 없고, 왠만해선 찾을기도 힘든 에러와 예외가 무지 발생합니다.
특히 보도 못한 onBWDone() 이라는게 계속 뜨면서 제가 3일 삽질한 원인을 제공했습니다.
짜증이 슬슬 밀려오면서 오기를 같이 모시고 오더군요.

샘플에서 as3.0으로 된 소스는 제공되지 않고, 제대로 된 소스도 구할 수 없었던 것도 이유입니다.
일단 국내 검색엔진에서 검색되는건 없고 플렉스컴포넌트 카페에서 어떤분이 질문을 하셨던데
제대로된 소스는 역시 없더군요.

구글에서도 찾기 힘들어서 미국야후 전전긍긍하다가 이렇게 해보라는 글이 있길래
해봤더니 된겁니다. 역시 제대로된 소스는 외국검색엔진에서도 찾기 힘들었습니다 -_-
내가 정보검색력이 딸리는건지 원.......

암튼 시작 합니다.

소스는 나중에 보여드리고 어떻게 해야 예외와 에러 발생을 피할 수 있는지에 대해
설명을 할께염.

코드 구성 순서대로~

conn = new NetConnection();
conn.client = this;
conn.addEventListener(NetStatusEvent.NET_STATUS, netStatus_handler);
conn.addEventListener(SecurityErrorEvent.SECURITY_ERROR, security_handler);

conn.objectEncoding = ObjectEncoding.AMF0;
conn.connect(connURL);

자 먼저 커넥션 하는 부분입니다.
넷커넥션 객첼르 만들고 리스너를 꼭 해줘야 합니다. 안그러면 예외 발생합니다.
무슨 예외 상황을 방지해야 하는지는 레퍼런스에 잘 나와있더라구요.
그리고 ObjectEncoding의 AMF0 이라고 나왔는데
AMF 라는건 ActionSript Message Format 입니다. 스트림을 통해 왔다갔다할 이진데이타의 포멧을
말하는데, AMF0은 as1.0이나 2.0이고 AMF3은 as3.0이랍니다.
일단 디폴트값이 있기 때문에 안해줘도 되긴 합니다.
그리고 커넥션을 겁니다.

여기서 connURL 에는 RED5 설치값인
private var connURL:String = "rtmp://localhost/oflaDemo";
이렇게 잡혀 있습니다.

as2.0에서는 다음에 그대로 NetStream을 연결하면 되지만, as3.0에서는 알 수 없는
예외가 쭉 듭니다. 사실 이게 제가 삽질한 부분의 가장 큰 부분이었네요.
3.0에서는 커넥션메서드를 쓰고, 커넥션이 완료 된 후에 NetStream을 연결해야 합니다.
안그러면 예외 쭉 뜹니다.

private function netStatus_handler(evt:NetStatusEvent):void
{
        var info:Object = evt.info;
        // 커넥션이 성공적으로 연결되면
        trace(info.code);
        if (info.code == "NetConnection.Connect.Success") {
                trace("Successful connection");
                connectStream();
                connectCam();
        }
}

뭐 이런식으로 핸들러로 들어온 이벤트의 내용에 커넥션 성공 메시지가 있는데
이걸 확인해서 다음으로 넘어가면 됩니다.

private function connectStream():void
{
        stream =  new NetStream(conn);
        stream.addEventListener(NetStatusEvent.NET_STATUS, netStatus_handler);
        stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, async_error_handler);
}

스트림역시 필요한 리스너를 걸어줘야 합니다. 합니다. 안그러면 예외없이 예외가 쭉 듭니다.
스트림에는 조금전에 만든 커넥션 객체를 넣어주면 됩니다.

private function connectCam():void
{
        // 캠 객체를 만들고 비디오에 연결합니다.
        var cam:Camera = Camera.getCamera();
        cam.setMode(320, 240, 30, true);
        cam.setQuality(0, 80);

        // 마이크로폰 객체
        var mic:Microphone = Microphone.getMicrophone();
  var myVideo:Video = getChildByName("myVideo") as Video;

        stream.attachCamera(cam, -1);
        stream.attachAudio(mic);
        myVideo.attachCamera(cam);
}

이제 캠과 연결 하는데, 캠을 화면에 표시하기 위해 myVideo에 넣는거고,
stream을 통해 데이타 전송을 해야하기 때문에 스트림에도 캠객체를 넣습니다.

주의하실건 Camera 객체는 new Camera로 하시면 작동이 안된다는거
Camera.getCamera() 하셔야 합니다. 마이크도 마찬가지구요.
myVideo 는 플래시 IDE의 Stage에 놓여져 있는 비디오객체구요.
스테이지에 놓여있는 참조를 얻기 위해 저런 형태로 차일드를 가져왔습니다.

자 이제 여기까지 해서 실행을 하면 일단 화면에 캠이 나옵니다.
이제 저장을 해봐야죠.

private function replay_handler(evt:MouseEvent):void
{
        var myVideo:Video = getChildByName("myVideo") as Video;
        myVideo.attachNetStream(stream);
        stream.play("hihihi");
}
private function end_handler(evt:MouseEvent):void
{
        trace("레코딩 끝");
        stream.close();

}
private function start_handler(evt:MouseEvent):void
{
        trace("레코딩 시작");
        stream.publish("hihihi", "record");

}

화면에 버튼이 3개 놓여져 있는데
녹화시작, 녹화끝, 저장된비됴 보기

이렇게 3개 입니다.
위의 핸들러가 대응되구요. 서버에 레코딩은 그냥 .publish("파일명", "record");
이렇게 하시면 끝납니다.
publish의 두번째 파라메터는3가지 형태가 있는데
"live" 는 브로드캐스팅 목적,
"record"는 서버에 flv로 저장하려는 목적,
"append"는 record와 비슷하지만, record는 파일을 오버라이드 하고, append는 이어서 붙입니다.

이렇게 녹화가 끝나면 stream.close()해서 스트림을 끝냅니다.
그리고 attachNetStream해서 스트림객체를 비디오에 넣고, play에다가 파일명을 넣어주면
그대로 플레이가 됩니다.

그러면 flv는 어디 저장이 되느냐
c:\Program Files\Red5\webapps\oflaDemo\streams\
여기 저장이 됩니다.

긴 글 읽느라고 고생하셨쎄여

여까징 히히
소스 첨부합니다.



 
]]> Fri, 26 Oct 2007 05:13:07
|

댓글 2개

으아~ 액션스크립트네요....어렵다.

stream.play

플래이는 이미 있는 명령어죠.

증말 어렵다... 포기..ㅋㅋ
아주 간단한건데..;;
댓글을 작성하시려면 로그인이 필요합니다.

프로그램

+
제목 글쓴이 날짜 조회
17년 전 조회 2,995
17년 전 조회 4,441
17년 전 조회 1,755
17년 전 조회 3,251
17년 전 조회 1,578
17년 전 조회 3,495
17년 전 조회 5,847
17년 전 조회 1,429
17년 전 조회 2,168
17년 전 조회 1,799
17년 전 조회 1,541
17년 전 조회 2,426
17년 전 조회 2,637
17년 전 조회 1,602
17년 전 조회 2,693
17년 전 조회 3,183
17년 전 조회 1,534
17년 전 조회 1,952
17년 전 조회 3,854
18년 전 조회 4,490
18년 전 조회 1,880
18년 전 조회 1,742
18년 전 조회 2,680
18년 전 조회 1,860
18년 전 조회 3,945
18년 전 조회 1,654
16년 전 조회 1,938
18년 전 조회 2,267
18년 전 조회 2,119
18년 전 조회 3,577
18년 전 조회 1,592
18년 전 조회 2,665
18년 전 조회 1,649
18년 전 조회 1,918
18년 전 조회 7,435
18년 전 조회 2,005
18년 전 조회 4,099
18년 전 조회 2,430
18년 전 조회 2,438
18년 전 조회 2,163
18년 전 조회 2,205
18년 전 조회 2,628
18년 전 조회 3,223
18년 전 조회 5,332
18년 전 조회 2,791
18년 전 조회 2,708
18년 전 조회 2,561
18년 전 조회 1,807
18년 전 조회 2,213
18년 전 조회 5,322
18년 전 조회 3,034
18년 전 조회 2,596
18년 전 조회 3,268
18년 전 조회 2,489
18년 전 조회 2,843
18년 전 조회 5,879
18년 전 조회 2,624
18년 전 조회 2,021
18년 전 조회 2,656
18년 전 조회 1,483
18년 전 조회 9,807
18년 전 조회 4,463
18년 전 조회 3,295
18년 전 조회 1,819
18년 전 조회 3,610
18년 전 조회 2,293
18년 전 조회 3,735
18년 전 조회 5,185
18년 전 조회 3,843
18년 전 조회 2,681
18년 전 조회 2,947
18년 전 조회 2,455
18년 전 조회 2,795
18년 전 조회 1,905
18년 전 조회 3,450
18년 전 조회 2,149
18년 전 조회 2,274
18년 전 조회 2,091
18년 전 조회 3,062
18년 전 조회 2,009
18년 전 조회 2,673
18년 전 조회 3,878
18년 전 조회 4,573
18년 전 조회 2,381
18년 전 조회 2,855
18년 전 조회 4,626
18년 전 조회 2,695
18년 전 조회 1,884
18년 전 조회 3,329
18년 전 조회 3,146
18년 전 조회 3,868
18년 전 조회 2,178
18년 전 조회 2,350
18년 전 조회 1만
18년 전 조회 3,519
18년 전 조회 3,311
18년 전 조회 3,189
18년 전 조회 2,809
18년 전 조회 4,164
18년 전 조회 5,510