flask上传视频到服务器,flask传输文件
Flask是一个由Python实现的Web开发微框架。怎么用它传输视频数据流?Flask应用程序能够通过将大型请求划分为小数据块来高效地提供数据。
什么是流媒体?
流媒体是一种服务器以数据块的形式响应请求的技术。我能想到这项技术有用的一个原因:
反响很大。对于非常大的响应,内存中收集的响应只返回给客户端,效率很低。另一种方法是将响应写入磁盘,然后使用flask.send_file()返回文件,但这增加了I/O的组合,假设数据可以分块生成,那么以小数据块的形式提供对请求的响应是更好的解决方案。
实时数据。对于某些应用程序,需要请求返回的数据来自实时数据源。
使用Flask实现流式传输
Flask通过使用生成器函数为流式响应提供了本机支持。生成器是一个特殊的函数,可以中断和恢复。考虑以下函数:
defgen():
产量1
产量2
Yield3这是一个分三步运行的函数,其中每一步都返回值。描述如何实现生成器超出了本文的范围,但是如果您有点好奇,下面的shell会话将向您展示如何使用生成器:
x=gen()
x
generator object= gen= at= 0x7f 06f 3059 C30=
x.next()
一
x.next()
2
x.next()
3
x.next()
回溯(mostrecentcalllast):
文件 stdin ,第1行,在模块中
在这个简单的例子中,你可以看到一个生成器函数可以依次返回多个结果。Flask使用生成器函数的特性来实现流式传输。
以下示例显示了流式处理如何生成大型数据表,而不必将整个表放入内存:
fromflaskimportResponse,render_template
fromapp.modelsimportStock
defgenerate_stock_table():
yield render _ template( stock _ header . html )
forstockkinstock . query . all():
yield render _ template( stock _ row . html ,stock=stock)
yield render _ template( stock _ footer . html )
@app.route(/stock-table )
defstock_table():
return response(generate _ stock _ table())在这个例子中,你可以看到Flask和generator函数是如何协同工作的。返回流响应的路由需要返回一个由生成器函数初始化的响应对象。Flask然后调用生成器,并将结果分块发送给客户机。
对于这个特定的示例,如果您假设Stock.query.all()返回的数据库查询结果是一个迭代器,那么您可以一次生成一个可能很大的表的一行,因此无论查询中有多少个字符,Python进程中的内存消耗都不会因为响应字符串变大而增加。
多部分响应
>上文提到了表的例子以小块的形式生成一个传统网页,各个的部分连接成最后的结果。对于如何生成较大的响应这是一个很好的例子,但更令人激动的事情是处理实时数据。
使用流式传输的一个有趣的应用是使用每个块来替换原来页面中的地方,这能使流在浏览器窗口中形成动画。利用这种技术,你可以让流中每个数据块成为一个图像,这给你提供了一个运行在浏览器中的很酷的视频输入信号!
实现就地更新的秘密是使用多部分响应。多部分响应由一个报头(header)和很多部分(parts)组成。报头包括多部分中的一种内容类型,后面的部分由边界标记分隔,每个部分中含有自身部分中的特定内容类型。
对于不同的需求,这里有一些多部分内容类型。对于具有流式传输的,每个部分替换先前部分必须使用multipart/x-mixed-replace内容类型。为了帮助你了解它到底是什么样子的,这里有一个多部分视频流传输的响应结构:
HTTP/1.1200OK
正如你上面看到的,这个结构非常简单。主要的Content-Type头被设为multipart/x-mixed-replace,同时边界标记也被定义。然后每个部分中包括,有两个短横线的前缀,及这行上的边界字符串。每个部分有自己的Content-Type头,并且每个部分可以可选地包括一个说明所在部分有效载荷的字节长度的Content-Length头,但至少对图像浏览器而言,能够处理没有长度的流。
建立一个实时视频流媒体服务器
这篇文章中已经有足够的理论,现在是时候来建立一个将实时视频流式传输到Web浏览器的完整应用。
这里有很多方法将视频流式传输到浏览器,并且每个方法都有其优点和缺点。与Flask流特征协同工作的一个好方法是流式传输独立的JPEG图片序列。这就是动态JPEG。这被用于许多IP监控摄像机。这种方法具有较短的延迟时间,但传输质量并不是最好的,因为对于动态影像而言,JPEG压缩不是非常有效。
下面你可以看到一个非常简单但完整的Web应用。它可以提供一个动态JPEG流传输:
#!/usr/bin/envpython
这个应用导入一个Camera类来负责提供帧序列。在这个例子中,将camera控制部分放入一个单独的模块是一个很好的主意。这样,Web应用会保持干净、简单和通用。
该应用有两个路由(route)。/路由为主页服务,被定义在index.html模板中。下面你能看到这个模板文件中的内容:
<title>VideoStreamingDemonstration</title>
这是一个简单的HTML页面,只含有一个标题和图像标签。注意这个图像标签的src属性指向这个应用的第二个路由,这就是魔法发生的地方。
/video_feed路由返回流式响应。因为这个流返回要被展示在web页面上的图像,在图像标签的src属性中,URL指向这个路由。因为大多数/所有浏览器支持多部分响应(如果你找到一个不支持这个的浏览器,请告诉我),浏览器会通过显示JPEG图像流自动保持图像元素的更新。
在/video_feed路由中使用的生成器函数叫gen(),将Camera类的一个实例作为其参数。mimetype参数设置如上所示,并具有multipart/x-mixed-replace的内容类型和设为"frame"的边界字符串。
gen()函数进入一个循环,其中连续的从camera返回帧作为响应块。如上所示,这个函数通过调用camera.get_frame()方法要求camera提供帧,然后生成帧,使用image/jpeg内容类型将该帧格式化为响应块。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。