인터넷방송 및 웹캠(Webcam) 설치 (II)

    필자 : 배철수 / 리눅스월드 발행인

 

     

    4월 호에 실린 리얼서버를 사용하는 인터넷 방송은 영상과 사운드 데이터를 스트림 형태로 실시간으로 내보내는 방식이었다. 리얼서버는 동시 사용자가 25명을 넘으면 구매를 해야 하는 상용 프로그램이라 사용에 제한이 따른다. 또 인터넷 방송을 수신하는 측도 전용 프로그램(리얼플레이어)을 설치해야 한다.

    여기에 소개하는 웹캠(Webcam)은 소스가 공개된 프리웨어이므로 누구든 자유로 사용이 가능하고 프로그램 실력만 있으면 자신의 시스템에 맞게 변경해도 된다. 또 사용자는 웹브라우저에서 볼 수 있다. 단, 초당 프레임 수가 적어 동작이 끊기는 점과 사운드는 지원하지 않는다는 점이 인터넷 방송과 다르다.

    웹서버나 또는 다른 서버에 연결된  카메라에서 캡쳐한 화상을 일정 간격으로 웹브라우저에서 지원하는 그림 파일(jpg나 gif)로 홈페이지에 올려주고 이를 사용자의 웹브라우저가 계속해서 전송을 받도록 하는게 웹캠의 원리이다. 갱신되는 그림 파일을 초당 5 프레임 정도로 높이면 거의 인터넷 방송과 같은 수준의 화질을 구현할 수 있다.

    이 글의 전개 순서는 아래와 같다.

    1) 카메라에서 캡쳐 한 화상을 그림 파일(jpg 또는 gif)로 저장하는 단계
    2) 홈페이지에 그림 파일 업로드
    3) 서버에서 사용자의 웹브라우저로 그림 파일 연속 전송 등이다.

    설치에 사용한 배포본은 데비안 2.2 이고 커널은 2.2.18이다. 그러나 배포본 및 커널은 어느 것을 사용해도 상관없다. 커널 2.4를 사용한다면 캡쳐보드 설치를 위한 드라이버가 약간 달라진다.

 

1. 카메라 설치

    처음 필요한 것은 카메라를 리눅스에 연결하기 위해 필요한 드라이버 설치이다. USB용 카메라라면 USB 지원 및 해당 카메라에 대한 드라이버가 필요하다. 캡쳐보드에 카메라를 연결한다면 캡쳐보드 드라이버만 설치하면 된다. 이 부분은 4월 호에 설명했으므로 여기서는 기본적인 내용만 설명한다.

    Bt8x8 칩을 사용하는 캡쳐보드(TV 카드)용 bttv 드라이버를 설치하려면 커널 2.2.18의 경우 http://www.strusel007.de/linux/bttv/ 사이트에서 i2c 패치를 받아 커널 소스를 패치하고 커널 컴파일시 아래 옵션을 선택해야 한다.(2.4 커널은 패치가 필요 없다.)

    Character devices  --->
    I2C support  --->
    <*> I2C support  
    <*> I2C bit-banging interfaces

    Video For Linux  --->
    <*> Video For Linux
    <M> BT848 Video For Linux

    bttv 드라이버는 커널에 들어 있으나 현재 계속해서 업데이트 되고 있으므로 http://www.strusel007.de/linux/bttv/ 사이트에서 다운받아 컴파일해 모듈로 올리는게 좋다. 컴파일은 커널 모듈 생성 이후에 해야 한다.

    bttv 모듈은 데비안은 /etc/modules에 넣으면 되고 레드햇은 /etc/rc.d/rc.modules에 아래처럼 추가한다.

    #!/bin/bash
    depmod -a
    modprobe bttv

    bttv 드라이버가 모듈로 올라와 있는지 확인하는 방법이다.

    video:/usr/src/linux# lsmod
    Module               Size       Used by
    bttv                    53564    0
    kcompat24         3648       0  [bttv]

    USB 용 카메라는 해상도나 거리 등에 제한이 있어 웹캠 용으로는 부적당하다. 캡쳐보드를 사용해서 일반 CCD 방식 카메라를 사용해야 한다. 카메라는 NTSC 방식을 사용해야 한다. 우리나라의 TV 방송방식이 NTSC 방식이기 때문이다.

 

