🏒 Hockey Stream Auto‑Resume Player – Native VLC · actimeo=1

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.

Key trick: actimeo=1 makes NFS refresh file size every second – VLC sees the growing recording length while reads stay cached and smooth.

1. Install VLC and required tools

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.

DistributionCommands
Arch Linux sudo pacman -S vlc nfs-utils cronie playerctl
sudo systemctl enable --now cronie
Fedora sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
sudo dnf install vlc nfs-utils cronie playerctl
sudo 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 playerctl
sudo ln -s /etc/sv/cronie /var/service/
PCLinuxOS sudo dnf install vlc nfs-utils cronie playerctl
sudo systemctl enable --now cronie
Gentoo sudo emerge media-video/vlc net-fs/nfs-utils sys-process/cronie media-sound/playerctl
sudo rc-update add cronie default && sudo rc-service cronie start
Optional Flatpak fallback: If you cannot install native VLC, install Flatpak and the VLC Flatpak:
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install flathub org.videolan.VLC
If playerctl is not available in your repositories, install it via Flatpak:
flatpak install flathub org.mpris.MediaPlayer2.playerctl
Then create a wrapper script in /usr/local/bin/playerctl that runs flatpak run org.mpris.MediaPlayer2.playerctl "$@".

2. Mount the NFS share automatically at boot

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

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

3. Create the hockey launcher script

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

4. Create the reload helper script

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

5. Create the stop helper script

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
This closes all konsole windows. Replace konsole with your terminal’s process name if you use a different one (e.g., gnome-terminal, xfce4-terminal, foot).

6. Bind Meta+R (reload) and Meta+Q (stop)

Add two global custom shortcuts in your desktop environment.

KDE Plasma

  1. System Settings → Shortcuts → Custom Shortcuts → New → Global Shortcut → Command/URL.
  2. Reload: Name Hockey Reload, Trigger Meta+R, Action /usr/local/bin/vlc-reload.
  3. Stop: Name Hockey Stop, Trigger Meta+Q, Action /usr/local/bin/hockey-stop.

GNOME

  1. Settings → Keyboard → Custom Shortcuts → +.
  2. Reload: Name Hockey Reload, Command /usr/local/bin/vlc-reload, then press Super+R.
  3. Stop: Name Hockey Stop, Command /usr/local/bin/hockey-stop, then press Super+Q.

XFCE

  1. Settings → Keyboard → Application Shortcuts → Add.
  2. Command /usr/local/bin/vlc-reload, press Super+R.
  3. Command /usr/local/bin/hockey-stop, press Super+Q.

i3 / Sway

bindsym Mod4+r exec /usr/local/bin/vlc-reload
bindsym Mod4+q exec /usr/local/bin/hockey-stop

7. Optional: Desktop launcher

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;

✅ Usage Summary

🖨️ Printable Keyboard Reference Card

Cut along the dashed border and tape to your HTPC keyboard.

🚀 Launch

  • hockey in terminal
  • or double‑click "Hockey" on desktop

🎬 Playback

  • F   Fullscreen
  •   +10 seconds
  •   -10 seconds
  •   +1 minute
  •   -1 minute

🔄 Reload

  • Super + R (Meta+R)

Press when you reach the live edge – duration refreshes, seeking works again.

⏹️ Stop

  • Super + Q (Meta+Q)

Kills konsole – stops the script and VLC instantly.

ℹ️ Tips

  • If seeking stops working, hit Super+R to reload – playback resumes instantly.
  • To exit completely, press Super+Q or Ctrl+C in the terminal.
  • Hardware decoding is on by default (--avcodec-hw=any). Override with VLC_PERF_OPTS if needed.