Now using native VLC by default (with Flatpak as automatic fallback).
Hardware‑accelerated decoding, smooth NFS playback, auto‑resume, and global hotkeys.
Works on Arch, Fedora, Mint, Ubuntu, Pop!_OS, Void, PCLinuxOS, Gentoo – any modern Linux.
actimeo=1 makes NFS refresh file size every second – VLC sees the growing recording length while reads stay cached and smooth.
Install native VLC (preferred), NFS client, a cron daemon for the auto‑mount, and playerctl.
Flatpak is optional – the launcher will use it only if native VLC is missing.
| Distribution | Commands |
|---|---|
| Arch Linux |
sudo pacman -S vlc nfs-utils cronie playerctlsudo systemctl enable --now cronie
|
| Fedora |
sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpmsudo dnf install vlc nfs-utils cronie playerctlsudo systemctl enable --now cronie
|
| Linux Mint / Ubuntu |
sudo apt update && sudo apt install vlc nfs-common cron playerctl(cron is usually enabled by default) |
| Pop!_OS |
sudo apt update && sudo apt install vlc nfs-common cron playerctl
|
| Void Linux |
sudo xbps-install -S vlc nfs-utils cronie playerctlsudo ln -s /etc/sv/cronie /var/service/
|
| PCLinuxOS |
sudo dnf install vlc nfs-utils cronie playerctlsudo systemctl enable --now cronie
|
| Gentoo |
sudo emerge media-video/vlc net-fs/nfs-utils sys-process/cronie media-sound/playerctlsudo rc-update add cronie default && sudo rc-service cronie start
|
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepoflatpak install flathub org.videolan.VLC
playerctl is not available in your repositories, install it via Flatpak:flatpak install flathub org.mpris.MediaPlayer2.playerctl/usr/local/bin/playerctl that runs flatpak run org.mpris.MediaPlayer2.playerctl "$@".
Add this line to root’s crontab. It waits 15 seconds for the network, then mounts the NFS share with actimeo=1.
sudo crontab -e
Paste this single line:
@reboot sleep 15 && mount --mkdir -t nfs 192.168.40.45:/mnt/data /mnt/crow -o actimeo=1,rsize=1048576,wsize=1048576
--mkdir – creates /mnt/crow if it doesn’t exist.actimeo=1 – attribute cache timeout 1 second (live file‑size updates).rsize/wsize=1 MB – large chunks for smooth playback.Prerequisite: The NFS server exports /mnt/data. Videos must be under /mnt/crow/videos/Hockey (i.e. 192.168.40.45:/mnt/data/videos/Hockey). Adjust the VIDEO_DIR variable in the script if your layout differs.
Test the mount manually before rebooting:
sudo mkdir -p /mnt/crow
sudo mount -t nfs 192.168.40.45:/mnt/data /mnt/crow -o actimeo=1,rsize=1048576,wsize=1048576
ls /mnt/crow/videos/Hockey # should show .ts files
Save as /usr/local/bin/hockey. This script auto‑detects native VLC, falls back to Flatpak, and uses hardware‑accelerated decoding. It restarts VLC from 5 s before where you left off whenever VLC exits (EOF, manual reload, etc.).
#!/bin/bash
# Hockey auto‑resume player – native VLC first, Flatpak fallback; HW‑optimised
VIDEO_DIR="/mnt/crow/videos/Hockey"
TIME_FILE="/tmp/vlc-last-time"
SEEK_BACK=5
# --------------------------------------------------------------------
# 1. Locate a working VLC (native → Flatpak → exit)
# --------------------------------------------------------------------
if command -v vlc &>/dev/null; then
VLC_BIN="vlc"
USE_FLATPAK=0
elif command -v flatpak &>/dev/null && flatpak info org.videolan.VLC &>/dev/null; then
VLC_BIN="org.videolan.VLC"
USE_FLATPAK=1
else
echo "VLC not found. Install it natively or via Flatpak." >&2
exit 1
fi
# --------------------------------------------------------------------
# 2. Performance options – suitable for RPi5, Sandy Bridge, modern PCs
# --------------------------------------------------------------------
# Allow user override with the environment variable VLC_PERF_OPTS.
if [ -z "$VLC_PERF_OPTS" ]; then
# --avcodec-hw=any → enable hardware decoding (VAAPI, V4L2, etc.)
# --no-osd → disable on‑screen display (save CPU on weak hardware)
# --no-mouse-events → ignore mouse input while playing
# --no-snapshot-preview → skip thumbnail creation
VLC_PERF_OPTS="--avcodec-hw=any --no-osd --no-mouse-events --no-snapshot-preview --fullscreen"
fi
# --------------------------------------------------------------------
# 3. Video directory & file selection
# --------------------------------------------------------------------
if [ ! -d "$VIDEO_DIR" ]; then
echo "Directory $VIDEO_DIR not found." >&2
exit 1
fi
mapfile -t FILES < <(find "$VIDEO_DIR" -maxdepth 1 -type f -name "*.ts" -printf "%f\n" | sort)
if [ ${#FILES[@]} -eq 0 ]; then
echo "No .ts files in $VIDEO_DIR." >&2
exit 1
fi
echo "Available .ts files in $VIDEO_DIR:"
select file in "${FILES[@]}"; do
if [ -n "$file" ]; then
FULL_PATH="$VIDEO_DIR/$file"
echo "Selected: $FULL_PATH"
break
else
echo "Invalid choice."
fi
done
# --------------------------------------------------------------------
# 4. Cleanup & time‑logging preparation
# --------------------------------------------------------------------
: > "$TIME_FILE" # ensure an empty time file
if ! command -v playerctl >/dev/null; then
echo "Warning: playerctl not found – playback position won't be saved." >&2
fi
# Trap signals and kill the background time‑logger and VLC
trap 'kill "$STORE_PID" 2>/dev/null; kill "$VLC_PID" 2>/dev/null; exit' INT TERM
# --------------------------------------------------------------------
# 5. Main loop – play, log time, restart on exit
# --------------------------------------------------------------------
while true; do
# Determine start time
LAST_TIME=0
if [ -f "$TIME_FILE" ] && grep -qE '^[0-9]+' "$TIME_FILE"; then
LAST_TIME=$(cut -d' ' -f1 "$TIME_FILE")
fi
if [ "$LAST_TIME" -gt "$SEEK_BACK" ] 2>/dev/null; then
START_TIME=$(( LAST_TIME - SEEK_BACK ))
else
START_TIME=0
fi
echo "Starting VLC..."
if [ "$USE_FLATPAK" -eq 1 ]; then
flatpak run --filesystem="$VIDEO_DIR" --filesystem=/tmp \
"$VLC_BIN" $VLC_PERF_OPTS --start-time="$START_TIME" --play-and-exit "$FULL_PATH" &
else
"$VLC_BIN" $VLC_PERF_OPTS --start-time="$START_TIME" --play-and-exit "$FULL_PATH" &
fi
VLC_PID=$!
# Background logger – writes current playback position every second
(
while kill -0 "$VLC_PID" 2>/dev/null; do
if command -v playerctl >/dev/null; then
# Try the usual MPRIS name for VLC (lowercase)
POS=$(playerctl -p vlc position-raw 2>/dev/null || true)
# If that failed, try the capitalised name sometimes used by Flatpak
if [ -z "$POS" ]; then
POS=$(playerctl -p VLC position-raw 2>/dev/null || true)
fi
if [[ "$POS" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
echo "${POS%%.*}" > "$TIME_FILE"
fi
fi
sleep 1
done
) &
STORE_PID=$!
# Wait for VLC to finish, then stop the logger
wait "$VLC_PID" 2>/dev/null
kill "$STORE_PID" 2>/dev/null || true
wait "$STORE_PID" 2>/dev/null || true
echo "VLC exited. Restarting..."
done
Make it executable:
sudo chmod +x /usr/local/bin/hockey
Kills the VLC process (native or Flatpak). The wrapper will restart from the saved time. Save as /usr/local/bin/vlc-reload.
#!/bin/bash
pkill vlc
sudo chmod +x /usr/local/bin/vlc-reload
Kills the konsole terminal running the hockey script, effectively stopping everything. Save as /usr/local/bin/hockey-stop.
#!/bin/bash
pkill konsole
sudo chmod +x /usr/local/bin/hockey-stop
konsole with your terminal’s process name if you use a different one (e.g., gnome-terminal, xfce4-terminal, foot).Add two global custom shortcuts in your desktop environment.
/usr/local/bin/vlc-reload./usr/local/bin/hockey-stop./usr/local/bin/vlc-reload, then press Super+R./usr/local/bin/hockey-stop, then press Super+Q./usr/local/bin/vlc-reload, press Super+R./usr/local/bin/hockey-stop, press Super+Q.bindsym Mod4+r exec /usr/local/bin/vlc-reload
bindsym Mod4+q exec /usr/local/bin/hockey-stop
Create ~/.local/share/applications/hockey.desktop to launch with a double‑click.
[Desktop Entry]
Name=Hockey
Comment=Watch growing .ts recordings
Exec=/usr/local/bin/hockey
Terminal=true
Type=Application
Icon=vlc
Categories=AudioVideo;
hockey in terminal or double‑click the desktop icon.VLC_PERF_OPTS environment variable before running hockey to change the VLC flags.Cut along the dashed border and tape to your HTPC keyboard.
Press when you reach the live edge – duration refreshes, seeking works again.
Kills konsole – stops the script and VLC instantly.
--avcodec-hw=any). Override with VLC_PERF_OPTS if needed.