# Install dependencies
pip install -r requirements.txt
# Run Daphne server
daphne -b 0.0.0.0 -p 8000 config.asgi:application# Use Daphne for ASGI
daphne -b 0.0.0.0 -p 8000 config.asgi:application
# Or with Gunicorn + Uvicorn
pip install uvicorn
uvicorn config.asgi:application --host 0.0.0.0 --port 8000URL: ws://localhost:8001/ws/detect/?token=<jwt_token>
const token = "your_jwt_token_here";
const ws = new WebSocket(`ws://localhost:8001/ws/detect/?token=${token}`);
ws.onopen = () => {
console.log("Connected to detection service");
};
ws.onmessage = (event) => {
const response = JSON.parse(event.data);
console.log("Prediction:", response);
// response: {label: "Suspicious", confidence: 0.85}
// or: {label: "Normal", confidence: 0.92}
// or: {label: null, confidence: null} (collecting frames)
};
ws.onerror = (error) => {
console.error("WebSocket error:", error);
};
ws.onclose = () => {
console.log("Connection closed");
};
// Send frame for prediction
const sendFrame = (base64Image, cameraId, type = "multi") => {
ws.send(JSON.stringify({
image: base64Image,
camera_id: cameraId,
type: type // "multi", "multi15", "multi3d", "14"
}));
};
// Example usage - send multiple frames
const captureAndSend = async () => {
// Assuming you have a base64 encoded image from canvas or file input
const base64Image = "data:image/jpeg;base64,...";
sendFrame(base64Image, 1, "multi");
};import asyncio
import websockets
import json
import base64
import cv2
async def websocket_client():
token = "your_jwt_token_here"
uri = f"ws://localhost:8001/ws/detect/?token={token}"
async with websockets.connect(uri) as websocket:
print(await websocket.recv()) # Connected message
# Send frame
# Read image and convert to base64
frame = cv2.imread("sample.jpg")
_, buffer = cv2.imencode('.jpg', frame)
base64_image = "data:image/jpeg;base64," + base64.b64encode(buffer).decode()
message = {
"image": base64_image,
"camera_id": 1,
"type": "multi"
}
await websocket.send(json.dumps(message))
# Receive prediction
response = await websocket.recv()
print(json.loads(response))
# Keep connection alive and send more frames
for _ in range(10):
await websocket.send(json.dumps(message))
response = await websocket.recv()
print(json.loads(response))
asyncio.run(websocket_client()){
"image": "data:image/jpeg;base64,...",
"camera_id": 1,
"camera_name": "Front Door",
"type": "multi"
}Parameters:
image(required): Base64 encoded image withdata:image/jpeg;base64,prefixcamera_id(optional): Camera ID from databasecamera_name(optional): Camera name from databasetype(optional): Prediction model type"multi"(default): CNN-LSTM"multi15": Alternative CNN-LSTM"multi3d": 3D CNN"14": Frame buffering variant
Collecting frames:
{
"label": null,
"confidence": null
}Prediction ready:
{
"label": "Suspicious",
"confidence": 0.85
}Error:
{
"error": "Invalid image format"
}| Metric | HTTP | WebSocket |
|---|---|---|
| Connection setup | ~100ms | ~50ms (persistent) |
| Per frame | ~150ms | ~80-100ms |
| 10 frames | 1500ms | 800ms + initial |
| Overhead | Per-request | One-time |
Streaming 10+ frames per second:
- HTTP: ~1500ms overhead per 10 frames
- WebSocket: ~800ms total for streaming session
- Savings: ~40% latency reduction
Client WebSocket Connection
↓
authentication (JWT token)
↓
DetectionConsumer (async handler)
↓
predict_frame_multi (global model)
↓
Response (label + confidence only)
↓
Send back to client
No model reload per request - global model instance reused.