我想知道如何减少我的 Tornado 视频流代码块,这样我就不会影响我的网络应用程序中的其他处理程序。
我有一些遗留代码,我在 Tornado 中使用它们来流式传输传入的 jpeg 并将它们显示为 html 页面上的视频。我的处理程序看起来像这样。它已经运行了几年,但最近我注意到它实际上是一个巨大的资源消耗者。每当有东西调用此处理程序时,所有其他请求都会急剧减慢。
class VideoAPI(tornado.web.RequestHandler):
'''
Serves a MJPEG of the images posted from the vehicle.
'''
@tornado.gen.coroutine
def get(self):
host = self.get_argument("host")
port = int(self.get_argument("port"))
ioloop = tornado.ioloop.IOLoop.current()
self.set_header("Content-type", "multipart/x-mixed-replace;boundary=--frame")
self.served_image_timestamp = time.time()
my_boundary = "--frame"
for frame in live_video_stream(host,port=port):
interval = .1
if self.served_image_timestamp + interval < time.time():
img = cv2.imencode('.jpg', frame)[1].tostring()
self.write(my_boundary)
self.write("Content-type: image/jpeg\r\n")
self.write("Content-length: %s\r\n\r\n" % len(img))
# Serve the image
self.write(img)
self.served_image_timestamp = time.time()
yield tornado.gen.Task(self.flush)
else:
yield tornado.gen.Task(ioloop.add_timeout, ioloop.time() + interval)
在我的应用程序的其他地方,我有一些计算成本较高的代码,我可以在不占用太多 CPU 的情况下运行它们。它遵循以下模式:
class Example(tornado.web.RequestHandler):
executor = ThreadPoolExecutor(3)
@tornado.concurrent.run_on_executor
def do_some_stuff(self):
"""Do something that's not asyncio-friendly, and computationally slow"""
return something
@tornado.gen.coroutine
def get(self):
result = yield self.do_some_stuff()
self.write(result)
假设第二个示例是流视频最有效的模式,我如何将视频处理程序转换为看起来更像这样?我从其他人那里继承了视频处理程序代码,但我真的不知道如何复制循环部分。例如,我应该将循环留在执行器上运行的函数中吗?我应该将其保留在 @tornado.gen.coroutine
装饰方法中吗?我应该做一些完全不同的事情吗?
最佳答案
您需要识别代码中昂贵的部分并将它们移至其他线程;将其余代码留在协程中(这是进行像 self.write
这样的 Tornado 调用所必需的)。例如,我的猜测是主要问题在于线路
img = cv2.imencode('.jpg', frame)[1].tostring()
要将其移至另一个线程(使用比 run_on_executor 装饰器更现代的 Tornado 习惯用法),请将其放入函数中并按如下方式运行:
def expensive_fn():
return cv2.imencode('.jpg', frame)[1].tostring()
img = yield ioloop.run_in_executor(None, expensive_fn)
如果问题是for frame in live_video_stream(host,port=port)
那么您需要进行更广泛的重构以摆脱生成器模式,以便可以在单独的线程中对其进行迭代。
关于python - 如何在从 Tornado 流式传输视频时减少阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60716059/