Issue
With the current code, I can only send the video frame to the webpage. How can I also send some text along with each frame and have it displayed.
FastAPI code
def generate_frames(cap,i):
while True:
success,frame = cap.read()
if not success:
break
else:
# Reshape image
im_arr = cv2.imencode('.jpg', frame)[1]
cv2.waitKey(50)
print(loa[i]) //text to be displayed along with image
i = i + 1
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + bytearray(im_arr) + b'\r\n')
@app.get('/video')
def video():
i = 0
cap = cv2.VideoCapture('C:\\Users\\ryanv_k78mbsh\\Desktop\\FINAL\\MovenetTest\\animation.gif')
return StreamingResponse(generate_frames(cap,i),media_type = 'multipart/x-mixed-replace; boundary=frame')
HTML code that receives and displays the video frame
<div style= "height:50px"></div>
<img src ="{{ url_for('video') }}" width="50%" />
</div>
Solution
You could use WebSockets
instead, as described in this answer (Option 2), as well as this answer and this answer, and send both the text and image bytes to the frontend.
Working Example
app.py
from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect
from websockets.exceptions import ConnectionClosed
from fastapi.templating import Jinja2Templates
import uvicorn
import asyncio
import cv2
app = FastAPI()
camera = cv2.VideoCapture(0,cv2.CAP_DSHOW)
templates = Jinja2Templates(directory="templates")
@app.get('/')
def index(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
@app.websocket("/ws")
async def get_stream(websocket: WebSocket):
await websocket.accept()
try:
while True:
success, frame = camera.read()
if not success:
break
else:
ret, buffer = cv2.imencode('.jpg', frame)
await websocket.send_text("some text")
await websocket.send_bytes(buffer.tobytes())
await asyncio.sleep(0.03)
except (WebSocketDisconnect, ConnectionClosed):
print("Client disconnected")
if __name__ == '__main__':
uvicorn.run(app, host='127.0.0.1', port=8000)
templates/index.html
<!DOCTYPE html>
<html>
<head>
<title>Live Streaming</title>
</head>
<body>
<img id="frame" src="">
<div id="textArea"></div>
<script>
let ws = new WebSocket("ws://localhost:8000/ws");
let image = document.getElementById("frame");
image.onload = function(){
URL.revokeObjectURL(this.src); // release the blob URL once the image is loaded
}
ws.onmessage = function(event) {
if (typeof event.data === 'string')
document.getElementById("textArea").innerHTML = event.data;
else
image.src = URL.createObjectURL(event.data);
};
</script>
</body>
</html>
Answered By - Chris
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.