์ด๋ฒ์ ์๋ก ์งํํ ํ๋ก์ ํธ์ ๊ธฐ๋ฅ ์ค ํ๋๋ ์ผ๊ตด ์ธ์์ผ๋ก ํ๋ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ด์๋ค
์ผ๊ตด ์ธ์ํ๋ model์ cvteam์์ ๋ฐ์์ ๋๋ ui์ ๊ธฐ๋ฅ๋ง ๊ตฌํํ๋ฉด ๋๋ ์ํฉ
main.py
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import cv2
app = FastAPI()
def generate_frames():
cap = cv2.VideoCapture(0)
while True:
success, frame = cap.read()
if not success:
break
ret, buffer = cv2.imencode('.jpg', frame)
frame = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
@app.get("/video_feed")
def video_feed():
return StreamingResponse(
generate_frames(),
media_type="multipart/x-mixed-replace; boundary=frame")
main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Live Stream</title>
</head>
<body>
<h1>Live Video Stream</h1>
<img id="video-stream" src="/video_feed" alt="Video Stream" />
</body>
</html>
์๋ฐ์คํฌ๋ฆฝํธ์์ ํน๋ณํ ์ฒ๋ฆฌ๊ฐ ํ์ํ์ง ์๊ณ , ์ด๋ฏธ์ง ํ๊ทธ์ src ์์ฑ์ ๋ฐฑ์๋ ์คํธ๋ฆฌ๋ฐ URL๋ก ์ค์ ๋ง ํ๋ฉด ์ ์๋ํ๋ค.
์ฌ๊ธฐ์ ์ถ๊ฐ๋ก ์ผ๊ตด ์ธ์ ์๋ฃ๋๋ฉด ๋ฑ๋ก๋ ์ด๋ฆ์ ๊ฐ์ด ์๋จ์ ์ ๋ฌํด๋ฌ๋ผ๋ ์์ฒญ์ ๋ฐ์๋ค.
์คํธ๋ฆฌ๋ฐ ์ด๋ฏธ์ง ์ก์ถํ๊ณ ๋ถ๋ฆฌ๋์ด์ string๋ ์๋จ์ ๋ณด๋ด๋ ค๋ฉด media type์ ์์ ํด์ผ ํ๋ค.
๊ธฐ์กด ์ฝ๋
ret, buffer = cv2.imencode('.jpg', frame)
frame = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
@app.get("/video_feed")
def video_feed():
return StreamingResponse(generate_frames(), media_type="multipart/x-mixed-replace; boundary=frame")
๋ณ๊ฒฝ ์ฝ๋
media_type = "multipart/x-mixed-replace; boundary=frame" ์ผ๋ก ์ก์ถํ๋ frame์
base24๋ก encode → 'utf-8'๋ก decodeํด์ dict์ ๋ด์์ yieldํ๊ณ
์ถ๊ฐ๋ก ์ ๋ฌํด์ผํ๋ string๋ dict์ ๋ด์์ yield ํด์ ์๋จ์ ์ ๋ฌํ๋ค.
๊ทธ๋ฆฌ๊ณ StreamResponse์ media_type์ "text/event-stream"์ผ๋ก ๋ณ๊ฒฝํด์คฌ๋ค.
ret, buffer = cv2.imencode('.jpg', img)
img = buffer.tobytes()
base64_str = base64.b64encode(img)
base64_string = base64_str.decode('utf-8')
data = { "base64": base64_string }
# yield streaming image
yield f"event: image\ndata: {json.dumps(data)}\n\n"
# yield string
data = {"name": name}
yield f"event: notification\ndata: {json.dumps(data)}\n\n"
@app.get("/video_feed")
def video_feed():
return StreamingResponse(generate_frames(), media_type="text/event-stream")
๊ทธ๋ฌ๋๋ Streaming image, String ๋ชจ๋ ์๋จ์ผ๋ก ์ ๋๊ฒจ์ฃผ๋ ๊ฒ ํ์ธํ๋ค.
์ต์ข ์ฝ๋
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import cv2
app = FastAPI()
def generate_frames():
cap = cv2.VideoCapture(0)
while True:
success, frame = cap.read()
if not success:
break
ret, buffer = cv2.imencode('.jpg', frame)
img = buffer.tobytes()
base64_str = base64.b64encode(img)
base64_string = base64_str.decode('utf-8')
data = { "base64": base64_string }
# yield streaming image
yield f"event: image\ndata: {json.dumps(data)}\n\n"
# yield string
data = {"name": name}
yield f"event: notification\ndata: {json.dumps(data)}\n\n"
@app.get("/video_feed")
def video_feed():
return StreamingResponse(generate_frames(), media_type="text/event-stream")
'๐ฉ๐ปโ๐ป > python' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[python] Fastapi ์ ํ๋ฆฌ์ผ์ด์ exe ํ์ผ๋ก ๋ฐฐํฌํ๊ธฐ (0) | 2024.11.05 |
---|---|
[python] socket ๋์ ์ฐ๊ฒฐ (1) | 2024.10.22 |
[python] TypeError: 'type' object is not subscriptable (1) | 2024.05.02 |
[python] Received response with content-encoding: gzip, but failed to decode it. (0) | 2024.02.19 |
[python] ๋ค์ด๋ฒ ์นดํ ํฌ๋กค๋ง (1) | 2024.01.30 |