0

How can I have a stream like rtsp, that is accesible in a program on another computer?

asked Dec 11, 2020 at 20:54
2

3 Answers 3

1

I solved the problem by using the following code from here.

import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server
PAGE="""\
<html>
<head>
<title>picamera MJPEG streaming demo</title>
</head>
<body>
<h1>PiCamera MJPEG Streaming Demo</h1>
<img src="stream.mjpg" width="640" height="480" />
</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:
 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='640x480', framerate=24) as camera:
 output = StreamingOutput()
 camera.start_recording(output, format='mjpeg')
 try:
 address = ('', 8000)
 server = StreamingServer(address, StreamingHandler)
 server.serve_forever()
 finally:
 camera.stop_recording()

Now I have a constantly updating mjpg-file at a local server and I can e.g. refer to the mjpg link (something like http://raspberrypi:8000/stream.mjpg) in a html/node/electron application from somewhere else, which is exactly what I wanted. First I thought it would be better to do it via rtsp or some streaming protocol, but it turned out, that the html/mjpg way has actually much less delay (almost zero being streamed over local network) than the rtsp way (maybe 3 seconds).

Cheers

answered Dec 15, 2020 at 18:33
0

If both the Pi and the computer are on the same network, this can easily be done using ffmpeg, to both capture the stream from the camera and broadcast it over the network.

answered Dec 12, 2020 at 0:46
0

I send a stream of JPEG files using zmq which is a kind of wrapper over sockets that handles most of the ugly for you. It's not a standard protocol though.

from picamera import PiCamera
import io
import zmq
context = zmq.Context()
socket = context.socket(zmq.PUB)
# CONFLATE=1 disables the send queue so it will drop frames instead of creating latency.
socket.setsockopt(zmq.CONFLATE, 1)
socket.bind("tcp://*:12103")
camera = PiCamera()
camera.resolution = (320, 240)
camera.framerate = 10
camera.exposure_mode = 'sports'
camera.rotation = 0
stream = io.BytesIO()
for _ in camera.capture_continuous(stream, 'jpeg', use_video_port=True):
 stream.truncate()
 stream.seek(0)
 socket.send(stream.read())
 stream.seek(0)

At the receiving end:

import zmq
context = zmq.Context()
video_socket = .context.socket(zmq.SUB)
video_socket.setsockopt(zmq.CONFLATE, 1)
video_socket.setsockopt(zmq.SUBSCRIBE, b"")
video_socket.connect("tcp://192.168.1.2" + ":12103")
def get_image():
 # Read the latest image. None if there are no new images since the last read.
 if video_socket.poll(timeout=0) == zmq.POLLIN:
 return video_socket.recv()
 else:
 return None

You can also use raspivid to streams video from the camera without writing your own code.

answered Sep 13, 2021 at 2:21

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.