2. 그림 파일 생성 및 홈페이지에 업로드

    카메라에서 잡은 영상을 그림 파일로 캡쳐해서 이를 홈페이지로 올려주는 프로그램은 여러 가지가 있다.
    여기서는 xawtv 에 나와 있는 webcam 프로그램을 사용한다.

    1) 파일 있는 곳

    - 위치 : http://www.strusel007.de/linux/xawtv/
    - 파일명 : xawtv_3.30.tar.gz
              ###
    xawtv 최신 버전은 3.43이다. 그런데 필자가 이 글을 쓰려고 3.43을 다운받아 데비안 2.2에서 컴파일 후 실행하는데 계속해서 임시파일 저장 부분에서 에러가 났다. 배포본 문제인가 생각해서 레드햇 6.2에서 테스트해도 마찬가지였다. 그래서 예전에 다운 받아 설치한적이 있는 3.30을 사용하니 이상이 없다. 그래서 여기서는 일단 3.30을 기준으로 설명을 한다. 3.43에서 안되는 원인은 나중에 파악되면 다른 기회에 설명하겠다.
              ###

    2) 컴파일

    데비안의 경우는 아래 두 패키지가 설치돼야 한다. 레드햇은 멀티미디어 관련 프로그램 및 development 관련 프로그램을 설치한다.

    graphics   libjpeg62-de   Development files for the IJG JPEG library [libc6]
    libs       libjpeg62      The Independent JPEG Group's JPEG runtime library [libc6]

    - tar zxvf xawtv_3.30.tar.gz
    - cd cd xawtv-3.30
    - make
    - make install

    /usr/local/bin 디렉토리에 webcam 이라는 실행 파일이 만들어 진다. 사용법은 “man webcam” 명령을 주면 나온다.

    3) .webcamrc 파일 설정

    webcam 구성 파일은 .webcamrc 이다. webcam을 실행하는 사용자의 홈 디렉토리에 이 파일이 있어야 한다.
    (부팅 때 자동 실행이라면 root(/) 디렉토리에 넣는다.)

    필자가 사용한 설정은 아래와 같다.

    [ftp]
    host    = www
    user    = webcam
    pass    = xxxxxx
    dir     = /htdocs/video
    file     = webcam.jpeg
    tmp    = uploading.jpeg
    passive = 1
    debug  = 0
    auto    = 0
    local    = 1

    [grab]
    device  = /dev/video0
    text    = “www.linuxvideo.co.kr  %Y-%m-%d %H:%M:%S”
    width   = 320
    height  = 240
    delay   = 2
    input   = 1
    norm   = 1
    rotate   = 0
    top     = 0
    left     = 0
    bottom  = 240
    right   = 320
    quality  = 80
    trigger  = 0
    once    = 0

    [설명]

    - host  = www.xxx.co.kr
    - user  =  kim
    - pass  = xxxxxx

    위의 세 옵션은 카메라가 설치된 호스트와 홈페이지가 별개의 호스트에 있을 때 필요하다. (아래의 “local” 값을 0 으로 지정한 경우) 즉, 캡쳐 한 그림파일을 ftp로 다른 서버에 위치한 홈페이지로 옮길 때 필요하다.

    홈페이지가 위치한 서버에는 ftp 서버가 설치돼야 한다. ftp가 가능하다면 서버호스팅이나 웹호스팅을 하는 경우에도 웹캠 설치가 가능하며 상대 호스트는 리눅스가 아니어도 무관하다.

    - host 에는 홈페이지가 위치한 서버의 FQDN(Fully Qualified Domain Name)을 지정한다.
    - user 에는 ftp 사용자 계정,
    - pass 에는 패스워드를 입력한다.
      ftp 로 파일을 업로드 할 때 회선 속도가 느리면 전송되는 프레임 수를 줄여야 한다.
    - dir = /htdocs/video : 그림 파일이 저장되는 디렉토리이다. 홈페이지의 html 문서나
                                     이미지가 저장되는 디렉토리를 지정한다.
    - file = webcam.jpeg : 웹브라우저에 나타나는 그림파일 이름이다.
                                     이 파일을 html 문서에 지정한다.
    - tmp = uploading.jpeg : 카메라에서 캡쳐 한 그림 파일이 하드디스크에 전부 쓰여지기 전에
                                        일시적으로 저장되는 이름이다. 그림 파일을 하드에 writing 하는
                                        동안에 웹브라우저로 전송하면 깨진 그림이 나타나므로 그림 파일
                                        이 저장되는 동안에는 일단 이 이름으로 임시로 저장하고 저장이
                                        끝나면 실제 사용되는 파일 이름(위의 “file=”에 지정된 이름)으로
                                        이름이 변경된다.

    다음의 세 옵션도 ftp로 파일을 전송하는 경우(local=0)에만 사용된다.

    - passive = 1  :  1 이면 ftp 전송시 passive 모드를 사용한다.
    - debug = 0   :  1 이면 ftp 전송 과정에서의 메시지를 stderr에 나타낸다.
    - auto = 0     :  1 이면 ftp 전송시 .netrc 파일에 지정된 내용을 사용한다.
    - local= 1     :  0 이면 ftp 프로그램으로 다른 서버로 그림파일을 업로드 한다. 1 이면                       webcam 프로그램이 설치된 동일 서버의 위의 dir에 지정된 디렉토리에
                          그림 파일을 넣는다.

    [grab]

    - device = /dev/video0 : 카메라가 연결된 video4linux 장치명이다.
                                        장치 드라이버가 설치돼야 한다.

     bttv 드라이버를 사용하는 장치의 경우 아래 메시지가 부팅 때 나타난다.

    bttv: driver version 0.7.60 loaded
    bttv: using 2 buffers with 2080k (4160k total) for capture
    bttv: Bt8xx card found (0).
    bttv0: Bt878 (rev 17) at 00:0e.0, irq: 12, latency: 32, memory: 0xe3000000
    bttv0: subsystem: bd11:1200  =>  Pinnacle PCTV  =>  card=39
    bttv0: model: BT878(Pinnacle PCTV Studio/Ra) [autodetected]
    i2c-core.o: adapter bt848 #0 registered as adapter 0.
    bttv0: i2c: checking for MSP34xx @ 0x80... not found
    bttv0: miro: id=14 tuner=2 radio=no stereo=no

    캡쳐 보드가 한 개이면 /dev/video0가 맞으나 일부 카드의 경우 video1을 사용해야 한다.

    - text = “www.linuxvideo.co.kr %Y-%m-%d %H:%M:%S”  :
       그림 파일에 들어갈 문자를 지정한다. 위의 경우에는 “www.linuxvideo.co.kr
       2001-04-21 19:41:15” 형식의 텍스트가 그림 파일에 들어간다. 영어만 가능하다.
    - width = 320 : 캡쳐 할 그림의 가로 해상도이다.(dpi) 320, 640, 384 등이 가능하다.
    - height = 240 : 캡쳐 할 그림의 세로 해상도 이다.(dpi) 240, 480, 288 등이 가능하다.
    - delay = 2    : 캡쳐 간격(초)
    - input = 1    : 비디오 장치의 포트 번호이다. 캡쳐보드에는 보통 TV 단자와 composite 단자
                          가 기본으로 있고 그 외에 VHS 단자가 있는 경우도 있다.
                          카메라는 composite1 이나 2번에 연결된다. 0 은 TV 단자 1 은 composite1
                          단자이다. 그러나 보드에 따라서는 1 외의 다른 번호도 사용된다.
                          시행착오로 알아낸다.
    - norm = 1  : 카메라가 지원하는 방송 방식이다. 0은 pal 1은 ntsc 이다.
                        우리나라는 NTSC이다. 유럽에서 수입한 카메라라면 pal 이다.
    - rotate = 0  : 그림을 90도로 회전한다. 카메라를 거꾸로 매달 때 필요하다.
    - top = 0
    - left = 0
    - bottom = 240
    - right = 320 : 캡쳐 한 그림 중 실제 사용할 부분 즉 파일에 저장될 부분을 지정한다.
                         그림 파일의 좌상단 좌표는 top=0, left=0 이다. Bottom은 height를 초과할
                         수 없다. Right는 width를 초과할 수 없다.
    - qualit

    y = 80  : jpeg 파일에서 압축율(%)을 지정한다. 100으로 지정하면 압축하지 않는다.
                 값이 작을수록 압축율이 높아 파일 크기는 적어진다. 대신 선명도가 낮아진다.
    - trigger = 0  : 1 이면 이미지 파일이 변경될 경우만 업로드 한다. 즉 카메라가 잡은 이미지가
                          이전의 이미지와 달라진 경우에만 파일을 업로드 해 준다.
    - once = 0    : 0 이면 위의 delay에 지정된 시간만큼 경과 후 계속 그림파일을 생성한다.
                         1 이면 한 번만 그림 파일을 생성한다. 0 은 테스트시 필요하다.

    4) 이제 실제로 그림 파일이 만들어 지는지 살펴보자.

    카메라는 연결하지 않아도 테스트는 가능하다. 캡쳐보드와 bttv 드라이버는 설치돼야 한다. /htdocs/video 디렉토리를 만든다. .webcamrc 에서 once 를 1 로 설정한다. .webcamrc 파일을 /root 디렉토리에 넣고 root로 로그인해 아래 명령을 준다.

           * /usr/local/bin/webcam <enter>

    아래 메시지가 나오면 정상적으로 작동하는 것이다.

    video:~# webcam
    reading config file: /root/.webcamrc
    video4linux webcam v1.3 - (c) 1998-2000 Gerd Knorr
    grabber config: size 320x240, input 1, norm 1, jpeg quality 80
    rotate=0, top=0, left=0, bottom=240, right=320
    ftp config:
      local transfer /htdocs/video/uploading.jpeg => /htdocs/video/webcam.jpeg
    “www.linuxvideo.co.kr  2001-04-22 21:32:00”
     
            /htdocs/video 디렉토리에 아래 파일이 생성되었는지 확인하라.(파일 크기는 상관없다.)

            -rw-r--r--    1 root     root         4365 Apr 22 21:32 webcam.jpeg

    위의 파일을 웹브라우저나 그림판으로 보면 아래처럼 나온다. (카메라가 연결이 안된 상태인 경우)

    바탕색이 청색이어야 하고 화면 하단에 “www.linuxvideo.co.kr 2001-04-dd 시:분:초” 글자가 나온다.
    여기까지 이상 없으면 어려운 작업은 끝났다. 나머지는 CGI 와 관련되는 부분이다.

 

