Skip to content

Instantly share code, notes, and snippets.

@exelban
Last active February 14, 2024 05:08
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save exelban/c4dd0bf1856ddafb0899859bc66bbfc5 to your computer and use it in GitHub Desktop.
Save exelban/c4dd0bf1856ddafb0899859bc66bbfc5 to your computer and use it in GitHub Desktop.
Streaming video from Raspberry Pi camera via WebSockets.
import io
import socket
import struct
import time
import picamera
import argparse
import logging
########################################################################################################################
logging.basicConfig(level=logging.INFO, datefmt='%m/%d/%Y %I:%M:%S %p', format='%(asctime)s - %(name)s - %(message)s')
########################################################################################################################
width = 640 # Frame width
height = 480 # Frame height
fps = 30 # Camera FPS
ip = "192.168.1.222" # WebSocket (computer) server ip address
port = 2281 # WebSocket (computer) server port
vflip = 1 # Flip frame vertically (0-False, 1-True)
hflip = 0 # Flip frame horizontally (0-False, 1-True)
timeout = 1 # Timeout for camera warmup in seconds
########################################################################################################################
parser = argparse.ArgumentParser(description='Streaming video from Raspberry Pi.')
parser.add_argument("-width", type=int, default=width, help="Width of frame.")
parser.add_argument("-height", type=int, default=height, help="Height of frame.")
parser.add_argument("-fps", type=int, default=fps, help="FPS from cam.")
parser.add_argument("-ip", type=str, default=ip, help="WebSocket (computer) server ip address.")
parser.add_argument("-port", type=int, default=port, help="WebSocket (computer) port.")
parser.add_argument("-vflip", type=int, default=vflip, help="Flip frame vertically.")
parser.add_argument("-hflip", type=int, default=hflip, help="Flip frame horizontally.")
parser.add_argument("-timeout", type=int, default=timeout, help="Timeout for camera warmup in seconds.")
args = vars(parser.parse_args())
########################################################################################################################
while True:
try:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((args["ip"], args["port"]))
connection = client_socket.makefile('wb')
logging.info("Connected to server successfully.")
with picamera.PiCamera() as camera:
logging.info("Starting broadcast to "+str(args["ip"])+".")
vflipV = True if args["vflip"] == 1 else False
hflipV = True if args["hflip"] == 1 else False
camera.vflip = vflipV
camera.hflip = hflipV
camera.resolution = (args["width"], args["height"])
camera.framerate = args["fps"]
time.sleep(args["timeout"])
start = time.time()
stream = io.BytesIO()
try:
for foo in camera.capture_continuous(stream, 'jpeg', use_video_port=True):
connection.write(struct.pack('<L', stream.tell()))
connection.flush()
stream.seek(0)
connection.write(stream.read())
stream.seek(0)
stream.truncate()
connection.write(struct.pack('<L', 0))
finally:
pass
except BrokenPipeError:
time.sleep(args["timeout"])
logging.error("Cant send frame to "+str(args["ip"])+" and reconnect for "+str(args["timeout"])+"s.")
except ConnectionRefusedError:
time.sleep(args["timeout"])
logging.error("Cant connect to server, retry for "+str(args["timeout"])+"s.")
else:
break
@Arnold1
Copy link

Arnold1 commented Mar 15, 2023

hi would that also work with Raspberry Pi module 3? how to restrict the streaming to 30 seconds only?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment