Python 使用Flask传输视频流

您所在的位置:网站首页 python读取rtsp Python 使用Flask传输视频流

Python 使用Flask传输视频流

2023-12-09 13:14| 来源: 网络整理| 查看: 265

文章目录 前言StreamingFlask实现流构建实时视频流 视频流优化

前言

最近有一项任务,将视频中目标检测的结果传输给前端。这个任务很好实现,按照实际,对每一帧的视频进行检测然后返回图像流在前端进行展示。然而上头要求不返回视频流,要的是返回检测结果。听到这项任务就纳闷,理论上只需要返回数据流,但是又感觉哪里有点说不出奇怪,于是写下这篇文章梳理整个视频流返回。本篇博客主要参考:Video Streaming with Flask和Flask Video Streaming Revisited。代码请参考:flask-video-streaming。

Streaming

在Flask中用到流的主要有以下两个应用场景:

large response 在返回的数据块较大的时候,使用流的方式生成并返回,是一种较好的解决方案。当然你也可以将返回响应写在磁盘中,然后返回一个文件flask.send_file()。但是这种情况会增加额外的I/O开销。实时数据传输 实时数据传输,如视频或者语音传输,可以使用流传输。 Flask实现流

Flask通过使用generator functions为流响应提供支持,一个generator function如下所示:

def gen(): yield 1 yield 2 yield 3

通过上面简单理解了生成器,接下来下面的实例显示了如何使用流来处理生成大型数据报表并返回:

from flask import Response, render_template from app.models import Stock def generate_stock_table(): yield render_template('stock_header.html') for stock in Stock.query.all(): yield render_template('stock_row.html', stock=stock) yield render_template('stock_footer.html') @app.route('/stock-table') def stock_table(): return Response(generate_stock_table())

在这个例子当中,返回流的响应路由需要返回一个由使用生成器函数初始化对象的Response,然后Flask负责调用生成器将结果分块发送给客户端。这样做的好处是程序当中需要生成一个很大的数据块,而通过流传输,响应返回请求不会随着你的块变大而变大。

流除了能够将将数据块大的进行分块之外,还能提供Multipart Responses。在这一方面最主要的应用场景是视频流或者音频流的返回播放。在这当中,流的一个有趣用途是让每个块替换页面的前一个块,这使得流能够在浏览器窗口中“播放”。Multipart/Response由一个包含多部分内容类型之一的标头组成,紧接着是边界标记的分割部分,每个部分都有自己的特定内容类型。以下是Multipart视频流的结构:

HTTP/1.1 200 OK Content-Type: multipart/x-mixed-replace; boundary=frame --frame Content-Type: image/jpeg --frame Content-Type: image/jpeg ...

如上所述,头的Content-Type设置为multipart/x-mixed-replace以及定义bouondary。然后包括每一帧数据,以--为前缀,并在各自行中添加边界字符串以及Content-type的标头,每个部分都可以选择包含一个Content-Length,说明有效payload的字节长度。

在了解完上面基础知识后,接下来就构建实时视频流服务器。原理比较简单,或者视频中的每一帧然后以流的方式通过Multipart/Response返回给客户端。

构建实时视频流

一个简单的FlaskWeb程序,提供Motion JPEG流,注意Motion JPEG应用广泛。这种方法延迟低,但质量不是最好的,因为 JPEG 压缩对于运动视频不是很有效。 从摄像机中获取视频帧:

from time import time class Camera(object): def __init__(self): self.frames = [open(f + '.jpg', 'rb').read() for f in ['1', '2', '3']] def get_frame(self): return self.frames[int(time()) % 3]

上面一部分代码是实例,针对没有摄像头设备的进行调试,通过在读取工程下面的图像来构建图像流。

#!/usr/bin/env python from flask import Flask, render_template, Response from camera import Camera app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') def gen(camera): while True: frame = camera.get_frame() yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') @app.route('/video_feed') def video_feed(): return Response(gen(Camera()), mimetype='multipart/x-mixed-replace; boundary=frame') if __name__ == '__main__': app.run(host='0.0.0.0', debug=True)

此应用程序定义了一个Camera负责提供帧序列的类。前端HTML内容:

Video Streaming Demonstration Video Streaming Demonstration


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3