3. 서버에서 사용자 웹브라우저로 그림 파일 연속 전송

    webcam 프로그램에서 .webcamrc의 once를 0으로 주면 2초 간격으로 /htdocs/video 디렉토리의 webcam.jpeg 파일이 갱신된다. 그러나 홈페이지의 html 문서에 이 그림 파일을 지정해도 사용자가 이 html 문서를 열면 그 당시의 webcam.jpeg 파일 한 개를 웹브라우저로 전송할 뿐이다.   

    웹프로토콜은 페이지의 전송이 끝나면 연결을 끊기 때문이다. 웹브라우저로 계속해서 홈페이지의 webcam.jpeg 파일을 전송하려면 다른 프로그램의 도움이 필요하다.

    가장 간단한 방법은 네트스케이프에서 가능한 Server Push 기법이다. 이는 사용자가 웹브라우저를 닫거나 다른 URL로 이동하기 전까지 동일한 페이지를 계속 재전송하게 하는 간단한 CGI이다.

    익스플로러에서는 서버푸쉬를 지원하지 않는다. 대신 클라이언트 풀이라는 방법이 있다. 연속적인 그림 파일 갱신에는 server push가 보다 낫다고 한다. 여기에는 서버푸쉬 방법만을 설명한다. 다른 방법으로는 자바 스크립트를 사용하는게 가능하다.

    아래 CGI 프로그램은 서버푸쉬를 이용해 /htdocs/video/webcam.jpeg 파일을 2초마다 한 번씩 사용자의 네트스케이프 웹브라우저로 전송한다. 이 cgi 를 홈페이지의 cgi-bin 디렉토리에 넣으면 된다.(필자는 /htdocs/cgi-bin 디렉토리에 넣었다.) 단 perl 이 설치되어 있어야 한다.(이 프로그램은 xawtv-3.30/webcam 디렉토리에 들어 있다.)

    * webcam.cgi

    #!/usr/bin/perl
    use strict;
    # config
    my $IMAGE  = “/htdocs/video/webcam.jpeg”; # 이미지 파일 위치
    my $MAXSEC = 360;       #  10분이 지나면 전송이 종료되게 함.
    ##############################################
    undef $/;
    $|=1;
    my $BO = “wrdlbrmpft”;
    my $serverpush = ($ENV{HTTP_USER_AGENT} =~ /^Mozilla/ &&
                      $ENV{HTTP_USER_AGENT} !~ /[Cc]ompatible/);
    my $start = time;
    my @st = stat($IMAGE) or die “stat $IMAGE: $!”;
    my $mtime = $st[9];
    if ($serverpush) {
            print “Content-Type: multipart/x-mixed-replace;boundary=\”$BO\“\r\n”;
            print “\r\n”;
            print “\r\n--$BO\r\n”;
    }
    for (;;) {
            # read image
            open IMG, “<$IMAGE”;
            my $image = <IMG>;
            close IMG;

    # send it
            print  “Content-Type: image/jpeg\r\n”;
            printf “Content-Length: %d\r\n”,length($image);
            print  “\r\n”;
            print $image;
            last unless $serverpush;
            # send multipart border
            if (time - $start > $MAXSEC) {
                    print “\r\n--$BO--\r\n”;
                    last;
            } else {
                    print “\r\n--$BO\r\n”;
            }

            # wait until there is a new image
            foreach my $i (1 .. $MAXSEC) {
                    sleep 1;
                    @st = stat($IMAGE);
                    if ($st[9] != $mtime) {
                            $mtime = $st[9];
                            last;
                    }
            }
    }
    exit;

    위의 cgi는 브라우저가 네트스케이프인 경우만 연속적인 화상을 전송하고 익스플로러인 경우는 정지화면을 전송한다. 익스플로러인 경우에도 연속적인 화상을 보내는 다른 CGI를 연결하려면  if ($serverpush) { ...}  다음에 else { } 문을 넣어 가능할 것이다.

 

