功能
1 完成了传输视频
2完成了网页端前后相互控制
百度网盘

链接:https://pan.baidu.com/s/1YZ6bY86LVoNMDr6PSPCGnw
提取码:pxj0
原理讲解

读取代码 flasksever.py
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import time
from flask import *
from flask_socketio import *
from camera import *
video=VideoCamera()
import time
from threading import Lock
import datetime,random #导入时间和随机数模块
import cv2
app = Flask(
__name__,
template_folder='.', # 表示在当前目录 (myproject/A/) 寻找模板文件
static_folder='', # 空 表示为当前目录 (myproject/A/) 开通虚拟资源入口
static_url_path='',
)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, async_mode=None)
thread = None
thread_lock = Lock()
import os
pathnow=os.getcwd()
pathnow=pathnow.replace('\\','/')
#print(pathnow) #获取当前工作目录路径
#print (os.path.abspath('mainPage0.html'))
HTML_PATH=pathnow
@app.route('/')
def index():
return render_template('websocket.html', async_mode=socketio.async_mode)
#传输视频
def gen(camera):
coutrec=1
while True:
coutrec=coutrec+1
socketio.emit('server_recmsg2_frame',
{'data': str(coutrec)},
namespace='/test')
frame = video.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
# 服务器每发送一次请求,video_feed被调用一次
@app.route('/video_feed')
def video_feed():
return Response(gen(video), mimetype='multipart/x-mixed-replace; boundary=frame')
# 后台线程 产生数据,即刻推送至前端
def background_thread():
count = 0
while True:
#socketio.sleep(1)
count += 1
# 获取系统时间(只取分:秒)
t = time.strftime('%M:%S', time.localtime())
socketio.emit('server_recmsg1_backthread',
{'data': [str(t), str(count+1)], 'count': count},
namespace='/test')
time.sleep(1)
@socketio.on('connect', namespace='/test')
def test_connect():
global thread
with thread_lock:
if thread is None:
thread = socketio.start_background_task(target=background_thread)
#注意如何send()和emit()分别用于无名和命名事件。
@socketio.on('client_recmsg', namespace='/test')
def test_message(message):
#emit('message', {'data': message['data']},broadcast=True) #函数内发送
print(message['data'])
if __name__ == '__main__':
socketio.run(app,'0.0.0.0',8081,debug=False)
camera.py
# camera.py
import cv2
class VideoCamera(object):
def __init__(self):
# Using OpenCV to capture from device 0. If you have trouble capturing
# from a webcam, comment the line below out and use a video file
# instead.
self.video = cv2.VideoCapture(0)
# If you decide to use video.mp4, you must have this file in the folder
# as the main.py.
# self.video = cv2.VideoCapture('video.mp4')
def __del__(self):
self.video.release()
def get_frame(self):
success, image = self.video.read()
# We are using Motion JPEG, but OpenCV defaults to capture raw images,
# so we must encode it into JPEG in order to correctly display the
# video stream.
ret, jpeg = cv2.imencode('.jpg', image)
# 对于 python2.7 或者低版本的 numpy 请使用 jpeg.tostring()
return jpeg.tobytes()
网页websocket.html
中间引用了websocket的js库,我下载到了本地,可以去网上找到对应地址,百度网盘也有这个库的离线版本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>系统监控走势图</title>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="socket.io.min.js"></script>
<script type="text/javascript" src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdn.bootcss.com/socket.io/1.5.1/socket.io.min.js"></script>
</head>
<body>
<div>
<button id="state1" >发送按钮</button> <br><br>
<a> 已发送消息:</a>
<a id="sendnews"></a><br>
<a>1服务器伴随线程发来的消息:</a>
<a id="receivenews1"></a><br>
<a>2服务器视频流主动发来的消息:</a>
<a id="receivenews"></a><br>
</div>
<br>
<a>连接状态:</a>
<div id="statemsg">正在连接...</div>
<br>
<script type="text/javascript">
// 建立socket连接,等待服务器“推送”数据,用回调函数更新图表
$(document).ready(function() {
namespace = '/test';
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace);
socket.on('connect', function(){
console.log('connected')
statemsg.innerHTML ='connected'
});
//接受话题2 F12打印消息 开启视频 主动推送消息
socket.on('server_recmsg2_frame', function(res) {
console.log(res)
document.getElementById("receivenews").innerHTML=res.data;
});
//接受话题1 F12打印消息 背后进程伴随服务器开启,不停接收后台数据
socket.on('server_recmsg1_backthread', function(res) {
console.log(res.data[0]);//后台打印
document.getElementById("receivenews1").innerHTML=res.data[0];//接收消息显示<a>
//statemsg.innerHTML = res.count;//文字状态显示<div>
});
//设置点击事件
document.getElementById("state1").onclick = function(e){
//给服务器发送消息
socket.emit('client_recmsg',{'data': 1, 'count': 1});
document.getElementById("sendnews").innerHTML="给后台发数据 'data': 1, 'count': 1"
}
});
</script>
<a>视频流</a><br>
<img src="{{ url_for('video_feed') }}" height="300" width="300" >
</body>
</html>
浙公网安备 33010602011771号