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.
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.
Why this approach
Plex decides whether to Direct Play or transcode based on whether the client can handle the stream natively. One of the triggers that forces a transcode is a subtitle track marked “default” with an image-based format (like PGS, the format used on most Blu-ray rips). Image subtitles can’t be passed through — they have to be burned into the video frame, which requires a full video transcode. On a capable server, this is inconvenient. On a low-power NAS or LXC with no hardware video encoder, it means stuttering or complete failure.
The script in this playbook clears the default flag using ffmpeg’s stream-copy mode — it rewrites the MKV container without touching the video or audio streams, so there’s no quality loss and no re-encode. The operation takes a few seconds per file rather than the hours a re-encode would take. After the sweep, the subtitle tracks are still in the file and available for manual selection; they just won’t auto-enable and trigger a transcode.
Forced tracks (foreign-language dialogue like subtitles in an otherwise-English film) keep their forced flag, so they continue to display automatically in the appropriate context. The script filters specifically for default=1 without forced=1, so it only clears the tracks that would trigger unnecessary transcodes.
Running this sweep once after building a library from ripped or downloaded files is a significant quality-of-life improvement. Pairing it with a cron job (shown in the Auto-sweep section below) means future downloads get the same treatment automatically.
Prerequisites
ffmpegandffprobeinstalled (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):
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:
# 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 0flags 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 thefindif needed. - Not
mkvpropedit?mkvpropeditcan flip the flag without a remux and is faster if installed, butffmpegis far more commonly available (it ships on most NAS boxes), so this script uses it.