리자

[펌] 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,979
17년 전 조회 4,425
17년 전 조회 1,741
17년 전 조회 3,240
17년 전 조회 1,567
17년 전 조회 3,479
17년 전 조회 5,837
17년 전 조회 1,417
17년 전 조회 2,153
17년 전 조회 1,784
17년 전 조회 1,525
17년 전 조회 2,414
17년 전 조회 2,623
17년 전 조회 1,588
17년 전 조회 2,680
17년 전 조회 3,167
17년 전 조회 1,522
17년 전 조회 1,936
17년 전 조회 3,841
17년 전 조회 4,471
17년 전 조회 1,866
17년 전 조회 1,725
17년 전 조회 2,667
17년 전 조회 1,847
17년 전 조회 3,932
17년 전 조회 1,639
16년 전 조회 1,922
17년 전 조회 2,256
17년 전 조회 2,105
17년 전 조회 3,562
17년 전 조회 1,581
17년 전 조회 2,651
17년 전 조회 1,633
17년 전 조회 1,901
17년 전 조회 7,420
17년 전 조회 1,995
18년 전 조회 4,086
18년 전 조회 2,419
18년 전 조회 2,429
18년 전 조회 2,147
18년 전 조회 2,190
18년 전 조회 2,615
18년 전 조회 3,210
18년 전 조회 5,319
18년 전 조회 2,776
18년 전 조회 2,692
18년 전 조회 2,542
18년 전 조회 1,791
18년 전 조회 2,198
18년 전 조회 5,305
18년 전 조회 3,020
18년 전 조회 2,582
18년 전 조회 3,255
18년 전 조회 2,471
18년 전 조회 2,830
18년 전 조회 5,860
18년 전 조회 2,611
18년 전 조회 2,009
18년 전 조회 2,641
18년 전 조회 1,471
18년 전 조회 9,795
18년 전 조회 4,451
18년 전 조회 3,279
18년 전 조회 1,806
18년 전 조회 3,598
18년 전 조회 2,277
18년 전 조회 3,722
18년 전 조회 5,173
18년 전 조회 3,827
18년 전 조회 2,672
18년 전 조회 2,933
18년 전 조회 2,441
18년 전 조회 2,780
18년 전 조회 1,893
18년 전 조회 3,432
18년 전 조회 2,134
18년 전 조회 2,260
18년 전 조회 2,078
18년 전 조회 3,045
18년 전 조회 1,994
18년 전 조회 2,662
18년 전 조회 3,866
18년 전 조회 4,560
18년 전 조회 2,368
18년 전 조회 2,837
18년 전 조회 4,613
18년 전 조회 2,678
18년 전 조회 1,870
18년 전 조회 3,314
18년 전 조회 3,133
18년 전 조회 3,854
18년 전 조회 2,166
18년 전 조회 2,338
18년 전 조회 1만
18년 전 조회 3,500
18년 전 조회 3,296
18년 전 조회 3,175
18년 전 조회 2,795
18년 전 조회 4,149
18년 전 조회 5,493
🐛 버그신고