osc-vlc plays every video in ~/Videos, or on a USB drive, fullscreen and on a loop.
Control it over the network with TouchOSC, with physical buttons, or both, and keep up to
ten Pis playing in step.
Exhibitions, shop windows, stage backdrops, video walls. Set it up once, and it starts at boot and recovers from crashes without anyone touching it.
Play/pause, previous/next, seek, skip, scrub, speed, volume, loop modes and A-B loops.
For tablets and phones. One page per Pi, up to 10, plus an ALL page that controls them at once.
One button lines every Pi up on the same frame. LOCK keeps them within about 0.05 s with tiny speed changes.
Plug in a drive with videos and it plays those instead, until it's pulled out again. Safe to pull at any time.
GPIO buttons and a rotary encoder for seeking, working alongside TouchOSC.
Desktop or Lite mode, picked for your model. Warns in the log about videos your Pi can't decode smoothly.
On a Pi running Raspberry Pi OS (desktop or Lite), as your normal user. Not with sudo: the installer asks for your password itself when it needs it.
In a terminal or over SSH. (No internet on the Pi? Copy the osc-vlc folder to its home folder instead.)
sudo apt install -y git
git clone https://github.com/bzsqrl/osc-vlc.git ~/osc-vlc
It installs VLC and Python packages, sets up autostart, and picks Desktop or Lite mode for your Pi.
cd ~/osc-vlc
bash install.sh
Put them in ~/Videos or on a USB drive. They play in alphabetical order, so number them: 01-intro.mp4, 02-main.mp4…
The player starts fullscreen and loops the whole playlist. The installer prints your TouchOSC settings at the end.
sudo reboot
On one Pi:
cd ~/osc-vlc && git pull && bash install.sh
Or every Pi at once, from your computer (WSL, Linux or macOS):
bash update_pis.sh
bash install.sh --lite or --desktop.Open osc_vlc_player.tosc (tablet) or osc_vlc_player_phone.tosc (phone) in TouchOSC, and give each Pi its own connection. Every Pi uses the same install with no per-Pi settings.
| Connection | Host | Send port | Receive port |
|---|---|---|---|
| 1 | first Pi's IP | 9000 | 9001 |
| 2 | second Pi's IP | 9000 | 9002 |
| … | … | 9000 | … |
| 10 | tenth Pi's IP | 9000 | 9010 |
hostname -I on the Pi.Works with any mix of videos, formats and lengths, and reaches every player on the local network.
Every player pauses and jumps to the master's time. 1.5 seconds later, once they've all finished seeking, they start together. Press it once to line them up; they then run on their own.
The master sends its position once a second. A follower that drifts more than 0.05 s plays 1–2% faster or slower until it's back in step. No jumps, and the sound keeps its pitch.
The same files work on every model. What differs is what each can decode smoothly, so encode for the oldest Pi that will play your videos.
| Model | Best format | Limit |
|---|---|---|
| Pi Zero / Zero W | H.264, 1080p30, Lite mode | Through the desktop, far too slow |
| Pi Zero 2 W, 2, 3 / 3B+ | H.264, 1080p30, ≤ 20 Mbps | No HEVC / H.265 |
| Pi 4 / 400 | HEVC up to 4K60, level 5.1, ≤ 60 Mbps; or H.264 up to 1080p60 | HEVC above level 5.1 can crash VLC |
| Pi 5 / 500 | Same as Pi 4 | H.264 decoded by the CPU (fine to 1080p60) |
Ready-to-paste ffmpeg commands for each are in the README.
Building your own layout, or driving it from QLab, Max, or any OSC app? Send to port 9000.
| Address | Action |
|---|---|
/toggle | Play / pause |
/play | Play. From stopped, re-reads the videos first |
/pause · /stop | Pause · Stop |
/next · /prev | Next · previous video |
/ab/a · /ab/b · /ab/clear | A-B loop: set A, set B and start looping, clear |
/sync | Line every player up on this one |
/sync/lock | LOCK on / off with this player as master |
/quit | Quit the player |
| Address | Argument | Action |
|---|---|---|
/skip | float, e.g. 10, -10 | Jump forward / back that many seconds |
/seek | float, e.g. 0 | Jump to that time in seconds |
/goto | integer | Play video N (first is 0) |
/loop | none / all / one | Playlist mode |
/volume/step | integer, e.g. 10 | Volume up / down |
/aspect | fill / original / 16:9 | Picture shape |
/ab/set | two floats | A-B loop at exact times |
| Address | Value | Action |
|---|---|---|
/position | 0 → 1 | Scrub through the current video |
/volume | 0 → 100 | Volume |
/rate | e.g. 0.5 → 2 | Playback speed (1 = normal) |
/mute | 1 / 0 | Mute on / off |
/fullscreen | 1 / 0 | Fullscreen on / off |
| Send | Reply |
|---|---|
/status | Replies on port 9001 (or the port given as an integer argument) with /status/state, /status/file, /status/time, /status/length, /status/volume, /status/host, /status/loop, /status/aspect, /status/lock and more. |
GPIO pin-outs, player settings and troubleshooting are all in the full README.