4. webcam 프로그램 자동 실행

    웹캠 프로그램을 부팅시마다 자동으로 실행하려면 .webcamrc 파일을 root(/) 디렉토리에 넣고 데비안의 경우에는 /etc/rc.boot 디렉토리에 아래 스크립트를 만든다. (.webcamrc의 once를 0으로 해야 한다.)

    #!/bin/bash
    /usr/local/bin/webcam > /dev/null 2> /dev/null &

 

5. 램디스크 사용

    웹캠에서 webcam.jpeg 파일은 2초 간격으로 계속해서 하드디스크에 저장되므로 전체적인 시스템 속도에 영향을 준다. 리눅스는 거의 모든 작업에 하드디스크를 억세스하기 때문이다. 사용자가 로그인 하는 간단한 절차에서도 10 여개 이상의 파일이 사용된다. 즉 하드디스크를 읽는다. 또 같은 파일을 계속 하드의 같은 디렉토리에서 갱신하면 하드의 특정 섹터에 배드가 날 확률도 높다.

    따라서 웹캠을 설치할 때 webcam.jpeg 파일은 램디스크에 저장하기를 권한다. webcam.jpeg 파일은 불과 30k 바이트 수준이므로 램디스크에 넣어도 메모리를 별로 차지하지 않는다.(파일 크기는 화상 크기, 즉 width 및  height 와 압축 정도 즉 quality에 좌우된다.) 주의할 것은 램디스크 설정 부분이 웹캠 프로그램 가동 전에 이루어져야 한다는 것이다.

    아래는 램디스크 사용 절차이다.

    1) 커널을 컴파일해서 램디스크 지원을 추가한다. (또는 모듈을 올린다.)

    2) /etc/lilo.conf에 램디스크 크기를 지정한다.
    이를 지정하지 않으면 기본으로 램디스크 크기를 4 메가로 설정해 메모리 사용이 낭비되기 때문이다. 64k 정도면 충분하다.(커널 컴파일시에도 램디스크 크기를 지정할 수 있다.)

    ramdisk=64

    3) 아래 내용이 들어가는 스크립트를 만든다.
    아래의 스크립트는 웹서버(apache) 및 웹캠 프로그램보다 먼저 실행 되야 한다.

    # 램디스크를 ext2 파일시스템으로 포맷한다. 램디스크는 fdisk를 필요로 하지 않는다.
       크기는 커널 컴파일시나 lilo.conf에서 지정한다.
            /sbin/mke2fs /dev/ram0
    # 램디스크를 webcam.jpeg 파일이 저장되는 디렉토리에 마운트한다.
    # /htdocs/video 디렉토리를 미리 만들어야 놓아야 한다.
       이 디렉토리에는 다른 파일은 저장하지 않아야 한다.
            /bin/mount  /dev/ram0  /htdocs/video

    리부팅해서 램디스크가 설치되는지 확인할 것. 아래처럼 나와야 한다.

    video:/htdocs/cgi-bin# df
    Filesystem           1k-blocks    Used       Available   Use%  Mounted on
    /dev/hdc2            3004396      528116    2323664   19%    /
    /dev/ram0            57               18           36  33%    /htdocs/video

 

