As noted by @MatsLindh in the comments, you should rather use a more suitable protocol - such as WebSockets - than HTTP
for such a task. FastAPI/Starlette supports sending and receiving data on a websocket
(see the documentation here and here).
Below is a working example of using websockets
to send video frames from client side to server side (assuming this is your task based on your comment on 30fps
- however, the same appproach could be applied to sending other types of data). OpenCV
is used to capture the frames and websockets
library is used to connect to the WebSocket server. More details and examples on websockets and FastAPI can be found in this answer, on which the following example is based.
Working Example
server.py
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from websockets.exceptions import ConnectionClosed
import cv2
import numpy as np
app = FastAPI()
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
# listen for connections
await websocket.accept()
#count = 1
try:
while True:
contents = await websocket.receive_bytes()
arr = np.frombuffer(contents, np.uint8)
frame = cv2.imdecode(arr, cv2.IMREAD_UNCHANGED)
cv2.imshow('frame', frame)
cv2.waitKey(1)
#cv2.imwrite("frame%d.png" % count, frame)
#count += 1
except (WebSocketDisconnect, ConnectionClosed):
cv2.destroyWindow("frame")
print("Client disconnected")
client.py
from websockets.exceptions import ConnectionClosed
import websockets
import asyncio
import cv2
camera = cv2.VideoCapture(0, cv2.CAP_DSHOW)
async def main():
url = 'ws://localhost:8000/ws'
async for websocket in websockets.connect(url):
try:
while True:
success, frame = camera.read()
if not success:
break
else:
ret, buffer = cv2.imencode('.png', frame)
await websocket.send(buffer.tobytes())
await asyncio.sleep(0.03)
except ConnectionClosed:
continue # attempt reconnecting to the server (otherwise, call break)
asyncio.run(main())