LinuxstorageTested on real hardware

Plex Default-Subtitle Sweep (Linux)

Clear default subtitle flags across a media library with ffmpeg stream-copy remux so files Direct Play instead of forcing a transcode — plus a cron job for new downloads.

Distrosubuntu, debian, alpine
Shellbash
Updated
Script
bash
#!/usr/bin/env bash
# Clear the DEFAULT flag on subtitle streams across a media tree.
# Stream-copy remux only (no re-encode, no quality loss).
# Forced subtitle streams keep their forced flag.
set -euo pipefail

MEDIA_DIR="${1:-/media}"

find "$MEDIA_DIR" -type f -name '*.mkv' -print0 | while IFS= read -r -d '' f; do
  # Which subtitle streams are marked default?
  defaults=$(ffprobe -v error -select_streams s \
    -show_entries stream=index:stream_disposition=default,forced \
    -of csv=p=0 "$f" | awk -F, '$2==1 {print $1","$3}')

  [ -z "$defaults" ] && continue   # nothing defaulted, skip (idempotent)

  args=()
  while IFS=, read -r idx forced; do
    # keep forced foreign-dialogue subs forced, just not defaulted
    if [ "$forced" = "1" ]; then
      args+=(-disposition:s:"$idx" forced)
    else
      args+=(-disposition:s:"$idx" 0)
    fi
  done <<< "$defaults"

  tmp="${f%.mkv}.sweep.mkv"
  if ffmpeg -v error -fflags +genpts -i "$f" \
      -map 0 -map_metadata 0 -map_chapters 0 -c copy \
      -max_interleave_delta 0 "${args[@]}" "$tmp"; then
    mv -f "$tmp" "$f"
    echo "swept: $f"
  else
    rm -f "$tmp"
    echo "FAILED (left untouched): $f" >&2
  fi
done

What this does

A subtitle track marked default tells the client to display it, which forces Plex to burn the subtitle into the video — a full transcode. On low-power hardware that transcode stutters or fails outright. This script walks a media tree, finds every MKV with a defaulted subtitle stream, and clears the default flag with an ffmpeg stream-copy remux (no re-encode, so zero quality loss and it runs in seconds per file). Forced foreign-dialogue subtitles keep their forced flag so they still show when needed.

After the sweep, files Direct Play and the subtitles are still there — just off by default, ready to toggle on manually.

Prerequisites

  • ffmpeg and ffprobe installed (sudo apt-get install -y ffmpeg)
  • Read/write access to the media folder
  • Run against a backup or a copy first if you’re nervous — the remux is lossless but it does overwrite in place

Usage

Point it at your media root (defaults to /media):

bash

chmod +x sub-sweep.sh
./sub-sweep.sh /media/Movies

Auto-sweep new downloads with cron

To keep new downloads clean, run a lightweight version every 30 minutes that only touches recently-modified files:

bash

# Only scan MKVs modified in the last 90 minutes, then sweep them.
# Add to root's crontab:  crontab -e
*/30 * * * * find /media -name '*.mkv' -mmin -90 -print0 | \
xargs -0 -I{} /usr/local/bin/sub-sweep-one.sh "{}" >> /var/log/sub-sweep.log 2>&1

Notes

  • Timestamp errors: some MKVs fail with “Can’t write packet with unknown timestamp.” The -fflags +genpts -max_interleave_delta 0 flags in the script fix that — keep them.
  • Idempotent: a file with no defaulted subtitle is skipped, so re-running is safe and cheap.
  • MKV only: the script targets .mkv. MP4 rarely carries the problematic image subtitle formats, but you can add -o -name '*.mp4' to the find if needed.
  • Not mkvpropedit? mkvpropedit can flip the flag without a remux and is faster if installed, but ffmpeg is far more commonly available (it ships on most NAS boxes), so this script uses it.