Release 2.13..0

This commit is contained in:
TheCaptain989
2025-03-08 10:46:29 -06:00
parent 29c8d67948
commit 2395da4c36
3 changed files with 103 additions and 39 deletions
+20 -19
View File
@@ -1,5 +1,5 @@
# About
A [Docker Mod](https://github.com/linuxserver/docker-mods) for the LinuxServer.io Radarr/Sonarr v3 or higher Docker containers that adds a script to automatically strip out unwanted audio and subtitle tracks, keeping only the desired languages.
A [Docker Mod](https://github.com/linuxserver/docker-mods) for the LinuxServer.io Radarr/Sonarr v3 or higher Docker containers that adds a script to automatically strip out unwanted audio and subtitle tracks, keeping only the desired languages. A [Batch Mode](#batch-mode) is also supported that allows usage outside of Radarr/Sonarr.
**This unified script works in both Radarr and Sonarr. Use this mod in either container!**
@@ -85,7 +85,7 @@ Development Container info:
</details>
The script will detect the language(s) defined in Radarr/Sonarr for the movie or TV show and only keep the audio and subtitles selected.
Alternatively, a wrapper script or an environment variable may be used to more granularly define which tracks to keep. See [Wrapper Scripts](./README.md#wrapper-scripts) or [Environment Variable](./README.md#environment-variable) for more details.
Alternatively, a wrapper script or an environment variable may be used to more granularly define which tracks to keep. See [Wrapper Scripts](#wrapper-scripts) or [Environment Variable](#environment-variable) for more details.
> [!IMPORTANT]
> You **must** configure language(s) in Radarr/Sonarr *or* pass command-line arguments for the script to do anything! See the next section for an example.
@@ -127,7 +127,7 @@ The following is a simplified example and steps to configure Radarr so the scrip
</details>
Now, when Radarr imports a movie with the 'Any' Quality Profile, the script will keep only Original and English languages. This is equivalent to calling the script with `--audio :org:eng --subs :org:eng` command-line arguments.
See [Automatic Language Detection](./README.md#automatic-language-detection) for more details.
See [Automatic Language Detection](#automatic-language-detection) for more details.
# Usage Details
The source video can be any mkvtoolnix supported video format. The output is an MKV file with the same name and the same permissions. Owner is preserved if the script is executed as root.
@@ -157,15 +157,15 @@ Both audio **and** subtitle tracks that match the configured language(s) are kep
### Special Language Selections
The language selection **'Original'** will use the language Radarr pulled from [The Movie Database](https://www.themoviedb.org/ "TMDB") or that Sonarr pulled from [The TVDB](https://www.thetvdb.com/ "TVDB") during its last refresh.
Selecting this language is functionally equivalent to calling the script with `--audio :org --subs :org` command-line arguments. See [Original language code](./README.md#original-language-code) below for more details.
Selecting this language is functionally equivalent to calling the script with `--audio :org --subs :org` command-line arguments. See [Original language code](#original-language-code) below for more details.
The language selection **'Unknown'** will match tracks with **no configured language** in the video file. Selecting this language is functionally equivalent to calling the script with `--audio :und --subs :und` command-line arguments.
See [Unknown language code](./README.md#unknown-language-code) below for more details.
See [Unknown language code](#unknown-language-code) below for more details.
The language selection **'Any'** has two purposes:
1) In Radarr only, when set on a Quality Profile, it will trigger a search of languages in ***Custom Formats***
2) If languages are not configured in a Custom Format, or if you're using Sonarr, it will preserve **all languages** in the video file. This is functionally equivalent to calling the script with `--audio :any --subs :any` command-line arguments.
See [Any language code](./README.md#any-language-code) below for more details.
See [Any language code](#any-language-code) below for more details.
> [!IMPORTANT]
> When using *Custom Formats* language conditions and scoring you may not get the results you expect.
@@ -210,16 +210,17 @@ All language conditions with positive scores *and* Negated conditions with negat
The script also supports command-line arguments that will override the automatic language detection. More granular control can therefore be exerted or extended using tagging and defining multiple *Connect* scripts (this is native Radarr/Sonarr functionality outside the scope of this documentation).
The syntax for the command-line is:
`striptracks.sh [{-a|--audio} <audio_languages> [{-s|--subs} <subtitle_languages>] [{-f|--file} <video_file>]] [{-l|--log} <log_file>] [{-c|--config} <config_file>] [{-d|--debug} [<level>]]`
`striptracks.sh [{-a|--audio} <audio_languages> [{-s|--subs} <subtitle_languages>] [--reorder] [{-f|--file} <video_file>]] [{-l|--log} <log_file>] [{-c|--config} <config_file>] [{-d|--debug} [<level>]]`
<details>
<summary>Table of Command-Line Arguments</summary>
Option|Argument|Description
---|---|---
`-a`, `--audio`|`<audio_languages>`|Audio languages to keep<br/>ISO 639-2 code(s) prefixed with a colon (`:`)<br/>Each code may optionally be followed by a plus (`+`) and one or more [modifiers](./README.md#language-code-modifiers).
`-a`, `--audio`|`<audio_languages>`|Audio languages to keep<br/>ISO 639-2 code(s) prefixed with a colon (`:`)<br/>Each code may optionally be followed by a plus (`+`) and one or more [modifiers](#language-code-modifiers).
`-s`, `--subs`|`<subtitle_languages>`|Subtitle languages to keep<br/>ISO 639-2 code(s) prefixed with a colon (`:`)<br/>Each code may optionally be followed by a plus (`+`) and one or more modifiers.
`-f`, `--file`|`<video_file>`|If included, the script enters **[Batch Mode](./README.md#batch-mode)** and converts the specified video file.<br/>Requires the `-a` option.<br/>![notes] **Do not** use this argument when called from Radarr or Sonarr!
`--reorder`| |Reorder audio and subtitles tracks to match the language code order specified in the `<audio_languages>` and `<subtitle_languages>` arguments.<br/>This is skipped if no tracks are removed.
`-f`, `--file`|`<video_file>`|If included, the script enters **[Batch Mode](#batch-mode)** and converts the specified video file.<br/>Requires the `--audio` option.<br/>![notes] **Do not** use this argument when called from Radarr or Sonarr!
`-l`, `--log`|`<log_file>`|The log filename<br/>Default is `/config/log/striptracks.txt`
`-c`, `--config`|`<config_file>`|Radarr/Sonarr XML configuration file<br/>Default is `/config/config.xml`
`-d`, `--debug`|`[<level>]`|Enables debug logging. Level is optional.<br/>Default is `1` (low)<br/>`2` includes JSON output<br/>`3` contains even more JSON output
@@ -228,7 +229,7 @@ Option|Argument|Description
</details>
The `<audio_languages>` and `<subtitle_languages>` are optional arguments that are colon (`:`) prepended language codes in [ISO 639-2](https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes "List of ISO 639-2 codes") format.
The `<audio_languages>` and `<subtitle_languages>` arguments are colon (`:`) prepended language codes in [ISO 639-2](https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes "List of ISO 639-2 codes") format.
For example:
* `:eng`
@@ -237,7 +238,7 @@ For example:
...etc.
Multiple codes may be concatenated, such as `:eng:spa` for both English and Spanish. Order is unimportant.
Multiple codes may be concatenated, such as `:eng:spa` for both English and Spanish. Order is unimportant, unless the `--reorder` option is also specified.
> [!WARNING]
> If no subtitle language is detected via Radarr/Sonarr configuration or specified on the command-line, all subtitles are removed.
@@ -268,7 +269,7 @@ The `:any` language code is a special code. When used, the script will preserve
### Original language code
The `:org` language code is a special code. When used, instead of retaining a specific language, the script substitutes the original movie or TV show language as specified in its [The Movie Database](https://www.themoviedb.org/ "TMDB") or [The TVDB](https://www.thetvdb.com/ "TVDB") entry.
As an example, when importing "*Amores Perros (2000)*" with options `--audio :org:eng`, the Spanish and English audio tracks are preserved.
Several [Included Wrapper Scripts](./README.md#included-wrapper-scripts) use this special code.
Several [Included Wrapper Scripts](#included-wrapper-scripts) use this special code.
> [!NOTE]
> This feature relies on the 'originalLanguage' field in the Radarr/Sonarr database. The `:org` code is therefore invalid when used in Batch Mode.
@@ -314,7 +315,7 @@ There is no way to force the script to remove audio tracks with these codes.
</details>
## Wrapper Scripts
To supply arguments to the script, you must either use one of the included wrapper scripts, create a custom wrapper script, or set the `STRIPTRACKS_ARGS` [environment variable](./README.md#environment-variable).
To supply arguments to the script, you must either use one of the included wrapper scripts, create a custom wrapper script, or set the `STRIPTRACKS_ARGS` [environment variable](#environment-variable).
> [!TIP]
> If you followed the Linuxserver.io recommendations when configuring your container, the `/config` directory will be mapped to an external storage location.
@@ -322,7 +323,7 @@ To supply arguments to the script, you must either use one of the included wrapp
### Included Wrapper Scripts
For your convenience, several wrapper scripts are included in the `/usr/local/bin/` directory.
You may use any of these in place of `striptracks.sh` mentioned in the [Installation](./README.md#installation) section above.
You may use any of these in place of `striptracks.sh` mentioned in the [Installation](#installation) section above.
<details>
<summary>List of scripts</summary>
@@ -350,7 +351,7 @@ striptracks-org-spa.sh # Keep Original, Spanish, and Unknown audio, and Orig
<details>
<summary>Example Script</summary>
To configure an entry from the [Examples](./README.md#examples) section above, create and save a file called `striptracks-custom.sh` to `/config` containing the following text:
To configure an entry from the [Examples](#examples) section above, create and save a file called `striptracks-custom.sh` to `/config` containing the following text:
```shell
#!/bin/bash
@@ -364,7 +365,7 @@ Make it executable:
chmod +x /config/striptracks-custom.sh
```
Then put `/config/striptracks-custom.sh` in the **Path** field in place of `/usr/local/bin/striptracks.sh` mentioned in the [Installation](./README.md#installation) section above.
Then put `/config/striptracks-custom.sh` in the **Path** field in place of `/usr/local/bin/striptracks.sh` mentioned in the [Installation](#installation) section above.
</details>
@@ -410,7 +411,7 @@ The only events/notification triggers that are supported are **On Import** and *
## Batch Mode
Batch mode allows the script to be executed independently of Radarr or Sonarr. It converts the file specified on the command-line and ignores any environment variables that are normally expected to be set by the video management program.
Using this function, you can easily process all of your video files in any subdirectory at once. See the [Batch Example](./README.md#batch-example) below.
Using this function, you can easily process all of your video files in any subdirectory at once. See the [Batch Example](#batch-example) below.
### Script Execution Differences in Batch Mode
Because the script is not called from within Radarr or Sonarr, their database is unavailable to the script. Therefore, expect the following behavior while in Batch Mode:
@@ -460,7 +461,7 @@ However, configuring hardlinks is still recommended.
<summary>Hardlink Limitations</summary>
*Radarr Hardlinks Configuration Screenshot*
![radarr-enable-hardlinks](./.assets/radarr-enable-hardlinks.png "Radarr hardlinks screenshot")
![radarr-enable-hardlinks](.assets/radarr-enable-hardlinks.png "Radarr hardlinks screenshot")
Hardlinks are essentially multiple references to the *same file*.
The purpose of a hardlink is to:
@@ -481,7 +482,7 @@ It is therefore still recommended to enable and use hardlinks in Radarr and Sona
# Uninstall
To completely remove the mod:
1. Delete the custom script from Radarr's or Sonarr's *Settings* > *Connect* screen that you created in the [Installation](./README.md#installation) section above.
1. Delete the custom script from Radarr's or Sonarr's *Settings* > *Connect* screen that you created in the [Installation](#installation) section above.
2. Stop and delete the Radarr/Sonarr container.
3. Remove the **DOCKER_MODS** environment variable from your `compose.yaml` file or exclude it from the `docker run` command when re-creating the Radarr/Sonarr container.
+2 -2
View File
@@ -6,8 +6,8 @@ Only the latest major and minor version are supported.
| Version | Supported |
| ------- | ------------------ |
| 2.12.x | :heavy_check_mark: |
| < 2.12 | :x: |
| 2.13.x | :heavy_check_mark: |
| < 2.13 | :x: |
## Reporting a Vulnerability
+81 -18
View File
@@ -62,10 +62,13 @@ export striptracks_debug=0
# Presence of '*_eventtype' variable sets script mode
export striptracks_type=$(printenv | sed -n 's/_eventtype *=.*$//p')
# Usage function
# Usage functions
function usage {
usage="
$striptracks_script Version: $striptracks_ver
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.
@@ -73,7 +76,7 @@ mode.
Source: https://github.com/TheCaptain989/radarr-striptracks
Usage:
$0 [{-a|--audio} <audio_languages> [{-s|--subs} <subtitle_languages>] [{-f|--file} <video_file>]] [{-l|--log} <log_file>] [{-d|--debug} [<level>]]
$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.
@@ -89,6 +92,12 @@ Options and Arguments:
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.
Track reorder is skipped if no tracks are
removed.
-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
@@ -122,11 +131,11 @@ 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
$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,
$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 -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
@@ -137,8 +146,13 @@ Examples:
# 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" >&2
echo "$usage"
}
# Log command-line arguments
@@ -182,11 +196,11 @@ while (( "$#" )); do
exit 1
fi
;;
-h|--help ) # Display usage
usage
--help ) # Display full usage
long_usage
exit 0
;;
-v|--version ) # Display version
--version ) # Display version
echo "$striptracks_script $striptracks_ver"
exit 0
;;
@@ -239,6 +253,10 @@ while (( "$#" )); do
exit 1
fi
;;
--reorder ) # Reorder audio and subtitles tracks
export striptracks_reorder="true"
shift
;;
-*) # Unknown option
echo "Error|Unknown option: $1" >&2
usage
@@ -319,7 +337,8 @@ elif [[ "${striptracks_type,,}" = "sonarr" ]]; then
# 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 called from Radarr/Sonarr.\nTry using Batch Mode option: -f <file>" >&2
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^}"
@@ -1397,19 +1416,22 @@ reduce .tracks[] as $track (
{"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] = (.counters[$track.type].normal[$track_lang] // 0) |
if $track.properties.forced_track then .counters[$track.type].forced[$track_lang] = (.counters[$track.type].forced[$track_lang] // 0) else . end |
if $track.properties.default_track then .counters[$track.type].default[$track_lang] = (.counters[$track.type].default[$track_lang] // 0) else . end |
(.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
@@ -1476,7 +1498,7 @@ elif (.tracks | map(select(.type == "audio" and .striptracks_keep)) | length ==
else . end |
# Output simplified dataset
{ striptracks_log, tracks: [ .tracks[] | { id, type, forced: .properties.forced_track, default: .properties.default_track, striptracks_debug_log, striptracks_log, striptracks_keep } ] }
{ 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
@@ -1541,6 +1563,47 @@ if [ "$(echo "$striptracks_json" | jq -crM '.tracks|map(select(.type=="audio" or
fi
fi
# Prepare to reorder tracks if option is enabled
if [ "$striptracks_reorder" = "true" ]; then
striptracks_neworder=$(echo "$striptracks_json_processed" | jq -jcM --arg AudioKeep "$striptracks_audiokeep" \
--arg SubsKeep "$striptracks_subskeep" '
# Reorder tracks
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 rules
.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
$tracks | map(select(.type == "video") | .id) + $audioOrder + $subsOrder | map("0:" + tostring) | join(",")
')
striptracks_neworder="--track-order $striptracks_neworder"
striptracks_message="Info|Reordering tracks using language rules."
echo "$striptracks_message" | log
[ $striptracks_debug -ge 1 ] && echo "Debug|Using track reorder string: $striptracks_neworder" | log
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
@@ -1563,7 +1626,7 @@ else
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_video\""
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=$?