Created
October 3, 2021 05:44
-
-
Save maximuskowalski/3136f8a9bf09ee8928c9b74e279817f9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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