实用
https://blog.csdn.net/u012675539/article/details/53306335
第一篇 讲解原理
https://blog.miguelgrinberg.com/post/video-streaming-with-flask
第二篇 加入多线程可以直接用
https://github.com/xitu/gold-miner/blob/master/TODO1/flask-video-streaming-revisited.md
https://zhuanlan.zhihu.com/p/54292646
链接:https://pan.baidu.com/s/16iyO_XR_JhhHn184RVH6Hw
提取码:6dq6
http://shumeipai.nxez.com/2018/07/17/raspberry-pi-cam-pan-tilt-control-over-local-inter.html

树莓派+Flask实现视频流媒体WEB服务器
http://shumeipai.nxez.com/2018/07/03/video-streaming-web-server-with-flask.html
1最简单的模式
opencv
单线程


# main.py
from flask import Flask, render_template, Response
from camera import VideoCamera
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
def gen(camera):
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
@app.route('/video_feed')
def video_feed():
return Response(gen(VideoCamera()),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)

# 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()

<html>
<head>
<title>Video Streaming Demonstration</title>
</head>
<body>
<h1>Video Streaming Demonstration</h1>
<img src="{{ url_for('video_feed') }}">
</body>
</html>
简单几步实现RTMP直播
主服务器
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
dianliang_v=100
import os
from configparser import ConfigParser
import datetime
#存一个新数据
def writeconfig(time,dianliang):
conf_path = "config.ini" #配置文件路径
config = ConfigParser()
config.read(conf_path, encoding="utf-8")
#获取当前长度
secs=config.sections()
print(len(secs))
config.add_section(str(len(secs)+1))
config.set(str(len(secs)+1), '时间:', time)
config.set(str(len(secs)+1), '电量:', dianliang)
#保存修改
with open(conf_path, "w") as fw:
config.write(fw)
import time
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
pinA1=12 # 左电机1
pinA2=16 # 左电机 2
pinB1=20 # 右电机 1
pinB2=21 # 右电机 2
pin_alram=22 # 报警器
GPIO.setup(pinA1, GPIO.OUT) #设置脚为输出模式
GPIO.setup(pinA2, GPIO.OUT) #设置脚为输出模式
GPIO.setup(pinB1, GPIO.OUT) #设置脚为输出模式
GPIO.setup(pinB2, GPIO.OUT) #设置脚为输出模式
GPIO.setup(pin_alram, GPIO.OUT) #设置脚为输出模式
go_time_intever=0.2 # 运动步长(秒) 通过改时间来改每一步的运动距离
def go_ahead():
print ("go_ahead")
GPIO.output(pinA1, GPIO.HIGH) # A往前转
GPIO.output(pinA2, GPIO.LOW) #灭
GPIO.output(pinB1, GPIO.HIGH) # B往前转
GPIO.output(pinB2, GPIO.LOW) #灭
time.sleep( go_time_intever ) #延时 秒
def go_back():
print ("go_ahead")
GPIO.output(pinA1, GPIO.LOW) # A往前转
GPIO.output(pinA2, GPIO.HIGH) #灭
GPIO.output(pinB1, GPIO.LOW) # B往前转
GPIO.output(pinB2, GPIO.HIGH) #灭
time.sleep( go_time_intever ) #延时 秒
def stop():
print ("stop")
GPIO.output(pinA1, GPIO.LOW) # A停止
GPIO.output(pinA2, GPIO.LOW) #灭
GPIO.output(pinB1, GPIO.LOW) # B停止
GPIO.output(pinB2, GPIO.LOW) #灭
time.sleep( go_time_intever ) #延时 秒
def tuen_left():
print ("tuen_left")
GPIO.output(pinA1, GPIO.LOW) # A往后转
GPIO.output(pinA2, GPIO.HIGH) #灭
GPIO.output(pinB1, GPIO.HIGH) #B往前转
GPIO.output(pinB2, GPIO.LOW) #灭
time.sleep( go_time_intever ) #延时 秒
def turn_right():
print ("turn_right")
GPIO.output(pinA1, GPIO.HIGH) #A往前转
GPIO.output(pinA2, GPIO.LOW) #灭
GPIO.output(pinB1, GPIO.LOW) #B往后转
GPIO.output(pinB2, GPIO.HIGH) #灭
time.sleep( go_time_intever ) #延时 秒
#from flask import Flask, render_template, Response,request,redirect,url_for
from flask import Flask, render_template, Response,request,redirect,url_for
from camera import VideoCamera
import cv2
video=VideoCamera()
app = Flask(__name__)
@app.route('/')
def index():
return render_template('dengku.html')
@app.route('/use')
def use():
return render_template('index1.html')
@app.route('/login', methods = ["GET","POST"])
def login():
name = request.args.get("username")
password = request.args.get("userpwd")
print('待验证账户:'+name+" 待验证密码:"+password)
if name== 'admin' and password=='admin':
#return redirect(url_for('use'))
return '登录成功'
else:
return '登录失败'
@app.route('/move', methods = ["GET","POST"])
def move():
fx = request.args.get("movefx")
#print('运动方向:'+fx)
if fx=='qian':
print('前行')
go_ahead()
fx='前行'
elif fx=='hou':
print('后退')
go_back()
fx='后退'
elif fx=='zuo':
print('左转')
tuen_left()
fx='左转'
elif fx=='you':
print('右转')
turn_right()
fx='右转'
elif fx=='stop':
print('停止')
stop()
fx='停止'
else:
pass
return fx
# 各种事情处理
@app.route('/do', methods = ["GET","POST"])
def do():
ting = request.args.get("dowhat")
#拍照
if ting=="paizhao":
img = video.get_img()
cv2.namedWindow('image',0)
cv2.imshow('image',img)
cv2.waitKey(10)
cv2.imwrite('save/image.jpg', img)
ting='拍照成功'
print(ting)
elif ting=="close_alram":
ting='警报关闭'
GPIO.output(pin_alram, GPIO.LOW) #低电平
print(ting)
pass
elif ting=="open_alram":
ting='警报打开'
GPIO.output(pin_alram, GPIO.HIGH) #高电平
print(ting)
pass
elif ting=="show_etc":
ting='当前电量:'
global dianliang_v
dianliang_v=dianliang_v-1
nowTime=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
writeconfig(str(nowTime),str(dianliang_v))
ting=ting+str(dianliang_v)+"--"+str(nowTime)
print(ting)
pass
return ting
# 2添加 电量
# 3添加 config保存
def gen(camera):
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
@app.route('/video_feed')
def video_feed():
return Response(gen(video),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
app.run(host='0.0.0.0',port='8080')
相机类
# 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_img(self):
success, image = self.video.read()
return image
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()
网页
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>视频流测试</title>
</head>
<body>
<h1>视频流演示</h1>
<script type="text/javascript">
function GETmethod(msg) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
alert("登录成功!")
if(this.responseText=="登录成功"){
window.location.href="use"}
}
};
xhttp.open("GET", msg, true);
xhttp.send();
}
//button 按钮,结合onclick事件,验证和提交表单
function checkForm(){
//判断用户名是否为空
if(document.form1.username.value==""){
window.alert("用户名不能为空");
}else{
//方法一 使用form对象的submit()方法,实现参数提交。整体刷新网页,无法获取返回值做逻辑控制
//document.form1.submit();
//方法二 使用xjax提交,局部刷新网页 可以获取返回值
msg= 'login?'+'username='+document.form1.username.value +'&userpwd='+document.form1.userpwd.value
GETmethod(msg)
}
}
</script>
<form name="form1" method="get" action="login">
用户名:<input type="text" name="username" />
密码:<input type="password" name="userpwd" />
<input type="button" value="登录验证" onclick="checkForm()" />
</form>
<div id="demo">
<h1>状态提示...</h2>
</div>
</body>
</html>
浙公网安备 33010602011771号