Crea tu cámara de seguridad con Raspberry Pi y el módulo de cámara.

💡
En calidad de Afiliado de Amazon, obtengo ingresos por las compras adscritas que cumplen los requisitos aplicables

¿Te gustaría poder vigilar qué pasa en casa desde cualquier sitio del mundo? Quizá tengas una mascota a la que quieras ver cuando estés fuera, o quizá simplemente quieres tener tus pertenencias bien vigiladas.

Sea cual sea el caso, en este artículo te voy a enseñar a hacer streaming de video con el módulo de cámara de la Raspberry Pi.

2 Piezas 5 Megapíxeles Sensor Ov5647 de 1080p Módulo de Mini Cámara con 6 Pulgadas de 15 Pines Cable de Cinta Compatible con Raspberry Pi Modelo A B B +, Pi 2 y Raspberry Pi 3, 3 B +, Pi 4 : Amazon.es: Informática
2 Piezas 5 Megapíxeles Sensor Ov5647 de 1080p Módulo de Mini Cámara con 6 Pulgadas de 15 Pines Cable de Cinta Compatible con Raspberry Pi Modelo A B B +, Pi 2 y Raspberry Pi 3, 3 B +, Pi 4 : Amazon.es: Informática

Activamos el módulo de cámara

Aunque es posible realizar este proyecto con otras cámaras USB, en este tutorial utilizaremos el módulo de cámara de Raspberry Pi, por requerir una configuración un tanto especial y porque creo que estos módulos molan mucho.

El módulo de cámara de Raspberry Pi que usaremos.

Lo primero que haremos es habilitar el uso de este módulo mediante la herramienta raspi-config, que nos permite configurar varias cosas de nuestra Raspberry Pi, incluida la cámara:

ardumaster@little-monkey:~ $ sudo raspi-config 
Ejecutamos la herramienta raspi-config
Activamos la cámara de Raspberry Pi.

Una vez dentro de la herramienta, seleccionamos 3 Interface Options, y después P1 Camera, para seleccionar Enable, lo cual habilitará el uso del módulo de cámara que hemos instalado.

Actualizamos el sistema y copiamos el programa.

Para hacer streaming con esta cámara, vamos a utilizar una receta de la documentación oficial del módulo de cámara de Raspberry Pi. Para ello, es necesario preparar algunas dependencias.

Empezamos actualizando el sistema:

ardumaster@little-monkey:~ $ sudo apt update and sudo apt full-upgrade 
Actualizamos el sistema.

Pasamos a darnos permisos del grupo de video para poder acceder a la cámara de forma programática:

ardumaster@little-monkey:~ $ sudo usermod -a -G video ardumaster
Nos damos permisos del grupo de video.

Instalamos picamera con pip3 (para Python 3, recuerda migrar si aún usas Python 2.7).

ardumaster@little-monkey:~ $ pip3 install picamera
Instalamos picamera

Ahora deberíamos tener todo lo necesario, creamos un directorio para nuestro script de Python y copiamos dentro el código de la documentación, que he copiado más abajo por conveniencia, pero que puedes consultar en el siguiente enlace:

ardumaster@little-monkey:~ $ mkdir camera
ardumaster@little-monkey:~ $ cd camera
ardumaster@little-monkey:~/camera $ nano camara.py
Creamos nuestro script de Python
4. Advanced Recipes — Picamera 1.13 Documentation
Código de ejemplo de Raspberry Pi.
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()
Código de ejemplo de Raspberry Pi

Ejecutamos el programa.

Por útimos, nos queda ejecutar el programa invocando a python3:

ardumaster@little-monkey:~/camera $ python3 camara.py
Ejecutamos nuestro script

¡Solo nos queda visitar la siguiente dirección: IP_de_nuestra_raspberry:8000(en mi caso 192.168.1.85:8000) para ver la imagen en directo!

Si no recuerdas la IP de tu raspberry, es fácil encontrarla con el sigueinte comando:

ardumaster@little-monkey:~ $ hostname -I
192.168.1.85 para mi.

Accedemos a nuestra cámara desde cualquier sitio del mundo.

Hemos creado un stream público, por lo que no es buena idea conectarlo directamente a internet (tampoco lo sería aunque fuese privado). Lo que recomiendo es instalar una VPN privada y acceder a este disco como si estuvieras en tu casa, aunque estés al otro lado del mundo.

Recomiendo utilizar Wireguard para instalar tu propia VPN en casa; en el siguiente artículo puedes encontrar como hacer esto de una forma muy sencilla:

Olvídate de anuncios estés donde estés con Pi-hole y WireGuard
Elimina anuncios en apps y internet en tu LAN y a distancia con WireGuard, Pi-Hole y Duck DNS

Conclusiones

Si bien es cierto que nuestro ejemplo es muy sencillo y que tendrás que ejecutar el programa cada vez que quieras ver la imagen en directo, creo que es muy resultón para el nivel de complejidad. Si deseas hacer algo más elaborado, claro, te animo a que estudies el programa ejemplo o explores otros métodos de streaming.

¡Espero que este artículo te haya sido de utilidad y que te diviertas observando a distancia!