Files
docker-mods-uptime-kuma-tim…/root/usr/local/bin/striptracks.sh
T
TheCaptain989 53bec57fb1 Release 2.13.1
2025-04-16 18:52:51 +00:00

1967 lines
100 KiB
Bash

#!/bin/bash
# Video remuxing script designed for use with Radarr and Sonarr
# Automatically strips out unwanted audio and subtitles tracks, keeping only the desired languages.
# Prod: https://github.com/linuxserver/docker-mods/tree/radarr-striptracks
# Dev/test: https://github.com/TheCaptain989/radarr-striptracks
#
# Inspired by Endoro's post 1/5/2014:
# https://forum.videohelp.com/threads/343271-BULK-remove-non-English-tracks-from-MKV-container#post2292889
#
# Put a colon `:` in front of every language code. Expects ISO639-2 codes
# NOTE: ShellCheck linter directives appear as comments
# Dependencies: # sudo apt install mkvtoolnix jq
# From mkvtoolnix:
# mkvmerge
# mkvpropedit
# From jq:
# jq
# Generally always available:
# sed
# awk
# curl
# numfmt
# stat
# nice
# basename
# dirname
# mktemp
# Exit codes:
# 0 - success; or test
# 1 - no video file specified on command line
# 2 - no audio language specified on command line
# 3 - no subtitles language specified on command line
# 4 - mkvmerge, mkvpropedit, or jq not found
# 5 - input video file not found
# 6 - unable to rename temp video to MKV
# 7 - unknown eventtype environment variable
# 8 - unsupported Radarr/Sonarr version (v2)
# 9 - mkvmerge get media info produced an error or warning
# 10 - remuxing completed, but no output file found
# 11 - source video had no audio tracks
# 12 - log file is not writable
# 13 - mkvmerge or mkvpropedit exited with an error
# 15 - could not set permissions and/or owner on new file
# 16 - could not delete the original file
# 17 - Radarr/Sonarr API error
# 18 - Radarr/Sonarr job timeout
# 20 - general error
### Variables
export striptracks_script=$(basename "$0")
export striptracks_ver="{{VERSION}}"
export striptracks_pid=$$
export striptracks_arr_config=/config/config.xml
export striptracks_log=/config/logs/striptracks.txt
export striptracks_maxlogsize=512000
export striptracks_maxlog=4
export striptracks_debug=0
# Presence of '*_eventtype' variable sets script mode
export striptracks_type=$(printenv | sed -n 's/_eventtype *=.*$//p')
# Usage functions
function usage {
usage="Try '$striptracks_script --help' for more information."
echo "$usage" >&2
}
function long_usage {
usage="$striptracks_script Version: $striptracks_ver
Video remuxing script that only keeps tracks with the specified languages.
Designed for use with Radarr and Sonarr, but may be used standalone in batch
mode.
Source: https://github.com/TheCaptain989/radarr-striptracks
Usage:
$0 [{-a|--audio} <audio_languages> [{-s|--subs} <subtitle_languages>] [--reorder] [{-f|--file} <video_file>]] [{-l|--log} <log_file>] [{-c|--config} <config_file>] [{-d|--debug} [<level>]]
Options can also be set via the STRIPTRACKS_ARGS environment variable.
Command-line arguments override the environment variable.
Options and Arguments:
-a, --audio <audio_languages> Audio languages to keep
ISO639-2 code(s) prefixed with a colon \`:\`
multiple codes may be concatenated.
Each code may optionally be followed by a
plus \`+\` and one or more modifiers.
-s, --subs <subtitle_languages> Subtitles languages to keep
ISO639-2 code(s) prefixed with a colon \`:\`
multiple codes may be concatenated.
Each code may optionally be followed by a
plus \`+\` and one or more modifiers.
--reorder Reorder audio and subtitles tracks to match
the language code order specified in the
<audio_languages> and <subtitle_languages>
arguments.
-f, --file <video_file> If included, the script enters batch mode
and converts the specified video file.
WARNING: Do not use this argument when called
from Radarr or Sonarr!
-l, --log <log_file> Log filename
[default: /config/log/striptracks.txt]
-c, --config <config_file> Radarr/Sonarr XML configuration file
[default: ./config/config.xml]
-d, --debug [<level>] Enable debug logging
level is optional, between 1-3
1 is lowest, 3 is highest
[default: 1]
--help Display this help and exit
--version Display script version and exit
When audio_languages and subtitle_languages are omitted the script detects the
audio or subtitle languages configured in the Radarr or Sonarr profile. When
used on the command line, they override the detected codes. They are also
accepted as positional parameters for backwards compatibility.
Language modifiers may be \`f\` or \`d\` which select Forced or Default tracks
respectively, or a number which specifies the maximum tracks to keep.
Batch Mode:
In batch mode the script acts as if it were not called from within Radarr
or Sonarr. It converts the file specified on the command line and ignores
any environment variables that are normally expected. The MKV embedded title
attribute is set to the basename of the file minus the extension.
Examples:
$striptracks_script -d 2 # Enable debugging level 2, audio and
# subtitles languages detected from
# Radarr/Sonarr
$striptracks_script -a :eng:und -s :eng # Keep English and Unknown audio and
# English subtitles
$striptracks_script -a :eng:org -s :any+f:eng # Keep English and Original audio,
# and forced or English subtitles
$striptracks_script -a :eng -s \"\" # Keep English audio and no subtitles
$striptracks_script -d :eng:kor:jpn :eng:spa # Enable debugging level 1, keeping
# English, Korean, and Japanese
# audio, and English and Spanish
# subtitles
$striptracks_script -f \"/movies/path/Finding Nemo (2003).mkv\" -a :eng:und -s :eng
# Batch Mode
# Keep English and Unknown audio and
# English subtitles, converting video
# specified
$striptracks_script -a :any -s \"\" # Keep all audio and no subtitles
$striptracks_script -a :org:any+d1 -s :eng+1:any+f2
# Keep all Original and one default
# audio in any language, and one
# English and two forced subtitles
# in any language
"
echo "$usage"
}
# Log command-line arguments
if [ $# -ne 0 ]; then
striptracks_prelogmessagedebug="Debug|Command line arguments are '$*'"
fi
# Check for environment variable arguments
if [ -n "$STRIPTRACKS_ARGS" ]; then
if [ $# -ne 0 ]; then
striptracks_prelogmessage="Warning|STRIPTRACKS_ARGS environment variable set but will be ignored because command line arguments were also specified."
else
# Move the environment variable arguments to the command line for processing
striptracks_prelogmessage="Info|Using settings from environment variable."
eval set -- "$STRIPTRACKS_ARGS"
fi
fi
# Process arguments
# Taken from Drew Stokes post 3/24/2015:
# https://medium.com/@Drew_Stokes/bash-argument-parsing-54f3b81a6a8f
unset striptracks_pos_params
while (( "$#" )); do
case "$1" in
-d|--debug ) # Enable debugging, with optional level
if [ -n "$2" ] && [ ${2:0:1} != "-" ] && [[ "$2" =~ ^[0-9]+$ ]]; then
export striptracks_debug=$2
shift 2
else
export striptracks_debug=1
shift
fi
;;
-l|--log ) # Log file
if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then
export striptracks_log="$2"
shift 2
else
echo "Error|Invalid option: $1 requires an argument." >&2
usage
exit 1
fi
;;
--help ) # Display full usage
long_usage
exit 0
;;
--version ) # Display version
echo "$striptracks_script $striptracks_ver"
exit 0
;;
-f|--file ) # Batch Mode
if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then
# Overrides detected *_eventtype
export striptracks_type="batch"
export striptracks_video="$2"
shift 2
else
echo "Error|Invalid option: $1 requires an argument." >&2
usage
exit 1
fi
;;
-a|--audio ) # Audio languages to keep
if [ -z "$2" ] || [ ${2:0:1} = "-" ]; then
echo "Error|Invalid option: $1 requires an argument." >&2
usage
exit 2
elif [[ "$2" != :* ]]; then
echo "Error|Invalid option: $1 argument requires a colon." >&2
usage
exit 2
fi
export striptracks_audiokeep="$2"
shift 2
;;
-s|--subs|--subtitles ) # Subtitles languages to keep
if [ -z "$2" ] || [ ${2:0:1} = "-" ]; then
echo "Error|Invalid option: $1 requires an argument." >&2
usage
exit 3
elif [[ "$2" != :* ]]; then
echo "Error|Invalid option: $1 argument requires a colon." >&2
usage
exit 3
fi
export striptracks_subskeep="$2"
shift 2
;;
-c|--config ) # *arr XML configuration file
if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then
# Overrides default /config/config.xml
export striptracks_arr_config="$2"
shift 2
else
echo "Error|Invalid option: $1 requires an argument." >&2
usage
exit 1
fi
;;
--reorder ) # Reorder audio and subtitles tracks
export striptracks_reorder="true"
shift
;;
-*) # Unknown option
echo "Error|Unknown option: $1" >&2
usage
exit 20
;;
*) # preserve positional arguments
striptracks_pos_params="$striptracks_pos_params $1"
shift
;;
esac
done
# Set positional arguments in their proper place
eval set -- "$striptracks_pos_params"
# Check for and assign positional arguments. Named override positional.
if [ -n "$1" ]; then
if [ -n "$striptracks_audiokeep" ]; then
echo "Warning|Both positional and named arguments set for audio. Using $striptracks_audiokeep" >&2
else
striptracks_audiokeep="$1"
fi
fi
if [ -n "$2" ]; then
if [ -n "$striptracks_subskeep" ]; then
echo "Warning|Both positional and named arguments set for subtitles. Using $striptracks_subskeep" >&2
else
striptracks_subskeep="$2"
fi
fi
## Mode specific variables
if [[ "${striptracks_type,,}" = "batch" ]]; then
# Batch mode
export batch_eventtype="Convert"
export striptracks_title="$(basename "$striptracks_video" ".${striptracks_video##*.}")"
elif [[ "${striptracks_type,,}" = "radarr" ]]; then
# Radarr mode
# shellcheck disable=SC2154
export striptracks_video="$radarr_moviefile_path"
# shellcheck disable=SC2154
export striptracks_video_folder="$radarr_movie_path"
export striptracks_video_api="movie"
# shellcheck disable=SC2154
export striptracks_video_id="${radarr_movie_id}"
export striptracks_videofile_api="moviefile"
# shellcheck disable=SC2154
export striptracks_videofile_id="${radarr_moviefile_id}"
# shellcheck disable=SC2154
export striptracks_rescan_id="${radarr_movie_id}"
export striptracks_json_quality_root="movieFile"
export striptracks_video_type="movie"
export striptracks_video_rootNode=""
# shellcheck disable=SC2154
export striptracks_title="${radarr_movie_title:-UNKNOWN} (${radarr_movie_year:-UNKNOWN})"
export striptracks_language_jq=".language"
# export striptracks_language_node="languages"
elif [[ "${striptracks_type,,}" = "sonarr" ]]; then
# Sonarr mode
# shellcheck disable=SC2154
export striptracks_video="$sonarr_episodefile_path"
# shellcheck disable=SC2154
export striptracks_video_folder="$sonarr_series_path"
export striptracks_video_api="episode"
# shellcheck disable=SC2154
export striptracks_video_id="${sonarr_episodefile_episodeids}"
export striptracks_videofile_api="episodefile"
# shellcheck disable=SC2154
export striptracks_videofile_id="${sonarr_episodefile_id}"
# shellcheck disable=SC2154
export striptracks_rescan_id="${sonarr_series_id}"
export striptracks_json_quality_root="episodeFile"
export striptracks_video_type="series"
export striptracks_video_rootNode=".series"
# shellcheck disable=SC2154
export striptracks_title="${sonarr_series_title:-UNKNOWN} $(numfmt --format "%02f" ${sonarr_episodefile_seasonnumber:-0})x$(numfmt --format "%02f" ${sonarr_episodefile_episodenumbers:-0}) - ${sonarr_episodefile_episodetitles:-UNKNOWN}"
# export striptracks_language_node="language"
# # Sonarr requires the episodeIds array
# export striptracks_sonarr_json=" \"episodeIds\":[.episodes[].id],"
else
# Called in an unexpected way
echo -e "Error|Unknown or missing '*_eventtype' environment variable: ${striptracks_type}\nNot calling from Radarr/Sonarr? Try using Batch Mode option: -f <file>" >&2
usage
exit 7
fi
export striptracks_rescan_api="Rescan${striptracks_video_type^}"
export striptracks_eventtype="${striptracks_type,,}_eventtype"
export striptracks_newvideo="${striptracks_video%.*}.mkv"
# If this were defined directly in Radarr or Sonarr this would not be needed here
# shellcheck disable=SC2089
striptracks_isocodemap='{"languages":[{"language":{"name":"Any","iso639-2":["any"]}},{"language":{"name":"Afrikaans","iso639-2":["afr"]}},{"language":{"name":"Albanian","iso639-2":["sqi","alb"]}},{"language":{"name":"Arabic","iso639-2":["ara"]}},{"language":{"name":"Bengali","iso639-2":["ben"]}},{"language":{"name":"Bosnian","iso639-2":["bos"]}},{"language":{"name":"Bulgarian","iso639-2":["bul"]}},{"language":{"name":"Catalan","iso639-2":["cat"]}},{"language":{"name":"Chinese","iso639-2":["zho","chi"]}},{"language":{"name":"Croatian","iso639-2":["hrv"]}},{"language":{"name":"Czech","iso639-2":["ces","cze"]}},{"language":{"name":"Danish","iso639-2":["dan"]}},{"language":{"name":"Dutch","iso639-2":["nld","dut"]}},{"language":{"name":"English","iso639-2":["eng"]}},{"language":{"name":"Estonian","iso639-2":["est"]}},{"language":{"name":"Finnish","iso639-2":["fin"]}},{"language":{"name":"Flemish","iso639-2":["nld","dut"]}},{"language":{"name":"French","iso639-2":["fra","fre"]}},{"language":{"name":"German","iso639-2":["deu","ger"]}},{"language":{"name":"Greek","iso639-2":["ell","gre"]}},{"language":{"name":"Hebrew","iso639-2":["heb"]}},{"language":{"name":"Hindi","iso639-2":["hin"]}},{"language":{"name":"Hungarian","iso639-2":["hun"]}},{"language":{"name":"Icelandic","iso639-2":["isl","ice"]}},{"language":{"name":"Indonesian","iso639-2":["ind"]}},{"language":{"name":"Italian","iso639-2":["ita"]}},{"language":{"name":"Japanese","iso639-2":["jpn"]}},{"language":{"name":"Kannada","iso639-2":["kan"]}},{"language":{"name":"Korean","iso639-2":["kor"]}},{"language":{"name":"Latvian","iso639-2":["lav"]}},{"language":{"name":"Lithuanian","iso639-2":["lit"]}},{"language":{"name":"Macedonian","iso639-2":["mac","mkd"]}},{"language":{"name":"Malayalam","iso639-2":["mal"]}},{"language":{"name":"Marathi","iso639-2":["mar"]}},{"language":{"name":"Norwegian","iso639-2":["nno","nob","nor"]}},{"language":{"name":"Persian","iso639-2":["fas","per"]}},{"language":{"name":"Polish","iso639-2":["pol"]}},{"language":{"name":"Portuguese","iso639-2":["por"]}},{"language":{"name":"Portuguese (Brazil)","iso639-2":["por"]}},{"language":{"name":"Romanian","iso639-2":["rum","ron"]}},{"language":{"name":"Russian","iso639-2":["rus"]}},{"language":{"name":"Serbian","iso639-2":["srp"]}},{"language":{"name":"Slovak","iso639-2":["slk","slo"]}},{"language":{"name":"Slovenian","iso639-2":["slv"]}},{"language":{"name":"Spanish","iso639-2":["spa"]}},{"language":{"name":"Spanish (Latino)","iso639-2":["spa"]}},{"language":{"name":"Swedish","iso639-2":["swe"]}},{"language":{"name":"Tagalog","iso639-2":["tgl"]}},{"language":{"name":"Tamil","iso639-2":["tam"]}},{"language":{"name":"Telugu","iso639-2":["tel"]}},{"language":{"name":"Thai","iso639-2":["tha"]}},{"language":{"name":"Turkish","iso639-2":["tur"]}},{"language":{"name":"Ukrainian","iso639-2":["ukr"]}},{"language":{"name":"Vietnamese","iso639-2":["vie"]}},{"language":{"name":"Unknown","iso639-2":["und"]}}]}'
### Functions
# Can still go over striptracks_maxlog if read line is too long
## Must include whole function in subshell for read to work!
function log {(
while read -r
do
# shellcheck disable=2046
echo $(date +"%Y-%m-%d %H:%M:%S.%1N")"|[$striptracks_pid]$REPLY" >>"$striptracks_log"
local striptracks_filesize=$(stat -c %s "$striptracks_log")
if [ $striptracks_filesize -gt $striptracks_maxlogsize ]
then
for i in $(seq $((striptracks_maxlog-1)) -1 0); do
[ -f "${striptracks_log::-4}.$i.txt" ] && mv "${striptracks_log::-4}."{$i,$((i+1))}".txt"
done
[ -f "${striptracks_log::-4}.txt" ] && mv "${striptracks_log::-4}.txt" "${striptracks_log::-4}.0.txt"
touch "$striptracks_log"
fi
done
)}
# Inspired by https://stackoverflow.com/questions/893585/how-to-parse-xml-in-bash
function read_xml {
local IFS=\>
read -r -d \< striptracks_xml_entity striptracks_xml_content
}
# Get Radarr/Sonarr version
function get_version {
local url="$striptracks_api_url/system/status"
[ $striptracks_debug -ge 1 ] && echo "Debug|Getting ${striptracks_type^} version. Calling ${striptracks_type^} API using GET and URL '$url'" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--get "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
if [ "$(echo $striptracks_result | jq -crM '.version?')" != "null" ] && [ "$(echo $striptracks_result | jq -crM '.version?')" != "" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Get video information
function get_video_info {
local url="$striptracks_api_url/$striptracks_video_api/$striptracks_video_id"
[ $striptracks_debug -ge 1 ] && echo "Debug|Getting video information for $striptracks_video_api '$striptracks_video_id'. Calling ${striptracks_type^} API using GET and URL '$url'" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--get "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
if [ $striptracks_curlret -eq 0 -a "$(echo $striptracks_result | jq -crM .hasFile)" = "true" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Get video file information
function get_videofile_info {
local url="$striptracks_api_url/$striptracks_videofile_api/$striptracks_videofile_id"
[ $striptracks_debug -ge 1 ] && echo "Debug|Getting video file information for $striptracks_videofile_api '$striptracks_videofile_id'. Calling ${striptracks_type^} API using GET and URL '$url'" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--get "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
if [ $striptracks_curlret -eq 0 -a "$(echo $striptracks_result | jq -crM .path)" != "null" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Initiate Rescan request
function rescan {
local url="$striptracks_api_url/command"
local data="{\"name\":\"$striptracks_rescan_api\",\"${striptracks_video_type}Id\":$striptracks_rescan_id}"
echo "Info|Calling ${striptracks_type^} API to rescan ${striptracks_video_type}" | log
local i=0
for ((i=1; i <= 5; i++)); do
[ $striptracks_debug -ge 1 ] && echo "Debug|Forcing rescan of $striptracks_video_type '$striptracks_rescan_id'. Calling ${striptracks_type^} API using POST and URL '$url' with data $data" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d "$data" \
"$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
# Exit loop if database is not locked, else wait 1 minute
if [[ ! "$(echo $striptracks_result | jq -jcM .message?)" =~ database\ is\ locked ]]; then
break
else
echo "Warn|Database is locked; system is likely overloaded. Sleeping 1 minute." | log
sleep 60
fi
done
striptracks_jobid="$(echo $striptracks_result | jq -crM .id)"
if [ $striptracks_curlret -eq 0 -a "$striptracks_jobid" != "null" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Check result of command job
function check_job {
# Exit codes:
# 0 - success
# 1 - queued
# 2 - failed
# 3 - loop timed out
# 10 - curl error
local url="$striptracks_api_url/command/$striptracks_jobid"
local i=0
[ $striptracks_debug -ge 1 ] && echo "Debug|Checking job $striptracks_jobid completion. Calling ${striptracks_type^} API using GET and URL '$url'" | log
for ((i=1; i <= 15; i++)); do
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--get "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
local striptracks_return=10
break
}
[ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
# Guard clauses
if [ "$(echo $striptracks_result | jq -crM .status)" = "failed" ]; then
local striptracks_return=2
break
fi
if [ "$(echo $striptracks_result | jq -crM .status)" = "queued" ]; then
local striptracks_return=1
break
fi
if [ "$(echo $striptracks_result | jq -crM .status)" = "completed" ]; then
local striptracks_return=0
break
fi
# It may have timed out, so let's wait a second
[ $striptracks_debug -ge 1 ] && echo "Debug|Job not done. Waiting 1 second." | log
local striptracks_return=3
sleep 1
done
return $striptracks_return
}
# Get profiles
function get_profiles {
local url="$striptracks_api_url/${1}profile"
[ $striptracks_debug -ge 1 ] && echo "Debug|Getting list of $1 profiles. Calling ${striptracks_type^} API using GET and URL '$url'" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--get "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
# This returns A LOT of data, and it is normally not needed for debugging
[ $striptracks_debug -ge 2 ] && echo "Debug|API returned ${#striptracks_result} bytes." | log
[ $striptracks_debug -ge 3 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
if [ $striptracks_curlret -eq 0 -a "$(echo $striptracks_result | jq -crM '.message?')" != "NotFound" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Get language codes
function get_language_codes {
local url="$striptracks_api_url/language"
if check_compat languageprofile; then
local url="$striptracks_api_url/languageprofile"
fi
[ $striptracks_debug -ge 1 ] && echo "Debug|Getting list of language codes. Calling ${striptracks_type^} API using GET and URL '$url'" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--get "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
# This returns more data than is normally needed for debugging
[ $striptracks_debug -ge 2 ] && echo "Debug|API returned ${#striptracks_result} bytes." | log
[ $striptracks_debug -ge 3 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
if [ $striptracks_curlret -eq 0 -a "$(echo $striptracks_result | jq -crM '.[] | .name')" != "null" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Get custom formats
function get_custom_formats {
local url="$striptracks_api_url/customformat"
[ $striptracks_debug -ge 1 ] && echo "Debug|Getting list of Custom Formats. Calling ${striptracks_type^} API using GET and URL '$url'" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--get "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
# This returns more data than is normally needed for debugging
[ $striptracks_debug -ge 2 ] && echo "Debug|API returned ${#striptracks_result} bytes." | log
[ $striptracks_debug -ge 3 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
if [ $striptracks_curlret -eq 0 -a "$(echo $striptracks_result | jq -crM '.[] | .name')" != "null" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Delete track
function delete_video {
local url="$striptracks_api_url/$striptracks_videofile_api/$1"
local i=0
for ((i=1; i <= 5; i++)); do
[ $striptracks_debug -ge 1 ] && echo "Debug|Deleting or recycling \"$striptracks_video\". Calling ${striptracks_type^} API using DELETE and URL '$url'" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-X DELETE "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
# Exit loop if database is not locked, else wait 1 minute
if [[ ! "$(echo $striptracks_result | jq -jcM .message?)" =~ database\ is\ locked ]]; then
break
else
echo "Warn|Database is locked; system is likely overloaded. Sleeping 1 minute." | log
sleep 60
fi
done
if [ $striptracks_curlret -eq 0 ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# # Get file details on possible files to import into Radarr/Sonarr
# function get_import_info {
# local url="$striptracks_api_url/manualimport"
# if [[ "${striptracks_type,,}" = "radarr" ]]; then
# local temp_id="${striptracks_video_type}Id=$striptracks_rescan_id"
# fi
# [ $striptracks_debug -ge 1 ] && echo "Debug|Getting list of files that can be imported. Calling ${striptracks_type^} API using GET and URL '$url?${temp_id:+$temp_id&}folder=$striptracks_video_folder&filterExistingFiles=false'" | log
# unset striptracks_result
# # Adding a 'seriesId' to the Sonarr import causes the returned videos to have an 'Unknown' quality. Probably a bug.
# striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
# -H "Content-Type: application/json" \
# -H "Accept: application/json" \
# --data-urlencode "${temp_id}" \
# --data-urlencode "folder=$striptracks_video_folder" \
# -d "filterExistingFiles=false" \
# --get "$url")
# local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
# local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url?${temp_id:+$temp_id&}folder=$striptracks_video_folder&filterExistingFiles=false\"\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
# echo "$striptracks_message" | log
# echo "$striptracks_message" >&2
# }
# [ $striptracks_debug -ge 2 ] && echo "Debug|API returned ${#striptracks_result} bytes." | log
# [ $striptracks_debug -ge 3 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
# if [ $striptracks_curlret -eq 0 -a "${#striptracks_result}" != 0 ]; then
# local striptracks_return=0
# else
# local striptracks_return=1
# fi
# return $striptracks_return
# }
# Update file metadata in Radarr/Sonarr
function set_metadata {
local url="$striptracks_api_url/$striptracks_videofile_api/editor"
local data="$(echo $striptracks_original_metadata | jq -crM "{${striptracks_videofile_api}Ids: [${striptracks_videofile_id}], quality, releaseGroup}")"
local i=0
for ((i=1; i <= 5; i++)); do
[ $striptracks_debug -ge 1 ] && echo "Debug|Updating from quality '$(echo $striptracks_videofile_info | jq -crM .quality.quality.name)' to '$(echo $striptracks_original_metadata | jq -crM .quality.quality.name)' and release group '$(echo $striptracks_videofile_info | jq -crM '.releaseGroup | select(. != null)')' to '$(echo $striptracks_original_metadata | jq -crM '.releaseGroup | select(. != null)')'. Calling ${striptracks_type^} API using PUT and URL '$url' with data $data" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d "$data" \
-X PUT "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "Debug|API returned ${#striptracks_result} bytes." | log
[ $striptracks_debug -ge 3 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
# Exit loop if database is not locked, else wait 1 minute
if [[ ! "$(echo $striptracks_result | jq -jcM .message?)" =~ database\ is\ locked ]]; then
break
else
echo "Warn|Database is locked; system is likely overloaded. Sleeping 1 minute." | log
sleep 60
fi
done
if [ $striptracks_curlret -eq 0 -a "${#striptracks_result}" != 0 ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Read in the output of mkvmerge info extraction (see issue #87)
function get_mediainfo {
[ $striptracks_debug -ge 1 ] && echo "Debug|Executing: /usr/bin/mkvmerge -J \"$1\"" | log
unset striptracks_json
striptracks_json=$(/usr/bin/mkvmerge -J "$1")
local striptracks_return=$?
[ $striptracks_debug -ge 2 ] && echo "mkvmerge returned: $striptracks_json" | awk '{print "Debug|"$0}' | log
case $striptracks_return in
0)
# Check for unsupported container.
if [ "$(echo "$striptracks_json" | jq -crM '.container.supported')" = "false" ]; then
striptracks_message="Error|Video format for '$1' is unsupported. Unable to continue. mkvmerge returned container info: $(echo $striptracks_json | jq -crM .container)"
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 9
fi
;;
1) striptracks_message=$(echo -e "[$striptracks_return] Warning when inspecting video.\nmkvmerge returned: $(echo "$striptracks_json" | jq -crM '.warnings[]')" | awk '{print "Warn|"$0}')
echo "$striptracks_message" | log
;;
2) striptracks_message=$(echo -e "[$striptracks_return] Error when inspecting video.\nmkvmerge returned: $(echo "$striptracks_json" | jq -crM '.errors[]')" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 9
;;
esac
return $striptracks_return
}
# # Import new video into Radarr/Sonarr
# function import_video {
# local url="$striptracks_api_url/command"
# local data="{\"name\":\"ManualImport\",\"files\":$striptracks_json,\"importMode\":\"auto\"}"
# echo "Info|Importing new video \"$striptracks_newvideo\" into ${striptracks_type^}" | log
# [ $striptracks_debug -ge 1 ] && echo "Debug|Importing new file into ${striptracks_type^}. Calling ${striptracks_type^} API using POST and URL '$url' with data $data" | log
# unset striptracks_result
# striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
# -H "Content-Type: application/json" \
# -H "Accept: application/json" \
# -d "$data" \
# "$url")
# local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
# local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
# echo "$striptracks_message" | log
# echo "$striptracks_message" >&2
# }
# [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
# if [ $striptracks_curlret -eq 0 -a "$(echo $striptracks_result | jq .id?)" != "null" ]; then
# local striptracks_return=0
# else
# local striptracks_return=1
# fi
# return $striptracks_return
# }
# Get video files from Radarr/Sonarr that need to be renamed
function get_rename {
local url="$striptracks_api_url/rename"
local data="${striptracks_video_type}Id=$striptracks_rescan_id"
[ $striptracks_debug -ge 1 ] && echo "Debug|Getting list of videos that could be renamed. Calling ${striptracks_type^} API using GET and URL '$url&$data'" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d "$data" \
--get "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url&$data\"\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
if [ $striptracks_curlret -eq 0 -a "$striptracks_result" != "null" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Rename video file according to Radarr/Sonarr naming rules
function rename_video {
local url="$striptracks_api_url/command"
local data="{\"name\":\"RenameFiles\",\"${striptracks_video_type}Id\":$striptracks_rescan_id,\"files\":[$striptracks_videofile_id]}"
echo "Info|Renaming new video file per ${striptracks_type^}'s rules to \"$(basename "$striptracks_renamedvideo")\"" | log
[ $striptracks_debug -ge 1 ] && echo "Debug|Renaming \"$striptracks_newvideo\". Calling ${striptracks_type^} API using POST and URL '$url' with data $data" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d "$data" \
"$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
if [ $striptracks_curlret -eq 0 -a "$striptracks_result" != "null" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Set video language in Radarr
function set_radarr_language {
local url="$striptracks_api_url/$striptracks_videofile_api/editor"
local data="{\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"languages\":${striptracks_json_languages}}"
[ $striptracks_debug -ge 1 ] && echo "Debug|Updating from language(s) '$(echo $striptracks_videofile_info | jq -crM "[.languages[].name] | join(\",\")")' to '$(echo $striptracks_json_languages | jq -crM "[.[].name] | join(\",\")")'. Calling ${striptracks_type^} API using PUT and URL '$url' with data $data" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d "$data" \
-X PUT "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
if [ $striptracks_curlret -eq 0 -a "$striptracks_result" != "null" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Set video language in Sonarr
function set_sonarr_language {
local url="$striptracks_api_url/$striptracks_videofile_api/editor"
local data="{\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"language\":$(echo $striptracks_json_languages | jq -crM ".[0]")}"
[ $striptracks_debug -ge 1 ] && echo "Debug|Updating from language '$(echo $striptracks_videofile_info | jq -crM ".language.name")' to '$(echo $striptracks_json_languages | jq -crM ".[0].name")'. Calling ${striptracks_type^} API using PUT and URL '$url' with data $data" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d "$data" \
-X PUT "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
if [ $striptracks_curlret -eq 0 -a "$striptracks_result" != "null" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Compatibility checker
function check_compat {
# return of 1 = the feature is incompatible
local striptracks_return=1
case "$1" in
apiv3)
[ ${striptracks_arr_version/.*/} -ge 3 ] && local striptracks_return=0
;;
languageprofile)
# Langauge Profiles
[ "${striptracks_type,,}" = "sonarr" ] && [ ${striptracks_arr_version/.*/} -eq 3 ] && local striptracks_return=0
;;
customformat)
# Language option in Custom Formats
[ "${striptracks_type,,}" = "radarr" ] && [ ${striptracks_arr_version/.*/} -ge 3 ] && local striptracks_return=0
[ "${striptracks_type,,}" = "sonarr" ] && [ ${striptracks_arr_version/.*/} -ge 4 ] && local striptracks_return=0
;;
originallanguage)
# Original language selection
[ "${striptracks_type,,}" = "radarr" ] && [ ${striptracks_arr_version/.*/} -ge 3 ] && local striptracks_return=0
[ "${striptracks_type,,}" = "sonarr" ] && [ ${striptracks_arr_version/.*/} -ge 4 ] && local striptracks_return=0
;;
qualitylanguage)
# Language option in Quality Profile
[ "${striptracks_type,,}" = "radarr" ] && [ ${striptracks_arr_version/.*/} -ge 3 ] && local striptracks_return=0
;;
*) # Unknown feature
local striptracks_message="Error|Unknown feature $1 in ${striptracks_type^}"
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
;;
esac
[ $striptracks_debug -ge 1 ] && echo "Debug|Feature $1 is $([ $striptracks_return -eq 1 ] && echo "not ")compatible with ${striptracks_type^} v${striptracks_arr_version}" | log
return $striptracks_return
}
# Get media management configuration
function get_media_config {
local url="$striptracks_api_url/config/mediamanagement"
[ $striptracks_debug -ge 1 ] && echo "Debug|Getting ${striptracks_type^} configuration. Calling ${striptracks_type^} API using GET and URL '$url'" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--get "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
if [ "$(echo $striptracks_result | jq -crM '.id?')" != "null" ] && [ "$(echo $striptracks_result | jq -crM '.id?')" != "" ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Update file metadata in Radarr/Sonarr
function set_video_info {
local url="$striptracks_api_url/$striptracks_video_api/$striptracks_video_id"
local data="$(echo $striptracks_videoinfo | jq -crM .monitored="$striptracks_videomonitored")"
local i=0
for ((i=1; i <= 5; i++)); do
[ $striptracks_debug -ge 1 ] && echo "Debug|Updating monitored to '$striptracks_videomonitored'. Calling ${striptracks_type^} API using PUT and URL '$url' with data $data" | log
unset striptracks_result
striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d "$data" \
-X PUT "$url")
local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && {
local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -jcM .message?)" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
}
[ $striptracks_debug -ge 2 ] && echo "Debug|API returned ${#striptracks_result} bytes." | log
[ $striptracks_debug -ge 3 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log
# Exit loop if database is not locked, else wait 1 minute
if [[ ! "$(echo $striptracks_result | jq -jcM .message?)" =~ database\ is\ locked ]]; then
break
else
echo "Warn|Database is locked; system is likely overloaded. Sleeping 1 minute." | log
sleep 60
fi
done
if [ $striptracks_curlret -eq 0 -a "${#striptracks_result}" != 0 ]; then
local striptracks_return=0
else
local striptracks_return=1
fi
return $striptracks_return
}
# Handle :org language code
function process_org_code {
local striptracks_track_type="$1" # 'audio' or 'subtitles'
local striptracks_keep_var="$2" # Variable name, e.g., striptracks_audiokeep or striptracks_subskeep
if [[ "${!striptracks_keep_var}" =~ :org ]]; then
# Check compatibility
if [ "${striptracks_type,,}" = "batch" ]; then
local striptracks_message="Warn|${striptracks_track_type^} argument contains ':org' code, but this is undefined for Batch mode! Unexpected behavior may result."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
elif ! check_compat originallanguage; then
local striptracks_message="Warn|${striptracks_track_type^} argument contains ':org' code, but this is undefined and not compatible with this mode/version! Unexpected behavior may result."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
fi
# Log debug message if applicable
[ "$striptracks_debug" -ge 1 ] && echo "Debug|${striptracks_track_type^} argument ':org' specified. Changing '${!striptracks_keep_var}' to '${!striptracks_keep_var//:org/${striptracks_originalLangCode}}'" | log
# Replace :org with the original language code
declare -g "$striptracks_keep_var=${!striptracks_keep_var//:org/${striptracks_originalLangCode}}"
fi
}
# Exit program
function end_script {
# Cool bash feature
striptracks_message="Info|Completed in $((SECONDS/60))m $((SECONDS%60))s"
echo "$striptracks_message" | log
[ "$1" != "" ] && striptracks_exitstatus=$1
[ $striptracks_debug -ge 1 ] && echo "Debug|Exit code ${striptracks_exitstatus:-0}" | log
exit ${striptracks_exitstatus:-0}
}
### End Functions
# Check that log path exists
if [ ! -d "$(dirname $striptracks_log)" ]; then
[ $striptracks_debug -ge 1 ] && echo "Debug|Log file path does not exist: '$(dirname $striptracks_log)'. Using log file in current directory."
striptracks_log=./striptracks.txt
fi
# Check that the log file exists
if [ ! -f "$striptracks_log" ]; then
echo "Info|Creating a new log file: $striptracks_log"
touch "$striptracks_log"
fi
# Check that the log file is writable
if [ ! -w "$striptracks_log" ]; then
echo "Error|Log file '$striptracks_log' is not writable or does not exist." >&2
striptracks_log=/dev/null
striptracks_exitstatus=12
fi
# Check for required binaries
for striptracks_file in "/usr/bin/mkvmerge" "/usr/bin/mkvpropedit" "/usr/bin/jq"; do
if [ ! -f "$striptracks_file" ]; then
striptracks_message="Error|$striptracks_file is required by this script"
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 4
fi
done
# Log Debug state
if [ $striptracks_debug -ge 1 ]; then
striptracks_message="Debug|Enabling debug logging level ${striptracks_debug}. Starting run for: $striptracks_title"
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
fi
# Log command line parameters
if [ -n "$striptracks_prelogmessagedebug" ]; then
# striptracks_prelogmessagedebug is set above, before argument processing
[ $striptracks_debug -ge 1 ] && echo "$striptracks_prelogmessagedebug" | log
fi
# Log STRIPTRACKS_ARGS usage
if [ -n "$striptracks_prelogmessage" ]; then
# striptracks_prelogmessage is set above, before argument processing
echo "$striptracks_prelogmessage" | log
[ $striptracks_debug -ge 1 ] && echo "Debug|STRIPTRACKS_ARGS: ${STRIPTRACKS_ARGS}" | log
fi
# Log environment
[ $striptracks_debug -ge 2 ] && printenv | sort | sed 's/^/Debug|/' | log
# Check for invalid _eventtypes
if [[ "${!striptracks_eventtype}" =~ Grab|Rename|MovieAdded|MovieDelete|MovieFileDelete|SeriesAdd|SeriesDelete|EpisodeFileDelete|HealthIssue|ApplicationUpdate ]]; then
striptracks_message="Error|${striptracks_type^} event ${!striptracks_eventtype} is not supported. Exiting."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 20
fi
# Check for WSL environment
if [ -n "$WSL_DISTRO_NAME" ]; then
[ $striptracks_debug -ge 1 ] && echo "Debug|Running in virtual WSL $WSL_DISTRO_NAME distribution." | log
# Adjust config file location to WSL default
if [ ! -f "$striptracks_arr_config" ]; then
striptracks_arr_config="/mnt/c/ProgramData/${striptracks_type^}/config.xml"
[ $striptracks_debug -ge 1 ] && echo "Debug|Will try to use the default WSL configuration file '$striptracks_arr_config'" | log
fi
fi
# Handle Test event
if [[ "${!striptracks_eventtype}" = "Test" ]]; then
echo "Info|${striptracks_type^} event: ${!striptracks_eventtype}" | log
striptracks_message="Info|Script was test executed successfully."
echo "$striptracks_message" | log
echo "$striptracks_message"
end_script 0
fi
# First normal log entry (when there are no errors) (see issue #61)
# shellcheck disable=SC2046
striptracks_filesize=$(stat -c %s "${striptracks_video}" | numfmt --to iec --format "%.3f")
striptracks_message="Info|${striptracks_type^} event: ${!striptracks_eventtype}, Video: $striptracks_video, Size: $striptracks_filesize"
echo "$striptracks_message" | log
# Log Batch mode
if [ "$striptracks_type" = "batch" ]; then
[ $striptracks_debug -ge 1 ] && echo "Debug|Switching to batch mode. Input filename: ${striptracks_video}" | log
fi
# Check for config file
if [ "$striptracks_type" = "batch" ]; then
[ $striptracks_debug -ge 1 ] && echo "Debug|Not using config file in batch mode." | log
elif [ -f "$striptracks_arr_config" ]; then
# Read *arr config.xml
[ $striptracks_debug -ge 1 ] && echo "Debug|Reading from ${striptracks_type^} config file '$striptracks_arr_config'" | log
while read_xml; do
[[ $striptracks_xml_entity = "Port" ]] && striptracks_port=$striptracks_xml_content
[[ $striptracks_xml_entity = "UrlBase" ]] && striptracks_urlbase=$striptracks_xml_content
[[ $striptracks_xml_entity = "BindAddress" ]] && striptracks_bindaddress=$striptracks_xml_content
[[ $striptracks_xml_entity = "ApiKey" ]] && striptracks_apikey=$striptracks_xml_content
done < $striptracks_arr_config
# Allow use of environment variables from https://github.com/Sonarr/Sonarr/pull/6746
striptracks_port_var="${striptracks_type^^}__SERVER__PORT"
[ -n "${!striptracks_port_var}" ] && striptracks_port="${!striptracks_port_var}"
striptracks_urlbase_var="${striptracks_type^^}__SERVER__URLBASE"
[ -n "${!striptracks_urlbase_var}" ] && striptracks_urlbase="${!striptracks_urlbase_var}"
striptracks_bindaddress_var="${striptracks_type^^}__SERVER__BINDADDRESS"
[ -n "${!striptracks_bindaddress_var}" ] && striptracks_bindaddress="${!striptracks_bindaddress_var}"
striptracks_apikey_var="${striptracks_type^^}__AUTH__APIKEY"
[ -n "${!striptracks_apikey_var}" ] && striptracks_apikey="${!striptracks_apikey_var}"
# Check for WSL environment and adjust bindaddress if not otherwise specified
if [ -n "$WSL_DISTRO_NAME" -a "$striptracks_bindaddress" = "*" ]; then
striptracks_bindaddress=$(ip route show | grep -i default | awk '{ print $3}')
fi
# Check for localhost
[[ $striptracks_bindaddress = "*" ]] && striptracks_bindaddress=localhost
# Strip leading and trailing forward slashes from URL base (see issue #66)
striptracks_urlbase="$(echo "$striptracks_urlbase" | sed -re 's/^\/+//; s/\/+$//')"
# Build URL to Radarr/Sonarr API (see issue #57)
striptracks_api_url="http://$striptracks_bindaddress:$striptracks_port${striptracks_urlbase:+/$striptracks_urlbase}/api/v3"
# Check Radarr/Sonarr version
get_version
striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
# curl errored out. API calls are really broken at this point.
striptracks_message="Error|[$striptracks_return] Unable to get ${striptracks_type^} version information. It is not safe to continue."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 17
}
striptracks_arr_version="$(echo $striptracks_result | jq -crM .version)"
[ $striptracks_debug -ge 1 ] && echo "Debug|Detected ${striptracks_type^} version $striptracks_arr_version" | log
# Requires API v3
if ! check_compat apiv3; then
# Radarr/Sonarr version 3 required
striptracks_message="Error|This script does not support ${striptracks_type^} version ${striptracks_arr_version}. Please upgrade."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 8
fi
else
# No config file means we can't call the API. Best effort at this point.
striptracks_message="Warn|Unable to locate ${striptracks_type^} config file: '$striptracks_arr_config'"
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
fi
# Check if video file variable is blank
if [ -z "$striptracks_video" ]; then
striptracks_message="Error|No video file found! radarr_moviefile_path or sonarr_episodefile_path environment variable missing and -f option not specified on command line."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
usage
end_script 1
fi
# Check if source video exists
if [ ! -f "$striptracks_video" ]; then
striptracks_message="Error|Input video file not found: \"$striptracks_video\""
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 5
fi
# Create temporary filename
striptracks_basename="$(basename -- "${striptracks_video}")"
striptracks_fileroot="${striptracks_basename%.*}"
export striptracks_tempvideo="$(dirname -- "${striptracks_video}")/$(mktemp -u -- "${striptracks_fileroot:0:5}.tmp.XXXXXX")"
[ $striptracks_debug -ge 1 ] && echo "Debug|Using temporary file \"$striptracks_tempvideo\"" | log
#### Prep work. Includes detect languages configured in Radarr/Sonarr, quality of video, etc.
# Bypass if using batch mode
if [ "$striptracks_type" = "batch" ]; then
[ $striptracks_debug -ge 1 ] && echo "Debug|Cannot detect languages in batch mode." | log
# Check for URL
elif [ -n "$striptracks_api_url" ]; then
# Get list of all language IDs
if get_language_codes; then
striptracks_lang_codes="$striptracks_result"
# Get video profile
if get_video_info; then
striptracks_videoinfo="$striptracks_result"
striptracks_videomonitored="$(echo "$striptracks_videoinfo" | jq -crM ".monitored")"
# This is not strictly necessary as this is normally set in the environment. However, this is needed for testing scripts and it doesn't hurt to use the data returned by the API call.
striptracks_videofile_id="$(echo $striptracks_videoinfo | jq -crM .${striptracks_json_quality_root}.id)"
# Get video file info. Needed to save the original quality, release group, and custom formats
if get_videofile_info; then
striptracks_videofile_info="$striptracks_result"
# Get quality profile info
if get_profiles quality; then
striptracks_qualityProfiles="$striptracks_result"
# Save original metadata
striptracks_original_metadata="$(echo $striptracks_videofile_info | jq -crM '{quality, releaseGroup}')"
[ $striptracks_debug -ge 1 ] && echo "Debug|Found video file quality '$(echo $striptracks_original_metadata | jq -crM .quality.quality.name)' and release group '$(echo $striptracks_original_metadata | jq -crM '.releaseGroup | select(. != null)')'" | log
# Get language name(s) from quality profile used by video
striptracks_profileId="$(echo $striptracks_videoinfo | jq -crM ${striptracks_video_rootNode}.qualityProfileId)"
striptracks_profileName="$(echo $striptracks_qualityProfiles | jq -crM ".[] | select(.id == $striptracks_profileId).name")"
striptracks_profileLanguages="$(echo $striptracks_qualityProfiles | jq -cM "[.[] | select(.id == $striptracks_profileId) | .language]")"
striptracks_languageSource="quality profile"
[ $striptracks_debug -ge 1 ] && echo "Debug|Found quality profile '${striptracks_profileName} (${striptracks_profileId})'$(check_compat qualitylanguage && echo " with language '$(echo $striptracks_profileLanguages | jq -crM '[.[] | "\(.name) (\(.id | tostring))"] | join(",")')'")" | log
# Query custom formats if returned language from quality profile is null or -1 (Any)
if [ -z "$striptracks_profileLanguages" -o "$striptracks_profileLanguages" = "[null]" -o "$(echo $striptracks_profileLanguages | jq -crM '.[].id')" = "-1" ] && check_compat customformat; then
[ $striptracks_debug -ge 1 -a "$(echo $striptracks_profileLanguages | jq -crM '.[].id')" = "-1" ] && echo "Debug|Language selection of 'Any' in quality profile. Deferring to Custom Format language selection if it exists." | log
# Get list of Custom Formats, and hopefully languages
get_custom_formats
striptracks_customFormats="$striptracks_result"
[ $striptracks_debug -ge 1 ] && echo "Debug|Processing custom format(s) '$(echo "$striptracks_customFormats" | jq -crM '[.[] | select(.specifications[].implementation == "LanguageSpecification") | .name] | unique | join(",")')'" | log
# Pick our languages by combining data from quality profile and custom format configuration.
# I'm open to suggestions if there's a better way to get this list or selected languages.
# Did I mention that JQ is crazy hard?
striptracks_qcf_langcodes=$(echo "$striptracks_qualityProfiles $striptracks_customFormats" | jq -s -crM --argjson ProfileId $striptracks_profileId '
[
# This combines the custom formats [1] with the quality profiles [0], iterating over custom formats that
# specify languages and evaluating the scoring from the selected quality profile.
(
.[1] | .[] |
{id, specs: [.specifications[] | select(.implementation == "LanguageSpecification") | {langCode: .fields[] | select(.name == "value").value, negate, except: ((.fields[] | select(.name == "exceptLanguage").value) // false)}]}
) as $CustomFormat |
.[0] | .[] |
select(.id == $ProfileId) | .formatItems[] | select(.format == $CustomFormat.id) |
{format, name, score, specs: $CustomFormat.specs}
] |
[
# Only count languages with positive scores plus languages with negative scores that are negated, and
# languages with negative scores that use Except
.[] |
(select(.score > 0) | .specs[] | select(.negate == false and .except == false)),
(select(.score < 0) | .specs[] | select(.negate == true and .except == false)),
(select(.score < 0) | .specs[] | select(.negate == false and .except == true)) |
.langCode
] |
unique | join(",")
')
[ $striptracks_debug -ge 2 ] && echo "Debug|Custom format language code(s) '$striptracks_qcf_langcodes' were selected based on quality profile scores." | log
if [ -n "$striptracks_qcf_langcodes" ]; then
# Convert the language codes into language code/name pairs
striptracks_profileLanguages="$(echo $striptracks_lang_codes | jq -crM "map(select(.id | inside($striptracks_qcf_langcodes)) | {id, name})")"
striptracks_languageSource="custom format"
[ $striptracks_debug -ge 1 ] && echo "Debug|Found custom format language(s) '$(echo $striptracks_profileLanguages | jq -crM '[.[] | "\(.name) (\(.id | tostring))"] | join(",")')'" | log
else
[ $striptracks_debug -ge 1 ] && echo "Debug|None of the applied custom formats have language conditions with usable scores." | log
fi
fi
# Check if the languageprofile API is supported (only in legacy Sonarr; but it was *way* better than Custom Formats <sigh>)
if [ -z "$striptracks_profileLanguages" -o "$striptracks_profileLanguages" = "[null]" ] && check_compat languageprofile; then
[ $striptracks_debug -ge 1 ] && echo "Debug|No language found in quality profile or in custom formats. This is normal in legacy versions of Sonarr." | log
if get_profiles language; then
striptracks_languageProfiles="$striptracks_result"
# Get language name(s) from language profile used by video
striptracks_profileId="$(echo $striptracks_videoinfo | jq -crM .series.languageProfileId)"
striptracks_profileName="$(echo $striptracks_languageProfiles | jq -crM ".[] | select(.id == $striptracks_profileId).name")"
striptracks_profileLanguages="$(echo $striptracks_languageProfiles | jq -cM "[.[] | select(.id == $striptracks_profileId) | .languages[] | select(.allowed).language]")"
striptracks_languageSource="language profile"
[ $striptracks_debug -ge 1 ] && echo "Debug|Found language profile '(${striptracks_profileId}) ${striptracks_profileName}' with language(s) '$(echo $striptracks_profileLanguages | jq -crM '[.[].name] | join(",")')'" | log
else
# languageProfile API failed
striptracks_message="Warn|The 'languageprofile' API returned an error."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
fi
fi
# Check if after all of the above we still couldn't get any languages
if [ -z "$striptracks_profileLanguages" -o "$striptracks_profileLanguages" = "[null]" ]; then
striptracks_message="Warn|No languages found in any profile or custom format. Unable to use automatic language detection."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=20
else
# Final determination of configured languages in profiles or custom formats
striptracks_profileLangNames="$(echo $striptracks_profileLanguages | jq -crM '[.[].name]')"
[ $striptracks_debug -ge 1 ] && echo "Debug|Determined ${striptracks_type^} configured language(s) of '$(echo $striptracks_profileLanguages | jq -crM '[.[] | "\(.name) (\(.id | tostring))"] | join(",")')' from $striptracks_languageSource" | log
fi
# Get originalLanguage of video
if check_compat originallanguage; then
striptracks_originalLangName="$(echo $striptracks_videoinfo | jq -crM ${striptracks_video_rootNode}.originalLanguage.name)"
# shellcheck disable=SC2090
striptracks_originalLangCode="$(echo $striptracks_isocodemap | jq -jcM ".languages[] | select(.language.name == \"$striptracks_originalLangName\") | .language | \":\(.\"iso639-2\"[])\"")"
[ $striptracks_debug -ge 1 ] && echo "Debug|Found original video language of '$striptracks_originalLangName ($striptracks_originalLangCode)' from $striptracks_video_type '$striptracks_rescan_id'" | log
fi
# Map language names to ISO code(s) used by mkvmerge
unset striptracks_profileLangCodes
for striptracks_templang in $(echo $striptracks_profileLangNames | jq -crM '.[]'); do
# Convert 'Original' language selection to specific video language
if [ "$striptracks_templang" = "Original" ]; then
striptracks_templang="$striptracks_originalLangName"
fi
# shellcheck disable=SC2090
striptracks_profileLangCodes+="$(echo $striptracks_isocodemap | jq -jcM ".languages[] | select(.language.name == \"$striptracks_templang\") | .language | \":\(.\"iso639-2\"[])\"")"
done
[ $striptracks_debug -ge 1 ] && echo "Debug|Mapped $striptracks_languageSource language(s) '$(echo $striptracks_profileLangNames | jq -crM "join(\",\")")' to ISO639-2 code list '$striptracks_profileLangCodes'" | log
else
# Get qualityprofile API failed
striptracks_message="Warn|Unable to retrieve quality profiles from ${striptracks_type^} API"
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
fi
else
# No '.path' in returned JSON
striptracks_message="Warn|The '$striptracks_videofile_api' API with id $striptracks_videofile_id returned no path."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=20
fi
else
# 'hasFile' is False in returned JSON.
striptracks_message="Warn|Could not find a video file for $striptracks_video_api id '$striptracks_video_id'"
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
fi
else
# Get language codes API failed
striptracks_message="Warn|Unable to retrieve language codes from 'language' API (curl error or returned a null name)."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
fi
# Check if Radarr/Sonarr are configured to unmonitor deleted videos
get_media_config
striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
# No '.id' in returned JSON
striptracks_message="Warn|The Media Management Config API returned no id."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
}
if [ "$(echo "$striptracks_result" | jq -crM ".autoUnmonitorPreviouslyDownloaded${striptracks_video_api^}s")" = "true" ]; then
striptracks_message="Warn|Will compensate for ${striptracks_type^} configuration to unmonitor deleted ${striptracks_video_api}s."
echo "$striptracks_message" | log
fi
else
# No URL means we can't call the API
striptracks_message="Warn|Unable to determine ${striptracks_type^} API URL."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=20
fi
# Special handling for ':org' code from command line.
process_org_code "audio" "striptracks_audiokeep"
process_org_code "subtitles" "striptracks_subskeep"
# Final assignment of audio and subtitles selection
## Guard clause
if [ -z "$striptracks_audiokeep" -a -z "$striptracks_profileLangCodes" ]; then
striptracks_message="Error|No audio languages specified or detected!"
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
usage
end_script 2
fi
## Allows command line argument to override detected languages
if [ -z "$striptracks_audiokeep" -a -n "$striptracks_profileLangCodes" ]; then
[ $striptracks_debug -ge 1 ] && echo "Debug|No command line audio languages specified. Using code list '$striptracks_profileLangCodes'" | log
striptracks_audiokeep="$striptracks_profileLangCodes"
else
[ $striptracks_debug -ge 1 ] && echo "Debug|Using command line audio languages '$striptracks_audiokeep'" | log
fi
## Log configuration that removes all subtitles
if [ -z "$striptracks_subskeep" -a -z "$striptracks_profileLangCodes" ]; then
striptracks_message="Info|No subtitles languages specified or detected. Removing all subtitles found."
echo "$striptracks_message" | log
striptracks_subskeep="null"
fi
## Allows command line argument to override detected languages
if [ -z "$striptracks_subskeep" -a -n "$striptracks_profileLangCodes" ]; then
[ $striptracks_debug -ge 1 ] && echo "Debug|No command line subtitle languages specified. Using code list '$striptracks_profileLangCodes'" | log
striptracks_subskeep="$striptracks_profileLangCodes"
else
[ $striptracks_debug -ge 1 ] && echo "Debug|Using command line subtitle languages '$striptracks_subskeep'" | log
fi
# Display what we're doing
striptracks_message="Info|Keeping audio tracks with codes '$(echo $striptracks_audiokeep | sed -e 's/^://; s/:/,/g')' and subtitle tracks with codes '$(echo $striptracks_subskeep | sed -e 's/^://; s/:/,/g')'"
echo "$striptracks_message" | log
#### BEGIN MAIN
# Read in the output of mkvmerge info extraction
# Populates the striptracks_json variable
get_mediainfo "$striptracks_video"
# Process JSON data from MKVmerge; track selection logic
striptracks_json_processed=$(echo "$striptracks_json" | jq -jcM --arg AudioKeep "$striptracks_audiokeep" \
--arg SubsKeep "$striptracks_subskeep" '
# Parse input string into JSON language rules function
def parse_language_codes(codes):
# Supports f, d, and number modifiers (see issues #82 and #86)
# -1 default value in language key means to keep unlimited tracks
# NOTE: Logic can result in duplicate keys, but jq just uses the last defined key
codes | split(":")[1:] | map(split("+") | {lang: .[0], mods: .[1]}) |
{languages: map(
# Select tracks with no modifiers or only numeric modifiers
(select(.mods == null) | {(.lang): -1}),
(select(.mods | test("^[0-9]+$")?) | {(.lang): .mods | tonumber})
) | add,
forced_languages: map(
# Select tracks with f modifier
select(.mods | contains("f")?) | {(.lang): ((.mods | scan("[0-9]+") | tonumber) // -1)}
) | add,
default_languages: map(
# Select tracks with d modifier
select(.mods | contains("d")?) | {(.lang): ((.mods | scan("[0-9]+") | tonumber) // -1)}
) | add
};
# Language rules for audio and subtitles, adding required audio tracks (see issue #54)
(parse_language_codes($AudioKeep) | .languages += {"mis":-1,"zxx":-1}) as $AudioRules |
parse_language_codes($SubsKeep) as $SubsRules |
# Log chapter information
if (.chapters[0].num_entries) then
.striptracks_log = "Info|Chapters: \(.chapters[].num_entries)"
else . end |
# Process tracks
reduce .tracks[] as $track (
# Create object to hold tracks and counters for each reduce iteration
# This is what will be output at the end of the reduce loop
{"tracks": [], "counters": {"audio": {"normal": {}, "forced": {}, "default": {}}, "subtitles": {"normal": {}, "forced": {}, "default": {}}}};
# Set track language to "und" if null or empty
# NOTE: The // operator cannot be used here because it checks for null or empty values, not blank strings
(if ($track.properties.language == "" or $track.properties.language == null) then "und" else $track.properties.language end) as $track_lang |
# Initialize counters for each track type and language
(.counters[$track.type].normal[$track_lang] //= 0) |
if $track.properties.forced_track then (.counters[$track.type].forced[$track_lang] //= 0) else . end |
if $track.properties.default_track then (.counters[$track.type].default[$track_lang] //= 0) else . end |
.counters[$track.type] as $track_counters |
# Add tracks one at a time to output object above
.tracks += [
$track |
.striptracks_debug_log = "Debug|Parsing track ID:\(.id) Type:\(.type) Name:\(.properties.track_name) Lang:\($track_lang) Codec:\(.codec) Default:\(.properties.default_track) Forced:\(.properties.forced_track)" |
# Use track language evaluation above
.properties.language = $track_lang |
# Determine keep logic based on type and rules
if .type == "video" then
.striptracks_keep = true
elif .type == "audio" or .type == "subtitles" then
.striptracks_log = "\(.id): \($track_lang) (\(.codec))\(if .properties.track_name then " \"" + .properties.track_name + "\"" else "" end)" |
# Same logic for both audio and subtitles
(if .type == "audio" then $AudioRules else $SubsRules end) as $currentRules |
if ($currentRules.languages["any"] == -1 or ($track_counters.normal | add) < $currentRules.languages["any"] or
$currentRules.languages[$track_lang] == -1 or $track_counters.normal[$track_lang] < $currentRules.languages[$track_lang]) then
.striptracks_keep = true
elif (.properties.forced_track and
($currentRules.forced_languages["any"] == -1 or ($track_counters.forced | add) < $currentRules.forced_languages["any"] or
$currentRules.forced_languages[$track_lang] == -1 or $track_counters.forced[$track_lang] < $currentRules.forced_languages[$track_lang])) then
.striptracks_keep = true |
.striptracks_rule = "forced"
elif (.properties.default_track and
($currentRules.default_languages["any"] == -1 or ($track_counters.default | add) < $currentRules.default_languages["any"] or
$currentRules.default_languages[$track_lang] == -1 or $track_counters.default[$track_lang] < $currentRules.default_languages[$track_lang])) then
.striptracks_keep = true |
.striptracks_rule = "default"
else . end |
if .striptracks_keep then
.striptracks_log = "Info|Keeping \(if .striptracks_rule then .striptracks_rule + " " else "" end)\(.type) track " + .striptracks_log
else
.striptracks_keep = false
end
else . end
] |
# Increment counters for each track type and language
.counters[$track.type].normal[$track_lang] +=
if .tracks[-1].striptracks_keep then
1
else 0 end |
.counters[$track.type].forced[$track_lang] +=
if ($track.properties.forced_track and .tracks[-1].striptracks_keep) then
1
else 0 end |
.counters[$track.type].default[$track_lang] +=
if ($track.properties.default_track and .tracks[-1].striptracks_keep) then
1
else 0 end
) |
# Ensure at least one audio track is kept
if ((.tracks | map(select(.type == "audio")) | length == 1) and (.tracks | map(select(.type == "audio" and .striptracks_keep)) | length == 0)) then
# If there is only one audio track and none are kept, keep the only audio track
.tracks |= map(if .type == "audio" then
.striptracks_log = "Warn|No audio tracks matched! Keeping only audio track " + .striptracks_log |
.striptracks_keep = true
else . end)
elif (.tracks | map(select(.type == "audio" and .striptracks_keep)) | length == 0) then
# If no audio tracks are kept, first try to keep the default audio track
.tracks |= map(if .type == "audio" and .properties.default_track then
.striptracks_log = "Warn|No audio tracks matched! Keeping default audio track " + .striptracks_log |
.striptracks_keep = true
else . end) |
# If still no audio tracks are kept, keep the first audio track
if (.tracks | map(select(.type == "audio" and .striptracks_keep)) | length == 0) then
(first(.tracks[] | select(.type == "audio"))) |= . +
{striptracks_log: ("Warn|No audio tracks matched! Keeping first audio track " + .striptracks_log),
striptracks_keep: true}
else . end
else . end |
# Output simplified dataset
{ striptracks_log, tracks: .tracks | map({ id, type, language: .properties.language, forced: .properties.forced_track, default: .properties.default_track, striptracks_debug_log, striptracks_log, striptracks_keep }) }
')
[ $striptracks_debug -ge 1 ] && echo "Debug|Track processing returned ${#striptracks_json_processed} bytes." | log
[ $striptracks_debug -ge 2 ] && echo "Track processing returned: $(echo "$striptracks_json_processed" | jq)" | awk '{print "Debug|"$0}' | log
# Write messages to log
echo "$striptracks_json_processed" | jq -crM --argjson Debug $striptracks_debug '
# Join log messages into one line function
def log_removed_tracks($type):
if (.tracks | map(select(.type == $type and .striptracks_keep == false)) | length > 0) then
"Info|Removing \($type) tracks: " +
(.tracks | map(select(.type == $type and .striptracks_keep == false) | .striptracks_log) | join(", "))
else empty end;
# Log the chapters, if any
.striptracks_log // empty,
# Log debug messages
( .tracks[] | (if $Debug >= 1 then .striptracks_debug_log else empty end),
# Log messages for kept tracks
(select(.striptracks_keep) | .striptracks_log // empty)
),
# Log removed tracks
log_removed_tracks("audio"),
log_removed_tracks("subtitles"),
# Summary of kept tracks
"Info|Kept tracks: \(.tracks | map(select(.striptracks_keep)) | length) " +
"(audio: \(.tracks | map(select(.type == "audio" and .striptracks_keep)) | length), " +
"subtitles: \(.tracks | map(select(.type == "subtitles" and .striptracks_keep)) | length))"
' | log
# Check for no audio tracks
if [ "$(echo "$striptracks_json_processed" | jq -crM '.tracks|map(select(.type=="audio" and .striptracks_keep))')" = "[]" ]; then
striptracks_message="Error|Unable to determine any audio tracks to keep. Exiting."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 11
fi
# Map current track order
striptracks_order=$(echo "$striptracks_json_processed" | jq -jcM '.tracks | map(.id | "0:" + tostring) | join(",")')
[ $striptracks_debug -ge 1 ] && echo "Debug|Current mkvmerge track order: $striptracks_order" | log
# Prepare to reorder tracks if option is enabled (see issue #92)
if [ "$striptracks_reorder" = "true" ]; then
striptracks_neworder=$(echo "$striptracks_json_processed" | jq -jcM --arg AudioKeep "$striptracks_audiokeep" \
--arg SubsKeep "$striptracks_subskeep" '
# Reorder tracks function
def order_tracks(tracks; rules; tracktype):
rules | split(":")[1:] | map(split("+") | {lang: .[0], mods: .[1]}) |
reduce .[] as $rule (
[];
. as $orderedTracks |
. += [tracks |
map(. as $track |
select(.type == tracktype and .striptracks_keep and
($rule.lang | in({"any":0,($track.language):0})) and
($rule.mods == null or
($rule.mods | test("[fd]") | not) or
($rule.mods | contains("f") and $track.forced) or
($rule.mods | contains("d") and $track.default)
)
) |
.id as $id |
# Remove track id from orderedTracks if it already exists
if ([$id] | flatten | inside($orderedTracks | flatten)) then empty else $id end
)]
) | flatten;
# Reorder audio and subtitles according to language code order
.tracks as $tracks |
order_tracks($tracks; $AudioKeep; "audio") as $audioOrder |
order_tracks($tracks; $SubsKeep; "subtitles") as $subsOrder |
# Output ordered track string compatible with the mkvmerge --track-order option
# Video tracks are always first, followed by audio tracks, then subtitles
# NOTE: Other track types are still preserved as mkvmerge will automatically place any missing tracks after those listed per https://mkvtoolnix.download/doc/mkvmerge.html#d4e544
$tracks | map(select(.type == "video") | .id) + $audioOrder + $subsOrder | map("0:" + tostring) | join(",")
')
[ $striptracks_debug -ge 1 ] && echo "Debug|New mkvmerge track order: $striptracks_neworder" | log
striptracks_message="Info|Reordering tracks using language code order."
echo "$striptracks_message" | log
fi
# All tracks matched/no tracks removed (see issues #49 and #89)
if [ "$(echo "$striptracks_json" | jq -crM '.tracks|map(select(.type=="audio" or .type=="subtitles"))|length')" = "$(echo "$striptracks_json_processed" | jq -crM '.tracks|map(select((.type=="audio" or .type=="subtitles") and .striptracks_keep))|length')" ]; then
[ $striptracks_debug -ge 1 ] && echo "Debug|No tracks will be removed from video \"$striptracks_video\"" | log
# Check if already MKV
if [[ $striptracks_video == *.mkv ]]; then
# Check if reorder option is unset or if the order wouldn't change (see issue #92)
if [ "$striptracks_reorder" != "true" -o "$striptracks_order" = "$striptracks_neworder" ]; then
# Remuxing not performed
striptracks_message="Info|No tracks would be removed from video$( [ "$striptracks_reorder" = "true" ] && echo " or reordered"). Setting Title only and exiting."
echo "$striptracks_message" | log
striptracks_mkvcommand="/usr/bin/mkvpropedit -q --edit info --set \"title=$striptracks_title\" \"$striptracks_video\""
[ $striptracks_debug -ge 1 ] && echo "Debug|Executing: $striptracks_mkvcommand" | log
striptracks_result=$(eval $striptracks_mkvcommand)
striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
striptracks_message=$(echo -e "[$striptracks_return] Error when setting video title: \"$striptracks_tempvideo\"\nmkvpropedit returned: $striptracks_result" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=13
}
end_script
else
# Reorder tracks anyway
striptracks_message="Info|No tracks will be removed from video, but they can be reordered. Remuxing anyway."
echo "$striptracks_message" | log
fi
else
# Not MKV
[ $striptracks_debug -ge 1 ] && echo "Debug|Source video is not MKV. Remuxing anyway." | log
fi
fi
# Test for hardlinked file (see issue #85)
striptracks_refcount=$(stat -c %h "$striptracks_video")
[ $striptracks_debug -ge 1 ] && echo "Debug|Input file has a hard link count of $striptracks_refcount" | log
if [ "$striptracks_refcount" != "1" ]; then
striptracks_message="Warn|Input video file is a hardlink and this will be broken by remuxing."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
fi
# Build argument with kept audio tracks for MKVmerge
striptracks_audioarg=$(echo "$striptracks_json_processed" | jq -crM '.tracks | map(select(.type == "audio" and .striptracks_keep) | .id) | join(",")')
striptracks_audioarg="-a $striptracks_audioarg"
# Build argument with kept subtitles tracks for MKVmerge, or remove all subtitles
striptracks_subsarg=$(echo "$striptracks_json_processed" | jq -crM '.tracks | map(select(.type == "subtitles" and .striptracks_keep) | .id) | join(",")')
if [ ${#striptracks_subsarg} -ne 0 ]; then
striptracks_subsarg="-s $striptracks_subsarg"
else
striptracks_subsarg="-S"
fi
# Build argument for track reorder option for MKVmerge
if [ ${#striptracks_neworder} -ne 0 ]; then
striptracks_neworder="--track-order $striptracks_neworder"
fi
# Execute MKVmerge (remux then rename, see issue #46)
striptracks_mkvcommand="nice /usr/bin/mkvmerge --title \"$striptracks_title\" -q -o \"$striptracks_tempvideo\" $striptracks_audioarg $striptracks_subsarg $striptracks_neworder \"$striptracks_video\""
[ $striptracks_debug -ge 1 ] && echo "Debug|Executing: $striptracks_mkvcommand" | log
striptracks_result=$(eval $striptracks_mkvcommand)
striptracks_return=$?
case $striptracks_return in
1) striptracks_message=$(echo -e "[$striptracks_return] Warning when remuxing video: \"$striptracks_video\"\nmkvmerge returned: $striptracks_result" | awk '{print "Warn|"$0}')
echo "$striptracks_message" | log
;;
2) striptracks_message=$(echo -e "[$striptracks_return] Error when remuxing video: \"$striptracks_video\"\nmkvmerge returned: $striptracks_result" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 13
;;
esac
# Check for non-empty file
if [ ! -s "$striptracks_tempvideo" ]; then
striptracks_message="Error|Unable to locate or invalid remuxed file: \"$striptracks_tempvideo\". Halting."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 10
fi
# Checking that we're running as root
if [ "$(id -u)" -eq 0 ]; then
# Set owner
[ $striptracks_debug -ge 1 ] && echo "Debug|Changing owner of file \"$striptracks_tempvideo\"" | log
striptracks_result=$(chown --reference="$striptracks_video" "$striptracks_tempvideo")
striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
striptracks_message=$(echo -e "[$striptracks_return] Error when changing owner of file: \"$striptracks_tempvideo\"\nchown returned: $striptracks_result" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=15
}
else
# Unable to change owner when not running as root
[ $striptracks_debug -ge 1 ] && echo "Debug|Unable to change owner of file when running as user '$(id -un)'" | log
fi
# Set permissions
striptracks_result=$(chmod --reference="$striptracks_video" "$striptracks_tempvideo")
striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
striptracks_message=$(echo -e "[$striptracks_return] Error when changing permissions of file: \"$striptracks_tempvideo\"\nchmod returned: $striptracks_result" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=15
}
# Just delete the original video if running in batch mode
if [ "$striptracks_type" = "batch" ]; then
[ $striptracks_debug -ge 1 ] && echo "Debug|Deleting: \"$striptracks_video\"" | log
striptracks_result=$(rm "$striptracks_video")
striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
striptracks_message=$(echo -e "[$striptracks_return] Error when deleting video: \"$striptracks_video\"\nrm returned: $striptracks_result" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=16
}
else
# Call Radarr/Sonarr to delete the original video, or recycle if configured.
delete_video $striptracks_videofile_id
striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
striptracks_message="Error|[$striptracks_return] ${striptracks_type^} error when deleting the original video: \"$striptracks_video\""
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
}
fi
# Another check for the temporary file, to make sure it wasn't deleted (see issue #65)
if [ ! -f "$striptracks_tempvideo" ]; then
striptracks_message="Error|${striptracks_type^} deleted the temporary remuxed file: \"$striptracks_tempvideo\". Halting."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 10
fi
# Rename the temporary video file to MKV
[ $striptracks_debug -ge 1 ] && echo "Debug|Renaming \"$striptracks_tempvideo\" to \"$striptracks_newvideo\"" | log
striptracks_result=$(mv -f "$striptracks_tempvideo" "$striptracks_newvideo")
striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
striptracks_message=$(echo -e "[$striptracks_return] Unable to rename temp video: \"$striptracks_tempvideo\" to: \"$striptracks_newvideo\". Halting.\nmv returned: $striptracks_result" | awk '{print "Error|"$0}')
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script 6
}
# Get file size (see issue #61)
# shellcheck disable=SC2046
striptracks_filesize=$(stat -c %s "${striptracks_newvideo}" | numfmt --to iec --format "%.3f")
striptracks_message="Info|New size: $striptracks_filesize"
echo "$striptracks_message" | log
#### END MAIN
#### Call Radarr/Sonarr API to RescanMovie/RescanSeries
# Check for URL
if [ "$striptracks_type" = "batch" ]; then
[ $striptracks_debug -ge 1 ] && echo "Debug|Not calling API while in batch mode." | log
elif [ -n "$striptracks_api_url" ]; then
# Check for video IDs
if [ "$striptracks_video_id" -a "$striptracks_videofile_id" ]; then
##### Leaving this here (and all supporting functions and variables) in case the single file import job problem can be resolved.
##### See GitHub Issue #50. Importing directly is a much better way than rescanning.
# Scan for files to import into Radarr/Sonarr
# if get_import_info; then
# # Build JSON data
# [ $striptracks_debug -ge 1 ] && echo "Debug|Building JSON data to import" | log
# striptracks_json=$(echo $striptracks_result | jq -jcM "
# map(
# select(.path == \"$striptracks_newvideo\") |
# {path, folderName, \"${striptracks_video_type}Id\":.${striptracks_video_type}.id,${striptracks_sonarr_json} quality, $striptracks_language_node}
# )
# ")
# # Import new video into Radarr/Sonarr
# import_video
# striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
# striptracks_message="Error|[$striptracks_return] ${striptracks_type^} error when importing new video!"
# echo "$striptracks_message" | log
# echo "$striptracks_message" >&2
# striptracks_exitstatus=17
# }
# striptracks_jobid="$(echo $striptracks_result | jq -crM .id)"
# Check status of job
# Scan the disk for the new movie file
if rescan; then
# Give it a beat
sleep 1
# Check that the Rescan completed
check_job
striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
case $striptracks_return in
1) striptracks_message="Info|${striptracks_type^} job ID $striptracks_jobid is queued. Trusting this will complete and exiting."
striptracks_exitstatus=0
;;
2) striptracks_message="Warn|${striptracks_type^} job ID $striptracks_jobid failed."
striptracks_exitstatus=17
;;
3) striptracks_message="Warn|Script timed out waiting on ${striptracks_type^} job ID $striptracks_jobid. Last status was: $(echo $striptracks_result | jq -crM .status)"
striptracks_exitstatus=18
;;
10) striptracks_message="Error|${striptracks_type^} job ID $striptracks_jobid returned a curl error."
striptracks_exitstatus=17
;;
esac
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
end_script
}
# Get new video file id
if get_video_info; then
striptracks_videoinfo="$striptracks_result"
striptracks_videofile_id="$(echo $striptracks_videoinfo | jq -crM .${striptracks_json_quality_root}.id)"
[ $striptracks_debug -ge 1 ] && echo "Debug|Using new video file id '$striptracks_videofile_id'" | log
# Check if video monitored status changed after the delete/import (see issues #87 and #90)
if [ "$(echo "$striptracks_videoinfo" | jq -crM ".monitored")" != "$striptracks_videomonitored" ]; then
striptracks_message="Warn|Video monitor status changed after deleting the original. Setting it back to '$striptracks_videomonitored'"
echo "$striptracks_message" | log
# Set video monitor state
set_video_info
fi
# Get new video file info
if get_videofile_info; then
striptracks_videofile_info="$striptracks_result"
# Check that the metadata didn't get lost in the rescan.
if [ "$(echo $striptracks_videofile_info | jq -crM .quality.quality.name)" != "$(echo $striptracks_original_metadata | jq -crM .quality.quality.name)" -o "$(echo $striptracks_videofile_info | jq -crM '.releaseGroup | select(. != null)')" != "$(echo $striptracks_original_metadata | jq -crM '.releaseGroup | select(. != null)')" ]; then
# Put back the missing metadata
set_metadata
# Check that the returned result shows the updates
if [ "$(echo $striptracks_result | jq -crM .[].quality.quality.name)" = "$(echo $striptracks_original_metadata | jq -crM .quality.quality.name)" ]; then
# Updated successfully
echo "Info|Successfully updated quality to '$(echo $striptracks_result | jq -crM .[].quality.quality.name)' and release group to '$(echo $striptracks_result | jq -crM '.[].releaseGroup | select(. != null)')'" | log
else
striptracks_message="Warn|Unable to update ${striptracks_type^} $striptracks_video_api '$striptracks_title' to quality '$(echo $striptracks_original_metadata | jq -crM .quality.quality.name)' or release group to '$(echo $striptracks_original_metadata | jq -crM '.releaseGroup | select(. != null)')'"
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
fi
else
# The metadata was already set correctly
[ $striptracks_debug -ge 1 ] && echo "Debug|Metadata quality '$(echo $striptracks_videofile_info | jq -crM .quality.quality.name)' and release group '$(echo $striptracks_videofile_info | jq -crM '.releaseGroup | select(. != null)')' remained unchanged." | log
fi
# Check the languages returned
# If we stripped out other languages, remove them
# Only works in Radarr and Sonarr v4 (no per-episode edit function in Sonarr v3)
[ $striptracks_debug -ge 1 ] && echo "Debug|Getting languages in new video file \"$striptracks_newvideo\"" | log
get_mediainfo "$striptracks_newvideo"
# Build array of full name languages
striptracks_newvideo_langcodes="$(echo $striptracks_json | jq -crM '.tracks[] | select(.type == "audio") | .properties.language')"
unset striptracks_newvideo_languages
for i in $striptracks_newvideo_langcodes; do
# shellcheck disable=SC2090
# Exclude Any, Original, and Unknown
striptracks_newvideo_languages+="$(echo $striptracks_isocodemap | jq -crM ".languages[] | .language | select((.\"iso639-2\"[]) == \"$i\") | select(.name != \"Any\" and .name != \"Original\" and .name != \"Unknown\").name")"
done
if [ -n "$striptracks_newvideo_languages" ]; then
# Covert to standard JSON
striptracks_json_languages="$(echo $striptracks_lang_codes | jq -crM "map(select(.name | inside(\"$striptracks_newvideo_languages\")) | {id, name})")"
# Check languages for Radarr and Sonarr v4
# Sooooo glad I did it this way
if [ "$(echo $striptracks_videofile_info | jq -crM .languages)" != "null" ]; then
if [ "$(echo $striptracks_videofile_info | jq -crM .languages)" != "$striptracks_json_languages" ]; then
if set_radarr_language; then
striptracks_exitstatus=0
else
striptracks_message="Error|${striptracks_type^} error when updating video language(s)."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
fi
else
# The languages are already correct
[ $striptracks_debug -ge 1 ] && echo "Debug|Language(s) '$(echo $striptracks_json_languages | jq -crM "[.[].name] | join(\",\")")' remained unchanged." | log
fi
# Check languages for Sonarr v3 and earlier
elif [ "$(echo $striptracks_videofile_info | jq -crM .language)" != "null" ]; then
if [ "$(echo $striptracks_videofile_info | jq -crM .language)" != "$(echo $striptracks_json_languages | jq -crM '.[0]')" ]; then
if set_sonarr_language; then
striptracks_exitstatus=0
else
striptracks_message="Error|${striptracks_type^} error when updating video language(s)."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
fi
else
# The languages are already correct
[ $striptracks_debug -ge 1 ] && echo "Debug|Language '$(echo $striptracks_json_languages | jq -crM ".[0].name")' remained unchanged." | log
fi
else
# Some unknown JSON formatting
striptracks_message="Warn|The '$striptracks_videofile_api' API returned unknown JSON language node."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=20
fi
elif [ "$striptracks_newvideo_langcodes" = "und" ]; then
# Only language detected is Unknown
echo "Warn|The only audio language in the video file was 'Unknown (und)'. Not updating ${striptracks_type^} database." | log
else
# Video language not in striptracks_isocodemap
striptracks_message="Warn|Video language code(s) '${striptracks_newvideo_langcodes//$'\n'/,}' not found in the ISO Codemap. Cannot evaluate."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=20
fi
# Get list of videos that could be renamed (see issue #50)
get_rename
striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
striptracks_message="Warn|[$striptracks_return] ${striptracks_type^} error when getting list of videos to rename."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
}
# Check if new video is in list of files that can be renamed
if [ -n "$striptracks_result" -a "$striptracks_result" != "[]" ]; then
striptracks_renamedvideo="$(echo $striptracks_result | jq -crM ".[] | select(.${striptracks_json_quality_root}Id == $striptracks_videofile_id) | .newPath")"
# Rename video if needed
if [ -n "$striptracks_renamedvideo" ]; then
rename_video
striptracks_return=$?; [ $striptracks_return -ne 0 ] && {
striptracks_message="Error|[$striptracks_return] ${striptracks_type^} error when renaming \"$(basename "$striptracks_newvideo")\" to \"$(basename "$striptracks_renamedvideo")\""
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
}
else
# This file doesn't need to be
[ $striptracks_debug -ge 1 ] && echo "Debug|This video file doesn't need to be renamed." | log
fi
else
# Nothing to rename
[ $striptracks_debug -ge 1 ] && echo "Debug|No video files need to be renamed." | log
fi
else
# No '.path' in returned JSON
striptracks_message="Warn|The '$striptracks_videofile_api' API with ${striptracks_video_api}File id $striptracks_videofile_id returned no path."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
fi
else
# 'hasFile' is False in returned JSON
striptracks_message="Warn|Could not find a video file for $striptracks_video_api id '$striptracks_video_id'"
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
fi
# else
# striptracks_message="Error|${striptracks_type^} error getting import file list in \"$striptracks_video_folder\" for $striptracks_video_type ID $striptracks_rescan_id. Cannot import remuxed video."
# echo "$striptracks_message" | log
# echo "$striptracks_message" >&2
# striptracks_exitstatus=17
# fi
else
# Error from rescan API
striptracks_message="Error|The '$striptracks_rescan_api' API with ${striptracks_video_type}Id $striptracks_rescan_id failed."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=17
fi
else
# No video ID means we can't call the API
striptracks_message="Warn|Missing or empty environment variable: striptracks_video_id='$striptracks_video_id' or striptracks_videofile_id='$striptracks_videofile_id'. Cannot rescan for remuxed video."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=20
fi
else
# No URL means we can't call the API
striptracks_message="Warn|Unable to determine ${striptracks_type^} API URL."
echo "$striptracks_message" | log
echo "$striptracks_message" >&2
striptracks_exitstatus=20
fi
end_script