基于ASGI服务器的IP摄像头(CCTV)直播流问题求助
问题描述
我使用Django、OpenCV、Daphne搭建ASGI系统,在WSGI模式下可通过StreamingHttpResponse正常在HTML中实现CCTV直播流,但切换为ASGI后该方式失效。参考网络示例调整为WebSocket方案后,HTML页面能正常建立WebSocket连接,但仍无法显示CCTV直播流,求排查建议。
排查方向与修正建议
修复前后端数据编码/解析不匹配问题
后端当前将帧字节用latin-1解码后塞进JSON,前端直接把整个JSON字符串当作base64使用,既没有解析JSON对象,也用错了编码格式:- 后端需将OpenCV编码后的buffer直接转为base64字符串,再封装成JSON发送
- 前端需先解析WebSocket收到的JSON字符串,提取
frame字段的base64值再赋值给img.src
避免阻塞ASGI事件循环
OpenCV的cap.read()是同步阻塞操作,在异步Consumer的主线程中直接执行会卡死ASGI事件循环,导致消息无法及时推送。需将帧读取操作放到线程池中异步执行。验证RTSP流读取有效性
在cap.read()后添加日志,打印ret值、frame的形状等信息,确认OpenCV是否成功从RTSP地址读取到帧数据,排除流地址错误、权限不足、网络连通性等问题。检查Daphne路由挂载
确认Daphne启动时正确加载了ASGI应用,WebSocket路由已通过websocket_urlpatterns正确注册到Django的ASGI路由中。
修正后的代码示例
consumer.py
import asyncio import cv2 import base64 import json from channels.generic.websocket import AsyncWebsocketConsumer from asgiref.sync import sync_to_async class CameraConsumer(AsyncWebsocketConsumer): async def connect(self): await self.accept() self.cap = cv2.VideoCapture("rtsp://admin:ads12345@192.168.1.65:554/") # 启动异步任务读取帧 self.task = asyncio.create_task(self.send_frames()) async def send_frames(self): while True: # 用sync_to_async把同步的read操作转成异步 ret, frame = await sync_to_async(self.cap.read)() if not ret: print("无法读取视频流") break _, buffer = cv2.imencode('.jpg', frame) # 将buffer转为base64字符串 frame_base64 = base64.b64encode(buffer).decode('utf-8') await self.send(json.dumps({'frame': frame_base64})) await asyncio.sleep(0.03) async def disconnect(self, close_code): self.task.cancel() self.cap.release()
stream.html
<!DOCTYPE html> <html> <head> <title>Camera Stream</title> <script> var socket = new WebSocket("ws://localhost:8000/ws/camera_stream/"); socket.onmessage = function(event) { // 先解析JSON对象 var data = JSON.parse(event.data); var img = document.getElementById("camera-image"); img.src = "data:image/jpeg;base64," + data.frame; }; </script> </head> <body> <img id="camera-image" src="" > </body> </html>
内容的提问来源于stack exchange,提问作者DesMon
相关产品推荐
相关产品推荐

