Quart бесконечный / неопределенный потоковый ответ

Я пытаюсь создать сервер (свободно) на основе старого сообщения в блоге для потоковой передачи видео с помощью Quart.

Для потоковой передачи видео клиенту, похоже, все, что мне нужно сделать, - это найти маршрут, который возвращает генератор кадров. Однако на самом деле это приводит к постоянному повторению сообщения socket.send() raised exceptionи показывает сломанное изображение на клиенте. После этого сервер не отвечает на дальнейшие запросы.

Используя больше вдохновения из оригинального поста, я попытался вернуть Response (с помощью return Response(generator, mimetype="multipart/x-mixed-replace; boundary=frame").) Это действительно показывает видео на клиенте, но как только они отключаются (закрывают вкладку, переходят на другую страницу и т. Д.), Сервер начинает рассылать спам. socket.send() raised exception снова и не отвечает на дальнейшие запросы.

Мой код ниже.

# in app.py
from camera_opencv import Camera
import os
from quart import (
    Quart,
    render_template,
    Response,
    send_from_directory,
)

app = Quart(__name__)

async def gen(c: Camera):
    for frame in c.frames():
        # d_frame = cv_processing.draw_debugs_jpegs(c.get_frame()[1])
        yield (b"--frame\r\nContent-Type: image/jpeg\r\n\r\n" + frame[0] + b"\r\n")


c_gen = gen(Camera(0))


@app.route("/video_feed")
async def feed():
    """Streaming route (img src)"""
    # return c_gen
    return Response(c_gen, mimetype="multipart/x-mixed-replace; boundary=frame")

# in camera_opencv.py
from asyncio import Event
import cv2

class Camera:
    last_frame = []

    def __init__(self, source: int):
        self.video_source = source
        self.cv2_cam = cv2.VideoCapture(self.video_source)
        self.event = Event()

    def set_video_source(self, source):
        self.video_source = source
        self.cv2_cam = cv2.VideoCapture(self.video_source)

    async def get_frame(self):
        await self.event.wait()
        self.event.clear()
        return Camera.last_frame

    def frames(self):
        if not self.cv2_cam.isOpened():
            raise RuntimeError("Could not start camera.")

        while True:
            # read current frame
            _, img = self.cv2_cam.read()

            # encode as a jpeg image and return it
            Camera.last_frame = [cv2.imencode(".jpg", img)[1].tobytes(), img]
            self.event.set()
            yield Camera.last_frame
        self.cv2_cam.release()

1 ответ

Решение

Первоначально это было проблемой самой Quart.

После серии исправлений ошибок как в Quart, так и в Hypercorn код, указанный в сообщении, функционирует как задумано (по состоянию на 2018-11-13 гг.)

Другие вопросы по тегам