樹莓派(4-6)網頁伺服器 flask為背景的 websocket網頁雙向通訊+視訊流顯示
阿新 • • 發佈:2020-11-14
功能
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>