Raspberry Pi Zero-based media player in a 3D-printed miniature TV that plays classic TV shows on loop with Bluetooth audio.
Supports two modes:
- VLC mode - plays local video files from
~/Videos/ - Jellyfin mode - streams random episodes from a Jellyfin server
~/.pitv.conf (MODE=VLC or JELLYFIN)
|
v
pitv.sh (launcher)
/ \
/ \
vlc.sh jellyfin.sh
| |
| Jellyfin API --> playlist of stream URLs
| |
v v
cvlc (fullscreen, random, loop)
|
v
PulseAudio null-sink (vlc_output)
|
v
PulseAudio combine-sink (vlc_bt)
|
v
Bluetooth A2DP speaker (auto-connects on power-on)
- 320x480 DPI display driven via
vc4-kms-dpi-genericoverlay - Rotated 270 degrees (portrait display used in landscape) via
wlr-randr - Boot config:
boot/config.txt - Rotation service:
systemd/user/rotate-display.service
- VLC mode: plays all files in
~/Videos/randomly in a loop - Jellyfin mode: queries a Jellyfin server for episodes from shows listed in
~/shows.txt, builds a streaming playlist, and plays randomly in a loop - Auto-restarts on crash (handles bluetooth disconnections gracefully)
- Config:
home/.pitv.conf - Launcher:
home/pitv.sh - VLC script:
home/vlc.sh - Jellyfin script:
home/jellyfin.sh - Show list:
home/shows.txt
The audio pipeline uses PulseAudio to route VLC audio to a Bluetooth speaker:
- Null sink (
vlc_output) - virtual audio device that VLC outputs to - Combine sink (
vlc_bt) - merges the null sink with the Bluetooth output device - Bluetooth auto-connect - PulseAudio's
module-bluetooth-discoverdetects when the paired BT speaker powers on and connects automatically
Key configs:
etc/pulse/default.pa- PulseAudio with bluetooth modules,tsched=0,autodetect_mtu=yesetc/pulse/daemon.conf.snippet- Lower fragment size for BT audio latencyetc/bluetooth/main.conf.snippet-AutoEnable=true, BlueZ reconnect disabled (PulseAudio handles it)
sudo apt install vlc pulseaudio pulseaudio-module-bluetooth bluez curl jq# Boot config (requires reboot)
sudo cp boot/config.txt /boot/firmware/config.txt
# PiTV scripts
cp home/pitv.sh home/vlc.sh home/jellyfin.sh ~/ && chmod +x ~/pitv.sh ~/vlc.sh ~/jellyfin.sh
cp home/.pitv.conf home/shows.txt ~/
# System service - edit BT_MAC_ADDR to your bluetooth device MAC (underscores, not colons)
sudo cp systemd/system/vlc.service /etc/systemd/system/vlc.service
sudo systemctl daemon-reload
sudo systemctl enable vlc.service
# Display rotation (user service)
mkdir -p ~/.config/systemd/user/graphical-session.target.wants
cp systemd/user/rotate-display.service ~/.config/systemd/user/
ln -sf ~/.config/systemd/user/rotate-display.service ~/.config/systemd/user/graphical-session.target.wants/
# PulseAudio
sudo cp etc/pulse/default.pa /etc/pulse/default.pa
# Apply daemon.conf snippet manually
# Bluetooth
# Apply main.conf.snippet changes to /etc/bluetooth/main.conf [Policy] sectionbluetoothctl
> power on
> scan on
> pair XX:XX:XX:XX:XX:XX
> trust XX:XX:XX:XX:XX:XX
> connect XX:XX:XX:XX:XX:XXEdit ~/.pitv.conf:
# For local files:
MODE=VLC
# For Jellyfin streaming:
MODE=JELLYFIN
JELLYFIN_URL=https://jellyfin.server.home
JELLYFIN_API_KEY=your-api-key-hereFor Jellyfin mode, add shows to ~/shows.txt (one per line):
Friends
IT Crowd
Home Improvement
Place video files in ~/Videos/ (subdirectories supported).
sudo systemctl start vlc.service