This Python project plays a video back at an extremely slow pace, updating a frame on a color e-paper display (like Pimoroni Inky Impression) at a defined interval. A local web interface allows you to manage and view playback in real-time.
- Inspired by Bryan Boyer’s Very Slow Movie Player and Tom Whitwell’s 2020 version
- Powered by a Raspberry Pi and a Pimoroni Inky display
- Web UI for uploading videos, setting frame intervals, and previewing current frames
- Playback state stored in SQLite for full synchronization
- Optional development mode for testing on desktop
- Raspberry Pi (Zero 2 W or better recommended)
- Pimoroni Inky Impression 7.3"
- Photo frame FrameWorks 8” x 10”
- Custom Matboard Matboard & More
- Python 3.10+ recommended (works with 3.11/3.12 with patching)
- OpenCV
- NumPy
- Pillow
- Inky
- Flask
- SQLite3 (included with Python)
Note: On Raspberry Pi, you’ll also need SPI enabled and spidev available; see Troubleshooting below if you run into header or build errors.
If you haven’t followed Pimoroni’s Inky setup yet, at minimum enable SPI and reboot. You can do the full Pimoroni setup later if needed, but SPI must be on:
Pimoroni guide: https://learn.pimoroni.com/article/getting-started-with-inky-impression
sudo raspi-config nonint do_spi 0
sudo rebootgit clone https://github.com/ryanlane/epaper-movie-frame.git
cd epaper-movie-frameMake sure that SPI is enabled via sudo raspi-config or by editing /boot/config.txt.
This sets up system packages (optional), creates a Python virtual environment, installs dependencies, writes .env and config.toml, and can install a systemd service.
./install.shPrefer manual steps? You can skip the installer and follow the "Manual installation (no installer)" section below. You may optionally run system-level deps first:
# Optional: system deps (apt)
./system-setup.shIf you prefer to set everything up by hand (or the installer isn't suitable), follow these steps:
- System packages (Debian/Ubuntu/Raspberry Pi OS)
sudo apt update
sudo apt install -y \
python3-venv python3-pip python3-dev \
libgl1 libopenblas-dev libopenjp2-7 libtiff-dev
# If installing Raspberry Pi hardware extras via pip and it fails to build lgpio,
# install these and retry the pip step:
# sudo apt install -y swig liblgpio-dev- Create and activate a Python virtual environment, then install the project (editable)
python3 -m venv ./venv
source ./venv/bin/activate
python -m pip install --upgrade pip
# Desktop/WSL (no hardware):
pip install -e .
# Raspberry Pi (hardware support):
# Install dependencies including Inky and related libs from requirements.txt,
# then install this project in editable mode.
pip install -r requirements.txt
pip install -e .- Create configuration files
.envcontrols how scripts choose the environment and venv path.
cat > .env << 'EOF'
ENVIRONMENT=development # or production
VENV_PATH=./venv # path to your virtualenv
EOFconfig.tomlcontrols app behavior. For development (no hardware), use:
cat > config.toml << 'EOF'
TARGET_WIDTH = 800
TARGET_HEIGHT = 600
VIDEO_DIRECTORY = "videos"
OUTPUT_IMAGE_PATH = "frame.jpg"
DEVELOPMENT_MODE = true
EOFFor hardware on a Pi, set DEVELOPMENT_MODE = false and ensure SPI is enabled via sudo raspi-config or by editing /boot/config.txt.
Some Pi OS releases ship Python 3.13, while many wheels/extensions (like spidev) lag behind. If you see errors like “Python.h not found,” you have two good paths:
Path A (recommended): use system Python + apt’s spidev
sudo apt update
sudo apt install -y python3 python3-venv python3-dev python3-pip python3-spidev build-essential
# Create a venv that can see apt-installed packages like spidev
python3 -m venv --system-site-packages .venv
source .venv/bin/activate
python -c "import spidev; print('spidev OK, version:', getattr(spidev, '__version__', 'unknown'))"Path B: stay on your custom Python and compile spidev
# If your OS provides matching dev headers for your Python, e.g. 3.13:
sudo apt update
sudo apt install -y python3.13-dev build-essential
# Activate your venv and build spidev
source venv/bin/activate # or your venv path
python -V # confirm it matches the headers you installed
pip install --upgrade pip setuptools wheel
pip install spidevIf python3.13-dev isn’t available on your Pi OS release, either switch to Path A, install a supported Python (3.11/3.12) via pyenv, or build Python from source with headers.
If installing inky via pip fails on your Pi or the display doesn’t respond, follow Pimoroni’s guide to prepare the Inky stack at the OS level:
Getting Started with Inky Impression (Pimoroni): https://learn.pimoroni.com/article/getting-started-with-inky-impression
- Create needed directories
mkdir -p videos- Launch the app
chmod +x launch.sh
./launch.sh
## or, inside the venv
movieframeThe database and default settings are created automatically on first run.
- Optional: run as a systemd service (Pi/Linux with systemd)
SERVICE_NAME=movieframe
SERVICE_FILE=/etc/systemd/system/${SERVICE_NAME}.service
sudo tee "$SERVICE_FILE" > /dev/null <<EOF
[Unit]
Description=E-Paper Movie Frame
After=network.target
[Service]
Type=simple
User=${USER}
WorkingDirectory=$(pwd)
Environment=ENVIRONMENT=${ENVIRONMENT:-production}
ExecStart=$(pwd)/launch.sh
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable "$SERVICE_NAME"
sudo systemctl start "$SERVICE_NAME"
sudo systemctl --no-pager status "$SERVICE_NAME"After the installer, you can start the app anytime with:
./launch.shOr, from within the virtual environment, you can use the console script:
movieframeIf you chose to install a systemd service, it can be managed with:
sudo systemctl status movieframe # or your chosen name
sudo systemctl start movieframe
sudo systemctl stop movieframeYou can run the system on a regular PC by enabling:
DEVELOPMENT_MODE = trueThis disables hardware access and renders images to disk instead of using the e-paper display.
Tip: The installer can set this for you. It writes ENVIRONMENT=development to .env and toggles DEVELOPMENT_MODE in config.toml.
After starting the app, access the web UI at:
http://<your-pi-ip>:8000
Features:
- Upload videos
- Adjust frame update intervals
- Toggle playback
- View live preview of the frame
- ✅ Replaced
VideoSettingsJSON state with SQLite - ✅ All timing and frame data now pulled live from the database
- ✅ Playback state (
current_frame) is updated after each frame - ✅ Supports real-time updates from the web interface
- Technical Architecture: docs/TECHNICAL_ARCHITECTURE.md
- User Experience Guide: docs/USER_EXPERIENCE.md
These documents support handoff and porting this project to other platforms.
To remove the service and local artifacts:
chmod +x uninstall.sh
./uninstall.sh- Playlist or folder-based auto playback
- Better error handling around bad video files
- Add Waveshare display support
- Optionally export video metadata or history
- Offline-friendly log viewer in the web UI
- Build full OOBE for easy deployment
Ryan Lane Website: ryanlane.com
