Te mostramos el código en Python y la configuración necesaria para hacer streaming de video con el Módulo de Cámara de Raspberry Pi. Esto es posible con todos los modelos que tengan el puerto de conexión de la cámara.
- Los modelos Raspberry Pi 3, 4 Model B
- El modelo más pequeño, la Raspberry Pi Zero W
Configurar la Raspberry Pi
Si vas a usar el módulo de cámara Raspberry Pi, debes habilitarlo antes en la Raspberry. En el entorno de escritorio, debes abrir la ventana de Configuración de Raspberry Pi en el menú Preferencias, abrir la pestaña «Interfaces» y habilitar la Cámara como se muestra en la siguiente figura:
O bien puedes hacerlo desde consola usando el comando «raspi-config«:
pi@raspberry:~ $ sudo raspi-config
Te aparecerá el panel de configuración de Raspberry que puedes navegar con la ayuda de las teclas arriba y abajo. Selecciona Interface Options.
Posteriormente selecciona «P1 Camera» y habilita la conexión con la cámara.
El Código para hacer Streaming en Raspberry
Te mostramos y explicamos el código en Python.
import io import picamera import logging import socketserver from threading import Condition from http import server #decodigo.com PAGE="""\ <html> <head> <title>Raspberry Pi - Stream de Video</title> </head> <body> <center><h1>Raspberry Pi - Streaming de Video</h1></center> <center>Surveillance Camera</center> <center><img src="stream.mjpg" width="640" height="480"></center> </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'): #Frame nuevo, copia el contenido existente del buffer y notifica a todos los clientes que esta disponible 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('Removiendo al cliente de streaming %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() #Si es necesario rotar la imagen de la camara, descomenta la siguiente linea #camera.rotation = 90 camera.start_recording(output, format='mjpeg') try: address = ('', 8000) server = StreamingServer(address, StreamingHandler) server.serve_forever() finally: camera.stop_recording()
En la primera sección del código definimos la página HTML en la variable PAGE, esto permitirá mostrar el streaming de video de la cámara.
PAGE="""\ <html> <head> <title>Raspberry Pi - Stream de Video</title> </head> <body> <center><h1>Raspberry Pi - Streaming de Video</h1></center> <center>Surveillance Camera</center> <center><img src="stream.mjpg" width="640" height="480"></center> </body> </html> """
Creamos una clase StreamingOutput que nos permita hacer streaming de video.
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'): #Frame nuevo, copia el contenido existente del buffer y notifica a todos los clientes que esta disponible self.buffer.truncate() with self.condition: self.frame = self.buffer.getvalue() self.condition.notify_all() self.buffer.seek(0) return self.buffer.write(buf)
La clase StreamingHandler nos permite dar respuesta a las peticiones del navegador:
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('Removiendo al cliente de streaming %s: %s', self.client_address, str(e)) else: self.send_error(404) self.end_headers()
La clase StreamingServer nos permite crear hilos de ejecución para cada petición del usuario desde el navegador:
class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer): allow_reuse_address = True daemon_threads = True
Finalmente, inicializamos la cámara y levantamos nuestro servidor Web para comenzar con el streaming.
with picamera.PiCamera(resolution='640x480', framerate=24) as camera: output = StreamingOutput() #Si es necesario rotar la imagen de la camara, descomenta la siguiente linea #camera.rotation = 90 camera.start_recording(output, format='mjpeg') try: address = ('', 8000) server = StreamingServer(address, StreamingHandler) server.serve_forever() finally: camera.stop_recording()
Ejecutar el script y visualizar el resultado en el Navegador
Antes de ejecutar el script asegúrate de saber la IP de tu Raspberry, ejecutando el comando ‘ifconfig‘:
pi@raspberry:~ $ ifconfig
En mi caso he llamado a mi archivo camara_stream.py, al ejecutar el script con Python nuestro Servidor Web comenzará a ejecutarse indefinidamente.
pi@raspberrypi:~/Documents/inicio $ python3 camara_stream.py
El resultado cuando escribas la URL en el navegador ‘http://la_ip_de_tu_raspberry:8000/‘ reemplazando la IP de la Raspberri Pi es el siguiente:
El Módulo de Cámara de Raspberry Pi es muy fácil de instalar y de usar. Aunque no es de la mejor calidad, es posible darle usos bastante prácticos.
Más información en la página oficial: https://projects.raspberrypi.org/en/projects/getting-started-with-picamera