• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
MKT-porter
博客园    首页    新随笔    联系   管理    订阅  订阅
树莓派(4-6)网页服务器 flask为背景的 websocket网页双向通信+视频流显示

功能

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>

  

 

posted on 2020-11-14 22:21  MKT-porter  阅读(926)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3