This is the always-on server for the Church Media Player. It runs on the church PC, owns the one real VLC instance, and plays audio/video out of that machine's PA connection and screen. It also serves a browser-based control page so playback can be controlled from any device on the same network ? laptop, tablet, or phone.
This server is the single source of truth for playback. The desktop app (
church_player.py, in thechurch_playerfolder) no longer runs its own VLC instance ? it's just another control surface that talks to this same server, exactly like the browser page does. That means you can run this server and have the desktop app open and control things from a phone, all at the same time, with zero conflict ? there's only ever one real player, and every control surface is a window onto the same live session. Keep this server running permanently (see the systemd setup below) so mobile/desktop control both work any time, whether or not anyone's physically at the church PC.
- Two libraries, each its own tab and folder setting:
- Music ? for background worship music. mp4s here play as audio-only by default.
- Videos ? for standalone video content (e.g. course sessions). Files here show video by default.
- Play / Pause / Stop with a 3-second fade-out on Stop
- Drag-and-drop playlist reordering per library (works with touch too, so you can reorder from a phone or tablet)
- Double-tap/double-click a song to move it to the top and play it
- Song / Artist columns, with the artist auto-detected from a trailing
(Artist Name)in the filename - Progress bar with elapsed/remaining time and click/drag-to-seek
- Volume control
- Show video toggle ? appears whenever the current track is a video file, letting you switch it between audio-only and video-visible from your phone
- Fullscreen toggle ? once video is showing, remotely control whether it's fullscreen on the church PC's screen
- Auto-advances to the next song in the same library when one finishes
- Volume is safely restored if the app is stopped/restarted mid fade-out
- Control from any device on the LAN at once (e.g. run playback from a tablet at the sound desk while it plays through the church PC)
-
Install VLC on the church PC.
pactlis also used, as a safety net to make sure the system volume never gets left low -- it's normally already installed as part of PulseAudio/PipeWire, but the package below makes sure:sudo apt update sudo apt install vlc pulseaudio-utils
(
xdotoolis no longer needed -- see "Video playback" below for why.) -
Install the Python packages:
pip3 install -r requirements.txt
From the church_player_web folder:
python3 server.pyYou'll see something like:
Church Media Player web server starting on port 5000...
On this machine, open: http://localhost:5000
From another device on the LAN, use this machine's LAN IP address, e.g.:
http://<this-computer's-ip-address>:5000
Run this on the church PC:
hostname -IIt'll print something like 192.168.1.42. From any other device on
the same Wi-Fi/network, open a browser to:
http://192.168.1.42:5000
Scroll to the settings panel at the bottom of the page. There are two
folder boxes ? Music folder and Video folder ? each with its
own Save button. Type the folder path as it exists on the church
PC (e.g. /home/yourname/Music) into each, and save. These are
remembered for next time.
Showing video requires this process to have access to the church PC's
actual screen (the same way it needs access to its audio session). The
server creates and owns its own borderless window, positioned
exactly on the display you've chosen, and VLC renders directly into
it ? this is the same technique the desktop app uses for its own video
window, just done directly against X11 since this process has no GUI
toolkit of its own. There's no separate "move a window after the fact"
step and no dependency on xdotool: since the window is ours from the
start, positioning it is just a normal, instant local call, with
nothing for the window manager to interfere with.
If nothing appears on screen when you'd expect it to:
- Confirm the church PC is logged into its desktop session (not just showing a lock screen), since the video window needs a real X display to draw into.
- Check the service logs (see below) for any error mentioning
DISPLAY,couldn't connect to X server, or similar ? if the service can't see the desktop's display, this is the equivalent of the earlier PulseAudio access issue we solved for audio, and may need a similar fix. - Try running
python3 server.pydirectly in a terminal on the church PC's desktop first (rather than as a background service) to confirm it works there, exactly like we did when debugging the original audio issue.
Which screen it picks: the server detects connected displays via
xrandr and defaults to whichever non-primary display looks like a
real, physically connected monitor (outputs reporting 0mm x 0mm
physical size ? a common sign of a stale/ghost display entry some
systems report ? are skipped automatically). If it guesses wrong, use
Video > Choose Video Display... in the desktop app (or the
equivalent dropdown in the web page's settings panel), which lists the
detected displays by name (e.g. HDMI-1-3) so you can pick the
right one ? this is remembered for next time and stays correct even on
machines with 3+ displays.
Switching which display is selected, or toggling Fullscreen, doesn't interrupt playback at all ? since we own the window outright, these are just instant repositioning/resizing of the same window, not a stop-and-restart of the video.
Use the Fullscreen button (web page or desktop app) any time you want to shrink video to a small preview window instead of covering the whole display ? handy for confirming what's about to show before it's full-size on the projector.
A note on closing the video window: since this window belongs to the server and isn't managed by the window manager, there's no title bar or close button for Alt+F4 to target, and the server itself is the only thing that can show, hide, move, or resize it. Turning video off via the Show video checkbox/toggle is the normal way to hide it.
If VLC's playback calls (not the window itself, but things like
starting or stopping a track) ever get stuck ? which can happen if the
underlying graphics driver has a genuine hiccup ? the server detects
several hung calls in a row and automatically rebuilds its VLC
instance to recover, rather than staying broken until someone
restarts the service by hand. You'll see a note like "libvlc appears
wedged ... rebuilding the VLC instance to recover" in the logs if this
happens; press Play again afterward to resume. If this keeps
recurring often, it's worth checking the church PC's graphics driver
setup (look for libva/VA-API errors in the logs around the same
time), since that's the more likely underlying cause rather than
something fixable purely in the app.
There's also a native desktop control window (church_player.py, in
the church_player folder) that talks to this same server instead of
running its own VLC instance ? see that folder's README. Since it's
just another client of this server, you can run it on the church PC
alongside this service running permanently in the background, and
control things from a phone at the same time, with no conflict.
If other devices can't reach the page, the church PC's firewall may be blocking the connection. Allow port 5000:
sudo ufw allow 5000/tcp(If you're not using ufw, check whatever firewall tool Linux Mint
has configured, or open port 5000 for local network traffic there.)
Run it as a user-level systemd service (not a system-wide one) so it has proper access to your desktop's audio and display sessions:
-
Create
~/.config/systemd/user/church-player.service:[Unit] Description=Church Media Player Web Server After=default.target sound.target [Service] Type=simple WorkingDirectory=/path/to/church_player_web ExecStart=/usr/bin/python3 -u /path/to/church_player_web/server.py Restart=on-failure RestartSec=3 [Install] WantedBy=default.target
Replace the paths with wherever you saved these files.
-
Let it run even when logged out, and enable/start it:
sudo loginctl enable-linger $USER systemctl --user daemon-reload systemctl --user enable church-player systemctl --user start church-player
Note: no
sudoon thesystemctl --usercommands. -
Check it's running and watch its logs:
systemctl --user status church-player journalctl --user -u church-player -f
Once set up, anyone on the LAN can open http://<church-pc-ip>:5000
whenever they need it ? no need to open a terminal first, and it
survives reboots and logouts.
- The "Song"/"Artist" parsing, drag-to-reorder, double-tap-to-play, fade-out-on-stop, and auto-advance all behave the same regardless of which control surface (browser or desktop app) triggers them ? it's all the same server-side logic.
- Multiple devices (and the desktop app) can be connected at the same time; they'll all stay in sync (the page/app polls the server a couple of times a second).
- Video-folder items default to showing video; music-folder items (even mp4s) default to audio-only. Either can be toggled per-track from any control surface while it's playing.
- Each library folder can have one level of subfolders (e.g.
Music/Christmas/,Music/Easter/) ? files inside are shown with their subfolder name as a small badge next to the artist. - The server exposes a small REST API (
/api/state,/api/play,/api/pause,/api/stop,/api/volume,/api/seek,/api/video,/api/fullscreen,/api/screens,/api/video_screen,/api/reorder,/api/settings,/api/refresh) ? this is what both the browser page and the desktop app talk to. Nothing else needs to be built on top of it, but it's there if you ever want to script something.