6. 가동

    1) /htdocs/cgi-bin 디렉토리에서 cgi 프로그램이 실행되게 httpd.conf 를 수정한다.
    DocumentRoot를 /htdocs로 지정한다.

    2) webcam.cgi를 수정한다.

    webcam.jpeg 파일 위치를 지정해야 한다.

       my $IMAGE  = “$ENV{DOCUMENT_ROOT}/video/webcam.jpeg”;

    3) /htdocs/cgi-bin 에 webcam.cgi 를 넣는다. (mode 755 )

    4) .webcamrc 파일을 “/” 에 넣는다.

    5) 리부팅해서 Apache, Webcam, Ramdisk 가 가동되는지 확인한다. 부팅시 램디스크, 웹캠, 아파치 순서로 실행 되야 한다.

    ps ax 명령을 주면 webcam 프로그램 가동 여부를 알 수 있다.

        129 ?        S      0:04 /usr/local/bin/webcam

    6) /htdocs/video 디렉토리에 webcam.jpeg 파일이 생성되는지 또 2초마다 갱신되는지 확인.

        -rw-r--r--    1 root     root        12124 Apr 23 11:15 webcam.jpeg

    7) 네트스케이프에서 http://xxx.yyy.zzz/cgi-bin/webcam.cgi 를 연결하면 아래 화면이 뜬다.
    (reload 버튼을 누르면 2초마다 화면이 갱신된다.)

            (필자의 사무실 책장을 카메라로 잡았다.)

    8) 익스플로러에서는 “다시 보기”를 눌러야 화면이 바뀐다.




▲ top

home으로...