当客户端断开连接时,如何停止Django中的StreamingHttpResponse?

8

我的Django服务器提供视频流服务,作为一帧帧的JPEG流。

它看起来像这样:

class VideoCamera():
    def __init__(self):
        # code

    def get_frame(self):
        # code
        return frame

def gen(camera):
    while True:
        yield camera.get_frame()

def view_cam(request):
    return StreamingHttpResponse(gen(VideoCamera()), content_type="multipart/x-mixed-replace;boundary=frame")

这是一个实时摄像头视频流,因此没有结束点。我需要在客户端断开连接时中断它,但到目前为止,我无法找出如何检测客户端已断开连接。

我是否遗漏了什么?

编辑:

为消除与摄像头有关的任何问题,我做了以下操作:

def gen():
    for i in range(1000):
        time.sleep(1)
        print(i)
        yield i

def view_cam(request):
    return StreamingHttpResponse(gen(), content_type="multipart/x-mixed-replace;boundary=frame")

通过 curl -N http://localhost/my_app/view_cam/ 连接到我的视图。该命令会实时地输出数字,当我使用 Ctrl+C 停止 curl 时,生成器却继续无限运行,没有注意到客户端已经断开。如果我再运行和停止几次 curl,就会有多个 gen() 函数正在运行,这正是相机发生的情况。

编辑 2:

该项目使用 Django Channels。我刚刚注意到,如果我在 settings.py 中注释掉 channels,则上面的例子可以完美地工作。我之前并没有认为 channels 与这个问题有关,但显然它是有关的。

channels 开发服务器确实会在10秒后检测到断开连接(不像默认的 django 服务器那样立即检测),并显示以下内容:

Application instance call() running at /home/pi/paperless_clipboard/venv3/lib/python3.5/site-packages/channels/http.py:213> wait_for=._call_check_cancel() at /usr/lib/python3.5/asyncio/futures.py:452, Task._wakeup()]>> for connection took too long to shut down and was killed.

尽管出现了某些被杀死的信息,gen() 仍然会继续运行,并输出数字到终端。


1
在使用django channels时,我似乎在生产环境中遇到了问题。我看到一个失控的进程占用了大量的CPU资源,并且它最后处理的请求是通过django channels向客户端返回StreamingHttpResponse。你是否曾经成功地使用StreamingHttpResponse和django channels?或者你只是决定禁用django channels? - Sachin Rekhi
1
我已经有一段时间没有处理这个问题了,但是如果我回忆起来的话,我好像从来没有解决过这个问题。我想我只是通过使用通道websocket来返回相机帧而不是StreamingHttpResponse()来绕过它。 - John
嗨@John,你能分享一下你如何使用OpenCV返回帧而不是StreamingHttpResponse()的示例吗? - Remy
1个回答

1

似乎在没有启用django channels的情况下完美地工作。流式响应被中断,类的__del__方法被运行,这正是我所希望的。我只是不确定为什么启用了channels后它就无法工作。 - John

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接