My django server serves a video feed, as a jpeg stream, one frame at a time.
It looks like this:
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")
It's a live camera feed, so there's no end to the stream. I need it to be interrupted when the client disconnects, but so far, I can't figure out how to detect that a client disconnected.
Am I missing something?
Edit:
To eliminate anything to do with the camera, I did this:
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")
and connected to my view with curl -N http://localhost/my_app/view_cam/
. It streams the numbers, and when I stop curl with Ctrl+C, the generator just keeps running indefinitely, not noticing that the client disappeared. If I run and stop curl a few more times, I have multiple instances of my gen()
function running, which is exactly what happens with the camera.
Edit 2:
This project uses Django Channels. I just noticed that if I disable channels by commenting it out in my settings.py, the above example works perfectly. I didn't think channels was related to the problem, but apparently, it is - somehow.
The channels development server does actually detect the disconnect after 10 seconds (not immediately like the default django server), and show this:
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.
but despite the message that something was killed, gen()
keeps running, printing numbers to the terminal.
You can't according the docs:
Performance considerations Django is designed for short-lived requests. Streaming responses will tie a worker process for the entire duration of the response. This may result in poor performance.
Generally speaking, you should perform expensive tasks outside of the request-response cycle, rather than resorting to a streamed response.
https://docs.djangoproject.com/en/2.1/ref/request-response/#streaminghttpresponse-objects
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With