I have a Raspberry Pi 3 with a Camera (Noir) and I found on python this pi camera module. So I have now when I am starting the python script a Webserver which allows me to see throw my camera. Thats fine and cool, but now I wanted to make with some php and html a form with two buttons:
Heres my code
import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server
PAGE="""\
<?php
if(isset($_POST['submit'])){
//code to be executed
shell_exec("./start_video.sh");
}else{
//code to be executed
}
if(isset($_POST['submit2'])){
shell_exec("./stop_video.sh");
}else{
}
?>
<html>
<head>
<title>Raspberry Pi - Surveillance Camera</title>
</head>
<body>
<center><h1>Raspberry Pi - Surveillance Camera</h1></center>
<center><img src="stream.mjpg" width="1280" height="720"></center>
<form method="post" action="">
<input type="submit" name="submit" value="Start Video">
<input type="submit" name="submit2" value="Stop Video">
</form>
</body>
</html>
"""
class StreamingOutput(object):
def __init__(self):
self.frame = None
self.buffer = io.BytesIO()
self.condition = Condition()
def write(self, buf):
if buf.startswith(b'\xff\xd8'):
# New frame, copy the existing buffer's content and notify all
# clients it's available
self.buffer.truncate()
with self.condition:
self.frame = self.buffer.getvalue()
self.condition.notify_all()
self.buffer.seek(0)
return self.buffer.write(buf)
class StreamingHandler(server.BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/':
self.send_response(301)
self.send_header('Location', '/index.html')
self.end_headers()
elif self.path == '/index.html':
content = PAGE.encode('utf-8')
self.send_response(200)
self.send_header('Content-Type', 'text/html')
self.send_header('Content-Length', len(content))
self.end_headers()
self.wfile.write(content)
elif self.path == '/stream.mjpg':
self.send_response(200)
self.send_header('Age', 0)
self.send_header('Cache-Control', 'no-cache, private')
self.send_header('Pragma', 'no-cache')
self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
self.end_headers()
try:
try:
while True:
with output.condition:
output.condition.wait()
frame = output.frame
self.wfile.write(b'--FRAME\r\n')
self.send_header('Content-Type', 'image/jpeg')
self.send_header('Content-Length', len(frame))
self.end_headers()
self.wfile.write(frame)
self.wfile.write(b'\r\n')
except Exception as e:
logging.warning(
'Removed streaming client %s: %s',
self.client_address, str(e))
else:
self.send_error(404)
self.end_headers()
class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
allow_reuse_address = True
daemon_threads = True
with picamera.PiCamera(resolution='1280x720', framerate=30) as camera:
output = StreamingOutput()
#Uncomment the next line to change your Pi's Camera rotation (in degrees)
#camera.rotation = 90
camera.start_recording(output, format='mjpeg')
address = ('', 8000)
server = StreamingServer(address, StreamingHandler)
server.serve_forever()
finally:
camera.stop_recording()
I would probably use Flask to setup the server instead of a basic HTTPServer with php. Using shell scripts that get called via php and control stuff inside the server is not very elegant and might not even work.
This Hackster project might be a good starting point for streaming with flask. To start/stop the video, one (crude) possibility could be to have a variable that gets toggled inside start_video
and stop_video
routes and controls whether the video feed returns an image or not.
In order to record video at the same time as streaming it through the webserver, this might be useful.