Node.js + Python 用WebSocket实现视频流推送
1 Node.js概述
根据百度百科的定义,Node.js是一个基于Chrome V8引擎的JavaScript运行环境,使用了一个事件驱动、非阻塞式I/O模型, 让JavaScript 成为一种不但可以运行在浏览器端,还可以运行在服务端的编程语言,它让JavaScript成为与PHP、Python、Perl、Ruby等服务端语言平起平坐的脚本语言。Node.js是单线程的,它通过事件循环(event loop)来实现并发操作,因此,编程时尽可能多使用非阻塞操作。
2 WebSocket
根据百度百科的定义,WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。因此,目前对于Web端消息推送应用,很多都采用WebSocket,它能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
3 视频流推送实现
视频流可以通过OpenCV从摄像头进行获取,视频流可以抽取出每一个帧,一般来说,如果一个视频的fps为24,那么则意味着1秒中播放24帧,而每一帧就是一副图像,因此,我们可以从视频流中抽取出图像帧,并对图像进行处理,比如大小跳转,绘制边框等,然后可以将其通过base64转换成字符串,通过WebSocket发送到服务器,而服务器则通过WebSocket协议推送到浏览器,并基于img标签进行显示。
本示例核心组件如下所示:
(1)Node.js 构建的server.js 是 WebSocket Server端;
(2)Python 构建的client.py 则获取视频流并推送base64编码后的图像到Server端;
(3)Python Flask构建的web.py,返回index.html页面,接收WebSocket协议推送过来的图像,并显示。
项目文件结构如下图所示:
下面给出server.js 核心代码,具体如下所示:
const PORT = 8168
// npm install ws
let WebSocketServer = require('ws').Server;
let wss = new WebSocketServer({
port: PORT
});
wss.on('connection', function (ws) {
console.log('Client Connected.');
ws.on('message', function (msg) {
wss.clients.forEach(function each(client) {
//console.log(client)
client.send(msg);
});
});
});
//node server.js
其中的WebSocket协议需要通过 npm install ws 进行安装。而wss.on方法可以监听客户端的连接,并通过循环客户端列表来发送数据,即client.send(msg)。下面再给出Python 构建的client.py核心代码,具体如下所示:
import asyncio
import websockets
import base64
from cv2 import cv2
import numpy as np
import configparser
#pip install websockets
capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
if not capture.isOpened():
print('no video')
quit()
ret, frame = capture.read()
encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),80]
#Send image to node server
async def send_msg(websocket):
global ret,frame
while ret:
result, imgencode = cv2.imencode('.jpg', frame, encode_param)
data = np.array(imgencode)
#img = data.tostring()
img = data.tobytes()
img = base64.b64encode(img).decode()
await websocket.send("data:image/jpeg;base64," + img)
ret, frame = capture.read()
async def main():
cf = configparser.ConfigParser()
cf.read("config.ini")
WS_HOST = cf.get("websocket", "host")
PORT = cf.get("websocket", "port")
WS_URL = 'ws://'+WS_HOST+':'+str(PORT)
print(WS_URL)
async with websockets.connect(WS_URL) as websocket:
await send_msg(websocket)
asyncio.get_event_loop().run_until_complete(main())
# python client.py
这里需要构建Python环境,且需要安装多种库,比如 pip install websockets 安装WebSocket协议库,而import cv2则需要执行pip install opencv-python 命令来安装opencv python库。同理,pip install numpy也是需要执行的。import configparser 可以解析 ini文件,其中有一些配置,如下所示:
[websocket]
host = 192.168.0.107
port = 8168
最后,给出Python Flask构建的web.py,返回index.html页面,核心代码如下所示:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.debug = True
app.run(host="0.0.0.0",port=5000)
其中需要执行pip install Flask来导入flask库,默认的路由返回templates目录下的index.html,其代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>View Video</title>
</head>
<body>
<div>
<img id="video" src="" />
</div>
<script src="/static/js/jquery-3.3.1.min.js" ></script>
<script>
let wss_url = "ws://192.168.0.107:8168/";
let ws = new WebSocket(wss_url);
ws.onopen = function(evt) {
console.log(">>> ws.onopen.");
//ws.send("Test");
};
ws.onmessage = function(evt) {
//get PromiseResult from Promise
var base64 = evt.data.text().then(
res => {
//console.log(res);
$("#video").attr("src",res);
}
)
};
ws.onclose = function(evt) {
console.log(">>> ws.onclose.");
};
</script>
</body>
</html>
至此,我们依次执行如下命令,则可以启动该示例:
node server.js
python client.py
python web.py
用浏览器打开网址 http://192.168.0.107:5000 则显示的界面如下所示:
- 点赞
- 收藏
- 关注作者
评论(0)