Skip to content

Instantly share code, notes, and snippets.

@maximuskowalski
Created October 3, 2021 05:44
Show Gist options
  • Save maximuskowalski/3136f8a9bf09ee8928c9b74e279817f9 to your computer and use it in GitHub Desktop.
Save maximuskowalski/3136f8a9bf09ee8928c9b74e279817f9 to your computer and use it in GitHub Desktop.
#!/bin/bash
# #####################################
# Script: Plex Preloader v0.9
# Description: Preloads the recent video files of a specific path into the RAM to bypass HDD spinup latency
# Author: Marc Gutt
#
# Changelog:
# 0.9
# - Preloads only subtitle files that belong to preloaded video files
# 0.8
# - Bug fix: In some situations video files were skipped instead of preloading them
# 0.7
# - Unraid dashboard notification added
# - Removed benchmark for subtitle preloading
# 0.6
# - multiple video path support
# 0.5
# - replaced the word "movie" against "video" as this script can be used for TV Shows as well
# - reduced preload_tail_size to 1MB
# 0.4
# - precleaning cache is now optional
# 0.3
# - the read cache is cleaned before preloading starts
# 0.2
# - preloading time is measured
# 0.1
# - first release
#
# ######### Settings ##################
video_paths=(
"/mnt/user/Movies/"
"/mnt/user/TV/"
)
video_min_size="2000MB" # 2GB, to exclude bonus content
preload_head_size="60MB" # 60MB, raise this value if your video buffers after ~5 seconds
preload_tail_size="1MB" # 10MB, should be sufficient even for 4K
video_ext='avi|mkv|mov|mp4|mpeg' # https://support.plex.tv/articles/203824396-what-media-formats-are-supported/
sub_ext='srt|smi|ssa|ass|vtt' # https://support.plex.tv/articles/200471133-adding-local-subtitles-to-your-media/#toc-1
free_ram_usage_percent=50
preclean_cache=0
notification=1
# #####################################
#
# ######### Script ####################
# make script race condition safe
if [[ -d "/tmp/${0///}" ]] || ! mkdir "/tmp/${0///}"; then exit 1; fi; trap 'rmdir "/tmp/${0///}"' EXIT;
# check user settings
video_min_size="${video_min_size//[!0-9.]/}" # float filtering https://stackoverflow.com/a/19724571/318765
video_min_size=$(awk "BEGIN { print $video_min_size*1000000}") # convert MB to Bytes
preload_head_size="${preload_head_size//[!0-9.]/}"
preload_head_size=$(awk "BEGIN { print $preload_head_size*1000000}")
preload_tail_size="${preload_tail_size//[!0-9.]/}"
preload_tail_size=$(awk "BEGIN { print $preload_tail_size*1000000}")
# clean the read cache
if [ "$preclean_cache" = "1" ]; then
sync; echo 1 > /proc/sys/vm/drop_caches
fi
# preload
preloaded=0
skipped=0
preload_total_size=$(($preload_head_size + $preload_tail_size))
free_ram=$(free -b | awk '/^Mem:/{print $7}')
free_ram=$(($free_ram / 100 * $free_ram_usage_percent))
echo "Available RAM in Bytes: $free_ram"
preload_amount=$(($free_ram / $preload_total_size))
echo "Amount of Videos that can be preloaded: $preload_amount"
# fetch video files
while IFS= read -r -d '' file; do
if [[ $preload_amount -le 0 ]]; then
break;
fi
size=$(stat -c%s "$file")
if [ "$size" -gt "$video_min_size" ]; then
TIMEFORMAT=%R
benchmark=$(time ( head -c $preload_head_size "$file" ) 2>&1 1>/dev/null )
echo "Preload $file (${benchmark}s)"
if awk 'BEGIN {exit !('$benchmark' >= '0.150')}'; then
preloaded=$((preloaded + 1))
else
skipped=$((skipped + 1))
fi
tail -c $preload_tail_size "$file" > /dev/null
preload_amount=$(($preload_amount - 1))
video_path=$(dirname "$file")
# fetch subtitle files
find "$video_path" -regextype posix-extended -regex ".*\.($sub_ext)" -print0 |
while IFS= read -r -d '' file; do
echo "Preload $file"
cat "$file" >/dev/null
done
fi
done < <(find "${video_paths[@]}" -regextype posix-extended -regex ".*\.($video_ext)" -printf "%T@ %p\n" | sort -nr | cut -f2- -d" " | tr '\n' '\0')
# notification
if [[ $preloaded -eq 0 ]] && [[ $skipped -eq 0 ]]; then
/usr/local/emhttp/webGui/scripts/notify -i alert -s "Plex Preloader failed!" -d "No video file has been preloaded (wrong path?)!"
elif [ "$notification" = "1" ]; then
/usr/local/emhttp/webGui/scripts/notify -i normal -s "Plex Preloader has finished" -d "$preloaded preloaded (from Disk) / $skipped skipped (already in RAM)"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment