본문 바로가기
Python

[Python] Raspberry Pi 4 카메라로 영상 스트리밍 하기

by teamnova 2023. 6. 15.

안녕하세요.

이번에는 Raspberry Pi 4 에 카메라를 연결해서 영상 스트리밍하는 예제를 진행하겠습니다.

 

운영체제는 Raspberry Pi OS (Legacy) 입니다.

 

아래 그림과 같이 카메라를 연결합니다.

 

전원을 연결하고, 설정에 들어가 카메라 소프트웨어를 활성화합니다.

Preferences -> Raspberry Pi Configuration 으로 들어가기
Interfaces에서 Camera를 Enable로 설정

 

또 다른 방법으로 터미널을 사용할 수 있습니다.

터미널에 다음 명령어를 입력하면 설정화면이 뜹니다.

sudo raspi-config

다음과 같이 진행합니다.

Interface Options 선택
Camera 선택

 

Yes 선택

 

 

설정이 완료되었으면 다음 명령어를 터미널에 입력하여 재부팅합니다.

sudo reboot

 

 

영상 스트리밍을 웹으로 접근하려면 Raspberry Pi 4의 IP주소를 알아야합니다.

다음 명령어를 입력해서 IP 주소를 출력합니다.

ifconfig

현 예제에서는 IP주소가 192.168.0.196 입니다.

 

 

다음 예제 코드를 실행합니다. 해당 예제에서는 포트 번호를 8000 으로 설정했습니다.

import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server

PAGE="""\
<html>
<head>
<title>picamera MJPEG streaming demo</title>
</head>
<body>
<h1>PiCamera MJPEG Streaming Demo</h1>
<img src="stream.mjpeg" width="640" height="480" />
</body>
</html>
"""

class StreamingOutput(object):
    def __init__(self):
        self.frame = None
        self.buffer = io.BytesIO()
        self.condition = Condition()

    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # New frame, copy the existing buffer's content and notify all
            # clients it's available
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.condition.notify_all()
            self.buffer.seek(0)
        return self.buffer.write(buf)

class StreamingHandler(server.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(301)
            self.send_header('Location', '/index.html')
            self.end_headers()
        elif self.path == '/index.html':
            content = PAGE.encode('utf-8')
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.send_header('Content-Length', len(content))
            self.end_headers()
            self.wfile.write(content)
        elif self.path == '/stream.mjpeg':
            self.send_response(200)
            self.send_header('Age', 0)
            self.send_header('Cache-Control', 'no-cache, private')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
            self.end_headers()
            try:
                while True:
                    with output.condition:
                        output.condition.wait()
                        frame = output.frame
                    self.wfile.write(b'--FRAME\r\n')
                    self.send_header('Content-Type', 'image/jpeg')
                    self.send_header('Content-Length', len(frame))
                    self.end_headers()
                    self.wfile.write(frame)
                    self.wfile.write(b'\r\n')
            except Exception as e:
                logging.warning(
                    'Removed streaming client %s: %s',
                    self.client_address, str(e))
        else:
            self.send_error(404)
            self.end_headers()

class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
    allow_reuse_address = True
    daemon_threads = True

with picamera.PiCamera(resolution='640x480', framerate=24) as camera:
    output = StreamingOutput()
    camera.start_recording(output, format='mjpeg')
    try:
        address = ('', 8000)
        server = StreamingServer(address, StreamingHandler)
        server.serve_forever()
    finally:
        camera.stop_recording()

 

웹 브라우저에서 아래 주소를 입력합니다. IP주소 + 포트번호

http://192.168.0.196:8000

 

결과는 아래와 같습니다.