Add PiCam network streamer with auto-setup for Pi 5
Initial commit of the MJPEG streaming server for Raspberry Pi. Supports Pi Camera Module (via picamera2), USB webcams (via OpenCV), and auto-detection of camera type. Includes: - `stream_picamera2.py` — optimized Pi CSI camera streamer - `stream_usb.py` — generic USB camera streamer - `stream.py` — auto-detects camera and launches correct streamer - `image-setup/` — SD card imaging scripts and Pi 5 headless setup guide for first-boot automation with systemd service - `requirements.txt` — Python dependencies
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
# Pi 5 + IMX219 OS Image Setup Guide
|
||||
|
||||
This guide walks you through setting up a **Raspberry Pi 5** with an **IMX219** camera module (Camera Module v2) to run the PiCam streamer.
|
||||
|
||||
## Option A: Easy Method — Run Setup on a Live Pi (Recommended)
|
||||
|
||||
If you already have Raspberry Pi OS running on your Pi 5:
|
||||
|
||||
1. **Copy the project** to your Pi (via USB drive, `scp`, or `git clone`).
|
||||
2. **Run the setup script:**
|
||||
```bash
|
||||
cd piCam/image-setup
|
||||
chmod +x setup-pi.sh
|
||||
./setup-pi.sh
|
||||
```
|
||||
3. **Done.** The streamer will start automatically and will auto-start on every boot.
|
||||
|
||||
Open `http://<pi-ip>:5000` in your browser.
|
||||
|
||||
---
|
||||
|
||||
## Option B: Prepare an SD Card Image from Scratch
|
||||
|
||||
### 1. Download Raspberry Pi OS
|
||||
|
||||
Download the latest **Raspberry Pi OS (64-bit)** from the official site:
|
||||
|
||||
```
|
||||
https://www.raspberrypi.com/software/operating-systems/
|
||||
```
|
||||
|
||||
Recommended: **Raspberry Pi OS with Desktop** or **Lite** if you want a headless server.
|
||||
|
||||
### 2. Flash the OS to SD Card
|
||||
|
||||
Use the official **Raspberry Pi Imager**:
|
||||
|
||||
```
|
||||
https://www.raspberrypi.com/software/
|
||||
```
|
||||
|
||||
Steps in Imager:
|
||||
1. Choose OS → Raspberry Pi OS (64-bit)
|
||||
2. Choose Storage → Your SD card
|
||||
3. Click the **gear icon (⚙️)** to open Advanced Options and configure:
|
||||
- **Hostname**: `picam` (or your preference)
|
||||
- **Enable SSH**: ☑️ (Use password authentication or public key)
|
||||
- **Set username/password**: `pi` / your-password
|
||||
- **Configure Wi-Fi**: Enter your SSID and password
|
||||
- **Set locale**: Your timezone and keyboard layout
|
||||
4. Click **Write**
|
||||
|
||||
### 3. Enable Camera Hardware
|
||||
|
||||
After flashing, the SD card will show a `bootfs` partition. You need to ensure camera support is enabled.
|
||||
|
||||
#### For Raspberry Pi OS Bookworm and later:
|
||||
|
||||
The IMX219 is usually auto-detected. However, if you need to force it, open `bootfs/config.txt` and add to the end:
|
||||
|
||||
```ini
|
||||
# IMX219 Camera Module v2
|
||||
dtoverlay=imx219
|
||||
```
|
||||
|
||||
> **Note:** On Pi 5, the camera uses the CSI/DSI connector. Make sure the flat cable is oriented correctly (blue tape facing away from the USB ports on Pi 5).
|
||||
|
||||
### 4. Copy the Project Files
|
||||
|
||||
Copy the contents of this `image-setup` folder to the SD card:
|
||||
|
||||
```bash
|
||||
# Linux/macOS example (adjust paths as needed)
|
||||
cp -r /path/to/piCam/image-setup/* /media/YOUR_USERNAME/bootfs/
|
||||
```
|
||||
|
||||
Specifically, ensure these files are placed on the `bootfs` partition:
|
||||
- `autosetup.sh` → root of `bootfs/`
|
||||
- `firstrun.sh` → root of `bootfs/`
|
||||
|
||||
### 5. Boot the Pi
|
||||
|
||||
Insert the SD card into the Pi 5, connect power, and wait 2-3 minutes for the first-boot setup to complete.
|
||||
|
||||
### 6. Access the Stream
|
||||
|
||||
Once booted, find the Pi on your network:
|
||||
```bash
|
||||
ping picam.local
|
||||
```
|
||||
|
||||
Then open in a browser:
|
||||
```
|
||||
http://picam.local:5000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| Camera not detected | Run `libcamera-hello --list-cameras` to verify hardware detection |
|
||||
| Green tint on image | Normal under some lighting; adjust AWB in picamera2 config |
|
||||
| Low framerate | Reduce resolution or ensure GPU memory isn't too low |
|
||||
| `picamera2` not found | Run `sudo apt install -y python3-picamera2` |
|
||||
|
||||
## Automated First-Boot Setup
|
||||
|
||||
If you copied the provided files to `bootfs`, the system will:
|
||||
1. Expand the filesystem
|
||||
2. Update all packages
|
||||
3. Install camera drivers, Python dependencies, and Flask
|
||||
4. Enable the camera interface
|
||||
5. Auto-start the streaming server on boot
|
||||
|
||||
Monitor progress by SSHing in:
|
||||
```bash
|
||||
ssh pi@picam.local
|
||||
tail -f /var/log/picam-setup.log
|
||||
```
|
||||
@@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
# PiCam First-Boot Setup Script
|
||||
# Run this on the Raspberry Pi after first boot to configure the IMX219 camera
|
||||
# and install the streaming server.
|
||||
|
||||
set -e
|
||||
|
||||
LOGFILE="/var/log/picam-setup.log"
|
||||
PROJECT_DIR="/home/pi/piCam"
|
||||
REPO_URL="" # Leave empty if copying files manually to the SD card
|
||||
|
||||
exec > >(tee -a "$LOGFILE")
|
||||
exec 2>&1
|
||||
|
||||
echo "========================================"
|
||||
echo "PiCam First-Boot Setup Starting"
|
||||
echo "Date: $(date)"
|
||||
echo "========================================"
|
||||
|
||||
# Update system
|
||||
echo "[1/6] Updating package lists..."
|
||||
sudo apt-get update
|
||||
|
||||
echo "[2/6] Installing system dependencies..."
|
||||
sudo apt-get install -y \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
python3-picamera2 \
|
||||
libcamera-dev \
|
||||
libcap-dev \
|
||||
git \
|
||||
i2c-tools \
|
||||
v4l-utils
|
||||
|
||||
# Ensure camera interface is enabled (legacy method, though Bookworm uses libcamera)
|
||||
echo "[3/6] Ensuring camera interface is enabled..."
|
||||
if command -v raspi-config &> /dev/null; then
|
||||
sudo raspi-config nonint do_camera 0 || true
|
||||
fi
|
||||
|
||||
# Create project directory
|
||||
echo "[4/6] Setting up project directory..."
|
||||
mkdir -p "$PROJECT_DIR"
|
||||
|
||||
# If files are already present (e.g., copied to SD card), use them.
|
||||
# Otherwise, clone or create a placeholder.
|
||||
if [ ! -f "$PROJECT_DIR/stream_picamera2.py" ]; then
|
||||
echo "Stream scripts not found in $PROJECT_DIR."
|
||||
echo "Please copy the project files manually:"
|
||||
echo " scp -r /path/to/piCam/* pi@picam.local:/home/pi/piCam/"
|
||||
fi
|
||||
|
||||
# Setup Python virtual environment
|
||||
echo "[5/6] Creating Python virtual environment..."
|
||||
python3 -m venv "$PROJECT_DIR/venv"
|
||||
source "$PROJECT_DIR/venv/bin/activate"
|
||||
|
||||
# Install Python dependencies
|
||||
echo "[6/6] Installing Python packages..."
|
||||
pip install --upgrade pip
|
||||
pip install Flask opencv-python-headless
|
||||
|
||||
# Install systemd service for auto-start
|
||||
echo "Installing systemd service..."
|
||||
cat <<EOF | sudo tee /etc/systemd/system/picam-stream.service
|
||||
[Unit]
|
||||
Description=PiCam MJPEG Streamer
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=pi
|
||||
WorkingDirectory=$PROJECT_DIR
|
||||
Environment="PATH=$PROJECT_DIR/venv/bin"
|
||||
ExecStart=$PROJECT_DIR/venv/bin/python $PROJECT_DIR/stream_picamera2.py --host 0.0.0.0 --port 5000
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable picam-stream.service
|
||||
|
||||
echo "========================================"
|
||||
echo "Setup Complete!"
|
||||
echo "========================================"
|
||||
echo "The streaming server will start automatically on boot."
|
||||
echo "To start it now, run: sudo systemctl start picam-stream"
|
||||
echo "To check status: sudo systemctl status picam-stream"
|
||||
echo "To view logs: sudo journalctl -u picam-stream -f"
|
||||
echo ""
|
||||
echo "Open in your browser: http://$(hostname -I | awk '{print $1}'):5000"
|
||||
|
||||
# Mark setup as complete so it doesn't run again
|
||||
touch /home/pi/.picam-setup-done
|
||||
@@ -0,0 +1,11 @@
|
||||
# Add these lines to the end of your /boot/firmware/config.txt (or /boot/config.txt)
|
||||
# to explicitly enable the IMX219 camera module on Raspberry Pi 5.
|
||||
|
||||
# IMX219 Camera Module v2
|
||||
dtoverlay=imx219
|
||||
|
||||
# Ensure camera is enabled (legacy, usually not needed on Bookworm but safe)
|
||||
camera_auto_detect=1
|
||||
|
||||
# Optional: Increase GPU memory if needed for higher resolutions
|
||||
# gpu_mem=128
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
# Raspberry Pi First-Boot Script
|
||||
# Place this file on the bootfs partition as 'firstrun.sh' to execute on first boot.
|
||||
# It will trigger the autosetup.sh script located in /boot/autosetup.sh
|
||||
|
||||
BOOT_SCRIPT="/boot/firmware/autosetup.sh"
|
||||
|
||||
# For older Raspberry Pi OS versions, the boot partition is mounted at /boot
|
||||
if [ ! -f "$BOOT_SCRIPT" ]; then
|
||||
BOOT_SCRIPT="/boot/autosetup.sh"
|
||||
fi
|
||||
|
||||
if [ -f "$BOOT_SCRIPT" ]; then
|
||||
echo "Found autosetup script at $BOOT_SCRIPT"
|
||||
chmod +x "$BOOT_SCRIPT"
|
||||
# Run as the default user (usually pi)
|
||||
sudo -u pi bash "$BOOT_SCRIPT"
|
||||
else
|
||||
echo "No autosetup.sh found on boot partition."
|
||||
fi
|
||||
@@ -0,0 +1,110 @@
|
||||
#!/bin/bash
|
||||
# PiCam Live Setup — Run this directly on your Raspberry Pi 5 after first boot.
|
||||
# This automates installation of dependencies and enables auto-start streaming.
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$HOME/piCam"
|
||||
LOGFILE="/var/log/picam-setup.log"
|
||||
|
||||
mkdir -p "$(dirname "$LOGFILE")"
|
||||
exec > >(tee -a "$LOGFILE")
|
||||
exec 2>&1
|
||||
|
||||
echo "============================================"
|
||||
echo " PiCam Setup Script"
|
||||
echo " Running on: $(hostname)"
|
||||
echo " Date: $(date)"
|
||||
echo "============================================"
|
||||
|
||||
# 1. System update
|
||||
echo "[1/7] Updating package lists..."
|
||||
sudo apt-get update
|
||||
|
||||
# 2. Install system packages
|
||||
echo "[2/7] Installing system packages..."
|
||||
sudo apt-get install -y \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
python3-picamera2 \
|
||||
libcamera-dev \
|
||||
libcap-dev \
|
||||
git \
|
||||
i2c-tools \
|
||||
v4l-utils
|
||||
|
||||
# 3. Detect camera
|
||||
echo "[3/7] Detecting camera..."
|
||||
if command -v libcamera-hello >/dev/null 2>&1; then
|
||||
echo "libcamera devices:"
|
||||
libcamera-hello --list-cameras || true
|
||||
else
|
||||
echo "libcamera-hello not found; relying on picamera2 detection."
|
||||
fi
|
||||
|
||||
# 4. Copy project files
|
||||
echo "[4/7] Installing project files..."
|
||||
mkdir -p "$PROJECT_DIR"
|
||||
|
||||
if [ -d "$SCRIPT_DIR/../" ] && [ -f "$SCRIPT_DIR/../stream_picamera2.py" ]; then
|
||||
# Running from cloned repo
|
||||
cp "$SCRIPT_DIR/../stream_picamera2.py" "$PROJECT_DIR/"
|
||||
cp "$SCRIPT_DIR/../stream_usb.py" "$PROJECT_DIR/"
|
||||
cp "$SCRIPT_DIR/../stream.py" "$PROJECT_DIR/"
|
||||
cp "$SCRIPT_DIR/../requirements.txt" "$PROJECT_DIR/"
|
||||
else
|
||||
echo "WARNING: Could not find project Python files."
|
||||
echo "Please copy them manually to $PROJECT_DIR"
|
||||
fi
|
||||
|
||||
# 5. Python environment
|
||||
echo "[5/7] Creating Python virtual environment..."
|
||||
python3 -m venv "$PROJECT_DIR/venv"
|
||||
source "$PROJECT_DIR/venv/bin/activate"
|
||||
|
||||
pip install --upgrade pip
|
||||
pip install Flask opencv-python-headless
|
||||
|
||||
# 6. Create systemd service
|
||||
echo "[6/7] Creating systemd service..."
|
||||
cat <<EOF | sudo tee /etc/systemd/system/picam-stream.service
|
||||
[Unit]
|
||||
Description=PiCam MJPEG Streamer
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$USER
|
||||
WorkingDirectory=$PROJECT_DIR
|
||||
Environment="PATH=$PROJECT_DIR/venv/bin"
|
||||
ExecStart=$PROJECT_DIR/venv/bin/python $PROJECT_DIR/stream_picamera2.py --host 0.0.0.0 --port 5000
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable picam-stream.service
|
||||
|
||||
# 7. Start service
|
||||
echo "[7/7] Starting streamer..."
|
||||
sudo systemctl start picam-stream.service
|
||||
|
||||
echo "============================================"
|
||||
echo " Setup Complete!"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Streamer is running as a systemd service."
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " Status: sudo systemctl status picam-stream"
|
||||
echo " Logs: sudo journalctl -u picam-stream -f"
|
||||
echo " Stop: sudo systemctl stop picam-stream"
|
||||
echo " Start: sudo systemctl start picam-stream"
|
||||
echo ""
|
||||
IP=$(hostname -I | awk '{print $1}')
|
||||
echo "Open in browser: http://$IP:5000"
|
||||
Reference in New Issue
Block a user