为什么写入 HTTP 流会每隔几次写入暂停超过 100 毫秒?

问题描述

我正在尝试使用带有 aiohttp 的多部分流通过 http 流式传输 MJPEG 视频。

我有一个基于 this Gist by james4388 的实现。我正在尝试每 30 毫秒左右发送一个新的 JPEG 图像。循环计时显示 await mpwriter.write(response,close_boundary=False) 通常需要 0.3 毫秒,但每 3-5 次需要 150-200 毫秒。这限制了我可以达到的最大帧速率,并在我试图避免的流中引入了延迟。

使用的循环是

while True:
        _,frame = wc.read()
        if frame is None:
            continue
        with MultipartWriter('image/jpeg',boundary=boundary) as mpwriter:
            result,encimg = cv2.imencode('.jpg',frame,encode_param)
            data = encimg.tostring()
            mpwriter.append(data,{
                'Content-Type': 'image/jpeg'
            })
            await mpwriter.write(response,close_boundary=False) # 'Pauses' here once every 3-5 times
        await response.drain()

我也尝试过使用 BaseHttpServer。这在调用 self.wfile.write(jpg.tostring()) 时表现出相同的行为。

虽然我在每个部分之后调用 response.drain(),但我认为这种暂停是在底层缓冲区通过网络刷新时发生的。每个 JPEG 帧(因此多部分流的每个部分)的大小为 441kB,因此对于 30fps,我将发送 13MB/s,但目前我达到 5.3MB/s。这是在专用的测试 LAN 连接上,所以我认为带宽不是问题(另一个使用 MJPEG 流的设备达到 >15MB/s)。

使图像尺寸更小(例如使用更高的压缩率)会增加我在命中块之前可以发送的帧数,但整体块仍然存在,我的吞吐量仍然只有 4.3MB/s。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)