diff --git a/Dockerfile b/Dockerfile index fe8fdd1..e263164 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,9 @@ FROM linuxserver/sabnzbd:unstable LABEL maintainer="RandomNinjaAtk" -ENV VERSION="1.0.2" -ENV SABSCRIPTS_PATH /usr/local/sabnzbd-scripts +ENV TITLE="SABnzbd Extended" +ENV VERSION="1.0.3" ENV SMA_PATH /usr/local/sma -ENV UPDATE_EXT FALSE -ENV UPDATE_SMA FALSE ENV VIDEO_LANG eng ENV VIDEO_SMA FALSE ENV VIDEO_SMA_TAGGING FALSE @@ -15,16 +13,15 @@ ENV AUDIO_BITRATE 320 ENV AUDIO_REPLAYGAIN FALSE ENV AUDIO_DSFA TRUE ENV AUDIO_DSFAS 150M -ENV AUDIO_BEETSTAGGING TRUE -ENV AUDIO_REQUIREBEETSTAGGING false RUN \ echo "************ install dependencies ************" && \ apt-get update && \ apt-get install -y software-properties-common && \ add-apt-repository ppa:jonathonf/ffmpeg-4 -y && \ - echo "************ install packages ************" && \ + echo "************ install and update packages ************" && \ apt-get update && \ + apt-get upgrade -y && \ apt-get install -y \ mkvtoolnix \ mp3val \ @@ -32,24 +29,12 @@ RUN \ opus-tools \ jq \ git \ - wget \ - beets \ - python3 \ ffmpeg \ + python3 \ python3-pip \ - libchromaprint-tools \ - ffmpeg \ - imagemagick \ - python3-pythonmagick \ - cron && \ + ffmpeg && \ apt-get purge --auto-remove -y && \ apt-get clean && \ - echo "************ install Beets dependencies ************" && \ - pip3 install --no-cache-dir -U \ - requests \ - Pillow \ - pylast \ - pyacoustid && \ echo "************ setup SMA ************" && \ echo "************ setup directory ************" && \ mkdir -p ${SMA_PATH} && \ @@ -63,21 +48,15 @@ RUN \ chmod g+w ${SMA_PATH}/config/sma.log && \ echo "************ install pip dependencies ************" && \ python3 -m pip install --user --upgrade pip && \ - pip3 install -r ${SMA_PATH}/setup/requirements.txt && \ - echo "************ setup sabnzbd-scripts ************" && \ - echo "************ setup directory ************" && \ - mkdir -p ${SABSCRIPTS_PATH} && \ - echo "************ download repo ************" && \ - git clone https://github.com/RandomNinjaAtk/sabnzbd-scripts.git ${SABSCRIPTS_PATH} && \ - echo "************ setup cron ************" && \ - service cron start && \ - echo "* * * * * root bash /etc/cont-init.d/33-script-setup.bash" >> "/etc/crontab" + pip3 install -r ${SMA_PATH}/setup/requirements.txt -WORKDIR / # copy local files COPY root/ / +# set work directory +WORKDIR /config + # ports and volumes EXPOSE 8080 9090 -VOLUME /config /storage +VOLUME /config diff --git a/README.md b/README.md index f13645a..3517bb9 100644 --- a/README.md +++ b/README.md @@ -37,18 +37,13 @@ Container images are configured using parameters passed at runtime (such as thos | `-e PUID=1000` | for UserID - see below for explanation | | `-e PGID=1000` | for GroupID - see below for explanation | | `-v /config` | Sabnzbd application files | -| `-v /storage` | Location of Downloads location | -| `-e UPDATE_EXT=TRUE` | TRUE = enabled :: Update scripts from git on container start | -| `-e UPDATE_SMA=FALSE` | TRUE = enabled :: Update scripts from git on container start | | `-e AUDIO_FORMAT=FLAC` | FLAC or OPUS or MP3 or AAC or ALAC - converts lossless FLAC files to set format | | `-e AUDIO_BITRATE=320` | Set to desired bitrate when converting to OPUS/MP3/AAC format types | | `-e AUDIO_VERIFY=TRUE` | TRUE = ENABLED, Verifies FLAC/MP3 files for errors (fixes MP3's, deletes bad FLAC files) | | `-e AUDIO_DSFA=TRUE` | TRUE = ENABLED :: Detects single file albums and mark download as failed if detected | | `-e AUDIO_REPLAYGAIN=FALSE` | TRUE = ENABLED, adds replaygain tags for compatible players (FLAC ONLY) | -| `-e AUDIO_BEETSTAGGING=TRUE` | TRUE = ENABLED, use beets to tag files | -| `-e AUDIO_REQUIREBEETSTAGGING=false` | true = enabled :: skips importing files that could not be matched using beets (marks as failed) | | `-e VIDEO_LANG=eng` | Default: eng :: Set to required language (ISO 639-2 language code), if not found, will mark as failed | -| `-e VIDEO_SMA=FALSE` | TRUE = Enabled :: Uses SMA to process incoming video files, update your configuration at: /config/scripts/configs/*-sma.ini | +| `-e VIDEO_SMA=FALSE` | TRUE = Enabled :: Uses SMA to process incoming video files, update your configuration at: `/config/scripts/configs/*-sma.ini` | | `-e VIDEO_SMA_TAGGING=TRUE` | TRUE = Enabled :: Uses SMA to Tag MP4 files (Enabled SMA process: manual.py -a; Disabled SMA Process: manual.py -nt) | ## Application Setup @@ -57,26 +52,30 @@ Access the webui at `:8080`, for more information check out [SABnzbd](h # Important Docker Information ### Important Paths: -/storage :: Root location for downloads, see additonal paths below
-/storage/downloads/sabnzbd/incomplete :: Automatically created on setup
-/storage/downloads/sabnzbd/complete :: Automatically created on setup
/config :: Location of SABnzbd aplication files
/config/scripts :: Location of SABnzbd post process script files (automatically mapped in SABnzbd)
/config/scripts/logs :: Location of SMA log files
/config/scritps/configs :: Location of config files
-### Important SABNzbd Categories: -lidarr :: Automatically configured to post process using audio-pp.bash
-radarr :: Automatically configured to post process using video-pp.bash
-sonarr :: Automatically configured to post process using video-pp.bash
+ +### Important SABNzbd Configuration: +Folders Configuration:
+* Scripts Folder :: Set to: /config/scripts
+ +Switches: Post processing
+* Pause Downloading During Post-Processing :: Highly recommended that you enable this setting to not overtask your system
+ +Categories Configuration:
+* lidarr :: Add category and post processing script: audio-pp.bash
+* radarr :: Add category and post processing script: video-pp.bash
+* sonarr :: Add category and post processing script: video-pp.bash
+ ### Scripts/Files included: audio-pp.bash :: Automatically clean up downloaded audio files and convert to standardized format if desired
video-pp.bash :: Verify incoming video files for required audio/subtitle languages and process with SMA if enabled
-beets-config.yaml :: Beet config file for matching

-Scripts are hosted here: https://github.com/RandomNinjaAtk/sabnzbd-scripts ### Sickbeard MP4 Automater (SMA): Config Files Location: /config/scritps/configs
-* radarr-sma.ini :: config file for SMA -* sonarr-sma.ini :: config file for SMA +* radarr-sma.ini :: config file for SMA (Applies to "radarr" category) +* sonarr-sma.ini :: config file for SMA (Applies to "sonarr" category) Log Files Location: /config/scritps/logs
* sma.log :: Log file for SMA diff --git a/root/etc/cont-init.d/30-script-update.bash b/root/etc/cont-init.d/30-script-update.bash index b4c5375..9f6c0e0 100644 --- a/root/etc/cont-init.d/30-script-update.bash +++ b/root/etc/cont-init.d/30-script-update.bash @@ -1,16 +1,8 @@ #!/usr/bin/with-contenv bash # update from git -if [[ "${UPDATE_EXT}" == "TRUE" ]]; then - git -C ${SABSCRIPTS_PATH} reset --hard HEAD && \ - git -C ${SABSCRIPTS_PATH} pull origin master -fi - -# update from git -if [[ "${UPDATE_SMA}" == "TRUE" ]]; then - git -C ${SMA_PATH} reset --hard HEAD && \ - git -C ${SMA_PATH} pull origin master -fi +git -C ${SMA_PATH} reset --hard HEAD +git -C ${SMA_PATH} pull origin master # update pip3 requirements pip3 install -r /usr/local/sma/setup/requirements.txt --upgrade --user diff --git a/root/etc/cont-init.d/31-path-setup.bash b/root/etc/cont-init.d/31-path-setup.bash index 7d27117..06514ce 100644 --- a/root/etc/cont-init.d/31-path-setup.bash +++ b/root/etc/cont-init.d/31-path-setup.bash @@ -18,16 +18,4 @@ if [ ! -d "/config/scripts/logs" ]; then chmod 0777 "/config/scripts/logs" fi -# Create downloads incomplete directory -if [ ! -d "/storage/downloads/sabnzbd/incomplete" ]; then - mkdir -p "/storage/downloads/sabnzbd/incomplete" - chmod 0777 "/storage/downloads/sabnzbd/incomplete" -fi - -# Create downloads complete directory -if [ ! -d "/storage/downloads/sabnzbd/complete" ]; then - mkdir -p "/storage/downloads/sabnzbd/complete" - chmod 0777 "/storage/downloads/sabnzbd/complete" -fi - -exit 0 +exit $? diff --git a/root/etc/cont-init.d/32-sma-setup.bash b/root/etc/cont-init.d/32-sma-setup.bash index 823be2c..5fe5cee 100644 --- a/root/etc/cont-init.d/32-sma-setup.bash +++ b/root/etc/cont-init.d/32-sma-setup.bash @@ -49,4 +49,4 @@ chmod 0777 -R "/usr/local/sma" chmod 0777 -R "/scripts" chmod 0777 -R "/config/scripts" -exit 0 +exit $? diff --git a/root/etc/cont-init.d/33-script-setup.bash b/root/etc/cont-init.d/33-script-setup.bash index d1a33e5..84bd859 100644 --- a/root/etc/cont-init.d/33-script-setup.bash +++ b/root/etc/cont-init.d/33-script-setup.bash @@ -1,102 +1,33 @@ #!/usr/bin/with-contenv bash -# set permissions -chmod 0777 -R /usr/local/sabnzbd-scripts - -# remove existing audio-pp script file -if [ -f "/config/scripts/audio-pp.bash" ]; then - rm "/config/scripts/audio-pp.bash" - sleep 0.1 -fi - -# cp audio-pp script file for use -if [ ! -f "/config/scripts/audio-pp.bash" ]; then - cp "/usr/local/sabnzbd-scripts/audio-pp.bash" "/config/scripts/audio-pp.bash" && \ - chmod 0777 "/config/scripts/audio-pp.bash" +if [ -f /config/scripts/video-pp.bash ]; then + rm /config/scripts/video-pp.bash fi -# cp beets config file for use -if [ ! -f "/config/scripts/configs/beets-config.yaml" ]; then - cp "/usr/local/sabnzbd-scripts/beets-config.yaml" "/config/scripts/configs/beets-config.yaml" && \ - chmod 0666 "/config/scripts/configs/beets-config.yaml" +if [ ! -f /config/scripts/video-pp.bash ]; then + cp /scripts/video-pp.bash /config/scripts/video-pp.bash + chmod 777 /config/scripts/video-pp.bash + chown abc:abc /config/scripts/video-pp.bash fi -# remove existing video-pp script file -if [ -f "/config/scripts/video-pp.bash" ]; then - rm "/config/scripts/video-pp.bash" - sleep 0.1 +if [ -f /config/scripts/audio-pp.bash ]; then + rm /config/scripts/audio-pp.bash fi -# cp video-pp script file for use -if [ ! -f "/config/scripts/video-pp.bash" ]; then - cp "/usr/local/sabnzbd-scripts/sabnzbd/video-pp.bash" "/config/scripts/video-pp.bash" && \ - chmod 0777 "/config/scripts/video-pp.bash" +if [ ! -f /config/scripts/audio-pp.bash ]; then + cp /scripts/audio-pp.bash /config/scripts/audio-pp.bash + chmod 777 /config/scripts/audio-pp.bash + chown abc:abc /config/scripts/audio-pp.bash fi -if [ ! -f "/config/sabnzbd.ini" ]; then - # start cron - service cron start - exit 0 +if [ -f /config/scripts/logs/audio-pp.log ]; then + rm /config/scripts/logs/audio-pp.log fi -# Check if config is already updated, if not start cron... -if cat "/config/sabnzbd.ini" | grep "/config/scripts" | read; then - echo "config already updated..." - exit 0 -else - # start cron - service cron start -fi - -# Check for finished initial config file, if sab is done, proceed with automated modifications... -if cat "/config/sabnzbd.ini" | grep "\[categories\]" | read; then - # Add scripts path - if cat "/config/sabnzbd.ini" | grep "script_dir = \"\"" | read; then - sed -i "s/script_dir = \"\"/script_dir = \"\/config\/scripts\"/g" "/config/sabnzbd.ini" - fi - - # Correct incomplete path - if cat "/config/sabnzbd.ini" | grep "Downloads/incomplete" | read; then - sed -i "s/Downloads\/incomplete/\/storage\/downloads\/sabnzbd\/incomplete/g" "/config/sabnzbd.ini" - fi - - # Correct complete path - if cat "/config/sabnzbd.ini" | grep "Downloads/complete" | read; then - sed -i "s/Downloads\/complete/\/storage\/downloads\/sabnzbd\/complete/g" "/config/sabnzbd.ini" - fi - - # Enable script failure - if cat "/config/sabnzbd.ini" | grep "script_can_fail = 0" | read; then - sed -i "s/script_can_fail = 0/script_can_fail = 1/g" "/config/sabnzbd.ini" - fi - - # Enable pause on post processing - if cat "/config/sabnzbd.ini" | grep "pause_on_post_processing = 0" | read; then - sed -i "s/pause_on_post_processing = 0/pause_on_post_processing = 1/g" "/config/sabnzbd.ini" - fi - - # Set permissions - if cat "/config/sabnzbd.ini" | grep "permissions = \"\"" | read; then - sed -i "s/permissions = \"\"/permissions = \"766\"/g" "/config/sabnzbd.ini" - fi - - # purge default categories - sed -i '/\[\[software\]\]/,+7d' "/config/sabnzbd.ini" && \ - sed -i '/\[\[audio\]\]/,+7d' "/config/sabnzbd.ini" && \ - sed -i '/\[\[tv\]\]/,+7d' "/config/sabnzbd.ini" && \ - sed -i '/\[\[movies\]\]/,+7d' "/config/sabnzbd.ini" && \ - - # Add categories - sed -i '/\[categories\]/a\\[\[radarr\]\]\npriority = -100\npp = ""\nname = radarr\nscript = video-pp.bash\nnewzbin = ""\norder = 1\n\dir = radarr\n\[\[sonarr\]\]\npriority = -100\npp = ""\nname = sonarr\nscript = video-pp.bash\nnewzbin = ""\norder = 2\n\dir = sonarr\n\[\[lidarr\]\]\npriority = -100\npp = ""\nname = lidarr\nscript = audio-pp.bash\nnewzbin = ""\norder = 3\n\dir = lidarr' "/config/sabnzbd.ini" - - sleep 2 - restartsab=$(pgrep s6-supervise | sort -r | head -n1) && \ - kill ${restartsab} && \ - echo "config updated" && \ - # stop cron - service cron stop +if [ -f /config/scripts/logs/video-pp.log ]; then + rm /config/scripts/logs/video-pp.log fi -exit 0 +exit $? diff --git a/root/scripts/audio-pp.bash b/root/scripts/audio-pp.bash new file mode 100644 index 0000000..6d0c6ab --- /dev/null +++ b/root/scripts/audio-pp.bash @@ -0,0 +1,219 @@ +#!/usr/bin/with-contenv bash +export LC_ALL=C.UTF-8 +export LANG=C.UTF-8 +TITLESHORT="APP" + +Main () { + # SETTINGS + AudioVerification="${AUDIO_VERIFY}" # TRUE = ENABLED, Verifies FLAC/MP3 files for errors (fixes MP3's, deletes bad FLAC files) + ConversionFormat="${AUDIO_FORMAT}" # SET TO: OPUS or AAC or MP3 or ALAC or FLAC - converts lossless FLAC files to set format + ConversionBitrate="${AUDIO_BITRATE}" # Set to desired bitrate when converting to OPUS/AAC/MP3 format types + ReplaygainTagging="${AUDIO_REPLAYGAIN}" # TRUE = ENABLED, adds replaygain tags for compatible players (FLAC ONLY) + DetectNonSplitAlubms="${AUDIO_DSFA}" # TRUE = ENABLED :: Uses "MaxFileSize" to detect and mark download as failed if detected + MaxFileSize="${AUDIO_DSFAS}" # M = MB, G = GB :: Set size threshold for detecting single file albums + + #============FUNCTIONS============ + + settings () { + + echo "Configuration:" + echo "Remove Non Audio Files: ENABLED" + echo "Duplicate File CleanUp: ENABLED" + if [ "${AudioVerification}" = TRUE ]; then + echo "Audio Verification: ENABLED" + else + echo "Audio Verification: DISABLED" + fi + echo "Format: $ConversionFormat" + if [ "${ConversionFormat}" = FLAC ]; then + echo "Bitrate: lossless" + echo "Replaygain Tagging: ENABLED" + elif [ "${ConversionFormat}" = ALAC ]; then + echo "Bitrate: lossless" + else + echo "Conversion Bitrate: ${ConversionBitrate}k" + fi + if [ "${DetectNonSplitAlubms}" = TRUE ]; then + echo "Detect Non Split Alubms: ENABLED" + echo "Max File Size: $MaxFileSize" + else + echo "DetectNonSplitAlubms: DISABLED" + fi + + echo "Processing: $1" + + } + + clean () { + if find "$1" -type f -iregex ".*/.*\.\(flac\|mp3\|m4a\|alac\|ogg\|opus\)" | read; then + if find "$1" -type f -not -iregex ".*/.*\.\(flac\|mp3\|m4a\|alac\|ogg\|opus\)" | read; then + find "$1" -type f -not -iregex ".*/.*\.\(flac\|mp3\|m4a\|alac\|ogg\|opus\)" -delete + fi + find "$1" -mindepth 2 -type f -exec mv "{}" "$1"/ \; + find "$1" -mindepth 1 -type d -delete + else + echo "ERROR: NO AUDIO FILES FOUND" && exit 1 + fi + } + + duplicatefilecleanup () { + duplicate="FALSE" + if find "$1" -type f -mindepth 1 -iname "*([0-9]).*" | read; then + find "$1" -type f -mindepth 1 -iname "*([0-9]).*" -delete + duplicate="TRUE" + fi + + if find "$1" -type f -mindepth 1 -iname "*.[0-9].*" | read; then + find "$1" -type f -mindepth 1 -iname "*.[0-9].*" -delete + duplicate="TRUE" + fi + + if find "$1" -type f -mindepth 1 -iname "*.flac" | read; then + if find "$1"/* -type f -not -iname "*.flac" | read; then + find "$1"/* -type f -not -iname "*.flac" -delete + duplicate="TRUE" + fi + fi + if [ "${duplicate}" = TRUE ]; then + echo "DUPLICATE FILE CLEANUP" + echo "DUPLICATE FILE CLEANUP COMPLETE" + fi + } + + detectsinglefilealbums () { + if find "$1" -type f -iregex ".*/.*\.\(flac\|mp3\|m4a\|alac\|ogg\|opus\)" -size +${MaxFileSize} | read; then + echo "ERROR: Non split album detected" && exit 1 + fi + } + + verify () { + if find "$1" -iname "*.flac" | read; then + verifytrackcount=$(find "$1"/ -iname "*.flac" | wc -l) + echo "Verifying: $verifytrackcount Tracks" + if ! [ -x "$(command -v flac)" ]; then + echo "ERROR: FLAC verification utility not installed (ubuntu: apt-get install -y flac)" + else + for fname in "$1"/*.flac; do + filename="$(basename "$fname")" + if flac -t --totally-silent "$fname"; then + echo "Verified Track: $filename" + else + echo "ERROR: Track Verification Failed: \"$filename\"" + rm -rf "$1"/* + sleep 0.1 + exit 1 + fi + done + fi + fi + if find "$1" -iname "*.mp3" | read; then + verifytrackcount=$(find "$1"/ -iname "*.mp3" | wc -l) + echo "" + echo "Verifying: $verifytrackcount Tracks" + if ! [ -x "$(command -v mp3val)" ]; then + echo "MP3VAL verification utility not installed (ubuntu: apt-get install -y mp3val)" + else + for fname in "$1"/*.mp3; do + filename="$(basename "$fname")" + if mp3val -f -nb "$fname" > /dev/null; then + echo "Verified Track: $filename" + fi + done + fi + fi + } + + conversion () { + converttrackcount=$(find "$1"/ -name "*.flac" | wc -l) + targetformat="$ConversionFormat" + bitrate="$ConversionBitrate" + if [ "${ConversionFormat}" = OPUS ]; then + options="-acodec libopus -ab ${bitrate}k -application audio -vbr off" + extension="opus" + targetbitrate="${bitrate}k" + fi + if [ "${ConversionFormat}" = AAC ]; then + options="-acodec aac -ab ${bitrate}k -movflags faststart" + extension="m4a" + targetbitrate="${bitrate}k" + fi + if [ "${ConversionFormat}" = MP3 ]; then + options="-acodec libmp3lame -ab ${bitrate}k" + extension="mp3" + targetbitrate="${bitrate}k" + fi + if [ "${ConversionFormat}" = ALAC ]; then + options="-acodec alac -movflags faststart" + extension="m4a" + targetbitrate="lossless" + fi + if [ "${ConversionFormat}" = FLAC ]; then + options="-acodec flac" + extension="flac" + targetbitrate="lossless" + fi + if [ -x "$(command -v ffmpeg)" ]; then + if [ "${ConversionFormat}" = FLAC ]; then + sleep 0.1 + elif find "$1"/ -name "*.flac" | read; then + echo "Converting: $converttrackcount Tracks (Target Format: $targetformat (${targetbitrate}))" + for fname in "$1"/*.flac; do + filename="$(basename "${fname%.flac}")" + if ffmpeg -loglevel warning -hide_banner -nostats -i "$fname" -n -vn $options "${fname%.flac}.temp.$extension"; then + echo "Converted: $filename" + if [ -f "${fname%.flac}.temp.$extension" ]; then + rm "$fname" + sleep 0.1 + mv "${fname%.flac}.temp.$extension" "${fname%.flac}.$extension" + fi + else + echo "Conversion failed: $filename, performing cleanup..." + rm -rf "$1"/* + sleep 0.1 + exit 1 + fi + done + fi + else + echo "ERROR: ffmpeg not installed, please install ffmpeg to use this conversion feature" + sleep 5 + fi + } + + replaygain () { + if ! [ -x "$(command -v flac)" ]; then + echo "ERROR: METAFLAC replaygain utility not installed (ubuntu: apt-get install -y flac)" + elif find "$1" -iname "*.flac" | read; then + replaygaintrackcount=$(find "$1"/ -iname "*.flac" | wc -l) + echo "Replaygain: Calculating $replaygaintrackcount Tracks" + find "$1" -iname "*.flac" -exec metaflac --add-replay-gain "{}" + && echo "Replaygain: $replaygaintrackcount Tracks Tagged" + fi + } + + #============START SCRIPT============ + + settings "$1" + clean "$1" + duplicatefilecleanup "$1" + detectsinglefilealbums "$1" + + if [ "${AudioVerification}" = TRUE ]; then + verify "$1" + fi + + conversion "$1" + + if [ "${ReplaygainTagging}" = TRUE ]; then + replaygain "$1" + fi + + echo "" + echo "Post Processing Complete!" && exit 0 + #============END SCRIPT============ +} + +Main "$@" | tee -a /config/scripts/logs/audio-pp.log +chmod 666 /config/scripts/logs/audio-pp.log +chown abc:abc /config/scripts/logs/audio-pp.log + +exit $? diff --git a/root/scripts/video-pp.bash b/root/scripts/video-pp.bash new file mode 100644 index 0000000..3d15f0d --- /dev/null +++ b/root/scripts/video-pp.bash @@ -0,0 +1,374 @@ +#!/usr/bin/with-contenv bash +export LC_ALL=C.UTF-8 +export LANG=C.UTF-8 +TITLESHORT="VPP" + +set -e + +Configuration () { + log "############################################ SABnzbd Job: $jobname" + log "############################################ SABnzbd Category: $category" + log "############################################ DOCKER: $TITLE" + log "############################################ SCRIPT: Video Post Processor ($TITLESHORT)" + log "############################################ SCRIPT VERSION: 1.0.0" + log "############################################ DOCKER VERSION: $VERSION" + log "############################################ CONFIGURATION VERIFICATION" + + log "$TITLESHORT: Required Audio/Subtitle Language: ${VIDEO_LANG}" + if [ ${VIDEO_MKVCLEANER} = TRUE ]; then + log "$TITLESHORT: MKV Cleaner: ENABLED" + else + log "$TITLESHORT: MKV Cleaner: DISABLED" + fi + if [ ${VIDEO_SMA} = TRUE ]; then + log "$TITLESHORT: Sickbeard MP4 Automator (SMA): ENABLED" + if [ ${VIDEO_SMA_TAGGING} = TRUE ]; then + tagging="-a" + log "$TITLESHORT: Sickbeard MP4 Automator (SMA): Tagging: ENABLED" + else + tagging="-nt" + log "$TITLESHORT: Sickbeard MP4 Automator (SMA): Tagging: DISABLED" + fi + else + log "$TITLESHORT: Sickbeard MP4 Automator (SMA): DISABLED" + fi + + if [ -z "VIDEO_SMA_TAGGING" ]; then + VIDEO_SMA_TAGGING=FALSE + fi +} + +log () { + m_time=`date "+%F %T"` + echo $m_time" "$1 +} + +Main () { + folderpath="$1" + jobname="$3" + category="$5" + + Configuration + + if [ ${VIDEO_SMA} = TRUE ]; then + touch "$1/sma-conversion-check" + elif [ ${VIDEO_MKVCLEANER} = TRUE ]; then + touch "$1/sma-conversion-check" + fi + + # check for video files + if find "$1" -type f -iregex ".*/.*\.\(mkv\|mp4\|avi\)" | read; then + sleep 0.1 + else + log "ERROR: No video files found for processing" + exit 1 + fi + + + filecount=$(find "$1" -type f -iregex ".*/.*\.\(mkv\|mp4\|avi\)" | wc -l) + log "Processing ${filecount} video files..." + count=0 + find "$1" -type f -iregex ".*/.*\.\(mkv\|mp4\|avi\)" -print0 | while IFS= read -r -d '' video; do + count=$(($count+1)) + log "" + log "====================================================" + basefilename="${video%.*}" + filename="$(basename "$video")" + extension="${filename##*.}" + log "Begin processing $count of $filecount: $filename" + log "Checking for audio/subtitle tracks" + tracks=$(mkvmerge -J "$video") + if [ ! -z "${tracks}" ]; then + # video tracks + VideoTrack=$(echo "${tracks}" | jq ".tracks[] | select(.type==\"video\") | .id") + VideoTrackCount=$(echo "${tracks}" | jq ".tracks[] | select(.type==\"video\") | .id" | wc -l) + # video preferred language + VideoTrackLanguage=$(echo "${tracks}" | jq ".tracks[] | select((.type==\"video\") and select(.properties.language==\"${VIDEO_LANG}\")) | .id") + # audio tracks + AudioTracks=$(echo "${tracks}" | jq ".tracks[] | select(.type==\"audio\") | .id") + AudioTracksCount=$(echo "${tracks}" | jq ".tracks[] | select(.type==\"audio\") | .id" | wc -l) + # audio preferred language + AudioTracksLanguage=$(echo "${tracks}" | jq ".tracks[] | select((.type==\"audio\") and select(.properties.language==\"${VIDEO_LANG}\")) | .id") + AudioTracksLanguageCount=$(echo "${tracks}" | jq ".tracks[] | select((.type==\"audio\") and select(.properties.language==\"${VIDEO_LANG}\")) | .id" | wc -l) + AudioTracksLanguageFound=$(echo "${tracks}" | jq ".tracks[] | select(.type==\"audio\") | .properties.language") + # audio unkown laguage + AudioTracksLanguageUND=$(echo "${tracks}" | jq ".tracks[] | select((.type==\"audio\") and select(.properties.language==\"und\")) | .id") + AudioTracksLanguageUNDCount=$(echo "${tracks}" | jq ".tracks[] | select((.type==\"audio\") and select(.properties.language==\"und\")) | .id" | wc -l) + AudioTracksLanguageNull=$(echo "${tracks}" | jq ".tracks[] | select((.type==\"audio\") and select(.properties.language==null)) | .id") + AudioTracksLanguageNullCount=$(echo "${tracks}" | jq ".tracks[] | select((.type==\"audio\") and select(.properties.language==null)) | .id" | wc -l) + # audio foreign language + AudioTracksLanguageForeignCount=$(echo "${tracks}" | jq ".tracks[] | select((.type==\"audio\") and select(.properties.language!=\"${VIDEO_LANG}\")) | .id" | wc -l) + # subtitle tracks + SubtitleTracks=$(echo "${tracks}" | jq ".tracks[] | select(.type==\"subtitles\") | .id") + SubtitleTracksCount=$(echo "${tracks}" | jq ".tracks[] | select(.type==\"subtitles\") | .id" | wc -l) + # subtitle preferred langauge + SubtitleTracksLanguage=$(echo "${tracks}" | jq ".tracks[] | select((.type==\"subtitles\") and select(.properties.language==\"${VIDEO_LANG}\")) | .id") + SubtitleTracksLanguageCount=$(echo "${tracks}" | jq ".tracks[] | select((.type==\"subtitles\") and select(.properties.language==\"${VIDEO_LANG}\")) | .id" | wc -l) + SubtitleTracksLanguageFound=$(echo "${tracks}" | jq ".tracks[] | select(.type==\"subtitles\") | .properties.language") + + else + log "ERROR: ffprobe failed to read tracks and set values" + rm "$video" && log "INFO: deleted: $video" + fi + + # Check for video track + if [ -z "${VideoTrack}" ]; then + log "ERROR: no video track found" + rm "$video" && log "INFO: deleted: $filename" + continue + else + log "$VideoTrackCount video track found!" + fi + + # Check for audio track + if [ -z "${AudioTracks}" ]; then + log "ERROR: no audio tracks found" + rm "$video" && log "INFO: deleted: $filename" + continue + else + log "$AudioTracksCount audio tracks found!" + fi + + # Check for audio track + if [ ! -z "${SubtitleTracks}" ]; then + log "$SubtitleTracksCount subtitle tracks found!" + fi + + if [ ! -z "$AudioTracksLanguage" ] || [ ! -z "$SubtitleTracksLanguage" ]; then + if [ ${VIDEO_MKVCLEANER} = TRUE ] || [ ${VIDEO_SMA} = TRUE ]; then + if [ ! -z "$AudioTracksLanguage" ] || [ ! -z "$SubtitleTracksLanguage" ] || [ ! -z "$AudioTracksLanguageUND" ] || [ ! -z "$AudioTracksLanguageNull" ]; then + sleep 0.1 + else + log "Checking for \"${VIDEO_LANG}\" video/audio/subtitle tracks" + log "ERROR: No \"${VIDEO_LANG}\" or \"Unknown\" audio tracks found..." + log "ERROR: No \"${VIDEO_LANG}\" subtitle tracks found..." + # rm "$video" && echo "INFO: deleted: $filename" + exit 1 + continue + fi + else + log "Checking for \"${VIDEO_LANG}\" video/audio/subtitle tracks" + if [ ! -z "${AudioTracks}" ]; then + log "INFO: ${AudioTracksLanguageFound} audio track found!" + fi + if [ ! -z "${SubtitleTracks}" ]; then + log "INFO: ${SubtitleTracksLanguageFound} subtitle track found!" + fi + log "ERROR: No \"${VIDEO_LANG}\" audio or subtitle tracks found..." + # rm "$video" && echo "INFO: deleted: $filename" + exit 1 + continue + fi + else + if [ ! ${VIDEO_MKVCLEANER} = TRUE ] || [ ! ${VIDEO_SMA} = TRUE ]; then + log "Checking for \"${VIDEO_LANG}\" video/audio/subtitle tracks" + if [ ! -z "$AudioTracksLanguage" ]; then + log "$AudioTracksLanguageCount \"${VIDEO_LANG}\" audio track found..." + fi + if [ ! -z "$SubtitleTracksLanguage" ]; then + log "$SubtitleTracksLanguageCount \"${VIDEO_LANG}\" subtitle track found..." + fi + fi + fi + + if [ ${VIDEO_MKVCLEANER} = TRUE ]; then + log "Begin processing with MKV Cleaner..." + log "Checking for \"${VIDEO_LANG}\" video/audio/subtitle tracks" + # Check for unwanted audio tracks and remove/re-label as needed... + if [ ! -z "$AudioTracksLanguage" ] || [ ! -z "$AudioTracksLanguageUND" ] || [ ! -z "$AudioTracksLanguageNull" ]; then + if [ $AudioTracksCount -ne $AudioTracksLanguageCount ]; then + RemoveAudioTracks="true" + if [ ! -z "$AudioTracksLanguage" ]; then + MKVaudio=" -a ${VIDEO_LANG}" + log "$AudioTracksLanguageCount audio tracks found!" + unwantedaudiocount=$(($AudioTracksCount-$AudioTracksLanguageCount)) + if [ $AudioTracksLanguageCount -ne $AudioTracksCount ]; then + unwantedaudio="true" + fi + elif [ ! -z "$AudioTracksLanguageUND" ]; then + for I in $AudioTracksLanguageUND + do + OUT=$OUT" -a $I --language $I:${VIDEO_LANG}" + done + MKVaudio="$OUT" + log "$AudioTracksLanguageUNDCount \"unknown\" audio tracks found, re-tagging as \"${VIDEO_LANG}\"" + unwantedaudiocount=$(($AudioTracksCount-$AudioTracksLanguageUNDCount)) + if [ $AudioTracksLanguageUNDCount -ne $AudioTracksCount ]; then + unwantedaudio="true" + fi + elif [ ! -z "$AudioTracksLanguageNull" ]; then + for I in $AudioTracksLanguageNull + do + OUT=$OUT" -a $I --language $I:${VIDEO_LANG}" + done + MKVaudio="$OUT" + log "$AudioTracksLanguageNullCount \"unknown\" audio tracks found, re-tagging as \"${VIDEO_LANG}\"" + unwantedaudiocount=$(($AudioTracksCount-$AudioTracksLanguageNullCount)) + if [ $AudioTracksLanguageNullCount -ne $AudioTracksCount ]; then + unwantedaudio="true" + fi + fi + else + log "$AudioTracksLanguageCount audio tracks found!" + RemoveAudioTracks="false" + MKVaudio="" + fi + elif [ -z "$SubtitleTracksLanguage" ]; then + if [ ! -z "${AudioTracks}" ]; then + log "INFO: ${AudioTracksLanguageFound} audio track found!" + fi + if [ ! -z "${SubtitleTracks}" ]; then + log "INFO: ${SubtitleTracksLanguageFound} subtitle track found!" + fi + log "ERROR: no \"${VIDEO_LANG}\" audio/subtitle tracks found!" + # rm "$video" && echo "INFO: deleted: $filename" + exit 1 + continue + else + foreignaudio="true" + RemoveAudioTracks="false" + MKVaudio="" + fi + + # Check for unwanted subtitle tracks... + if [ ! -z "$SubtitleTracks" ]; then + if [ $SubtitleTracksCount -ne $SubtitleTracksLanguageCount ]; then + RemoveSubtitleTracks="true" + MKVSubtitle=" -s ${VIDEO_LANG}" + if [ ! -z "$SubtitleTracksLanguage" ]; then + log "$SubtitleTracksLanguageCount subtitle tracks found!" + fi + unwantedsubtitlecount=$(($SubtitleTracksCount-$SubtitleTracksLanguageCount)) + if [ $SubtitleTracksLanguageCount -ne $SubtitleTracksCount ]; then + unwantedsubtitle="true" + fi + else + log "$SubtitleTracksLanguageCount subtitle tracks found!" + RemoveSubtitleTracks="false" + MKVSubtitle="" + fi + else + RemoveSubtitleTracks="false" + MKVSubtitle="" + fi + + # Correct video language, if needed... + if [ -z "$VideoTrackLanguage" ]; then + if [ ! -z "$AudioTracksLanguage" ] || [ ! -z "$AudioTracksLanguageUND" ] || [ ! -z "$AudioTracksLanguageNull" ]; then + SetVideoLanguage="true" + if [ "${RemoveAudioTracks}" = true ] || [ "${RemoveSubtitleTracks}" = true ]; then + log "$VideoTrackCount \"unknown\" video language track found, re-tagging as \"${VIDEO_LANG}\"" + fi + MKVvideo=" -d ${VideoTrack} --language ${VideoTrack}:${VIDEO_LANG}" + else + foreignvideo="true" + SetVideoLanguage="false" + MKVvideo="" + fi + else + log "$VideoTrackCount video track found!" + SetVideoLanguage="false" + MKVvideo="" + fi + + # Display foreign audio track counts + if [ "$foreignaudio" = true ] || [ "$foreignvideo" = true ]; then + log "Checking for \"foreign\" audio/video tracks" + if [ "$foreignvideo" = true ]; then + log "$VideoTrackCount video track found!" + foreignvideo="false" + fi + if [ "$foreignaudio" = true ]; then + log "$AudioTracksLanguageForeignCount audio tracks found!" + foreignaudio="false" + fi + fi + + # Display unwanted audio/subtitle track counts + if [ "$unwantedaudio" = true ] || [ "$unwantedsubtitle" = true ]; then + log "Checking for unwanted \"not: ${VIDEO_LANG}\" audio/subtitle tracks" + if [ "$unwantedaudio" = true ]; then + log "$unwantedaudiocount audio tracks to remove..." + unwantedaudio="false" + fi + if [ "$unwantedsubtitle" = true ]; then + log "$unwantedsubtitlecount subtitle tracks to remove..." + unwantedsubtitle="false" + fi + fi + skip="false" + if [ "${RemoveAudioTracks}" = false ] && [ "${RemoveSubtitleTracks}" = false ]; then + if find "$video" -type f -iname "*.mkv" | read; then + log "INFO: Video passed all checks, no processing needed" + touch "$video" + if [ ${VIDEO_SMA} = TRUE ]; then + skip="true" + fi + else + log "INFO: Video passed all checks, but is in the incorrect container, repackaging as mkv..." + MKVvideo=" -d ${VideoTrack} --language ${VideoTrack}:${VIDEO_LANG}" + MKVaudio=" -a ${VIDEO_LANG}" + MKVSubtitle=" -s ${VIDEO_LANG}" + fi + fi + if [ $skip = false ]; then + if mkvmerge --no-global-tags --title "" -o "${basefilename}.merged.mkv"${MKVvideo}${MKVaudio}${MKVSubtitle} "$video"; then + log "SUCCESS: mkvmerge complete" + log "INFO: Options used:${MKVvideo}${MKVaudio}${MKVSubtitle}" + # cleanup temp files and rename + mv "$video" "$video.original" && log "INFO: Renamed source file" + mv "${basefilename}.merged.mkv" "${basefilename}.mkv" && log "INFO: Renamed temp file" + rm "$video.original" && log "INFO: Deleted source file" + extension="mkv" + else + log "ERROR: mkvmerge failed" + rm "$video" && log "INFO: deleted: $video" + rm "${basefilename}.merged.mkv" && log "INFO: deleted: ${basefilename}.merged.mkv" + continue + fi + fi + fi + + if [ "${extension}" == "mkv" ]; then + log "========================START MKVPROPEDIT========================" + mkvpropedit "${basefilename}.${extension}" --add-track-statistics-tags + log "========================STOP MKVPROPEDIT=========================" + fi + + if [ ${VIDEO_SMA} = TRUE ]; then + if [ -f "${basefilename}.${extension}" ]; then + log "" + log "Begin processing with Sickbeard MP4 Automator..." + log "" + # Manual run of Sickbeard MP4 Automator + if python3 /usr/local/sma/manual.py --config "/config/scripts/configs/$5-sma.ini" -i "${basefilename}.${extension}" $tagging; then + log "Processing complete for: ${filename}!" + else + log "ERROR: Sickbeard MP4 Automator Processing Error" + rm "$video" && log "INFO: deleted: $filename" + fi + fi + fi + log "====================================================" + done + + if [ ${VIDEO_SMA} = TRUE ] || [ ${VIDEO_MKVCLEANER} = TRUE ]; then + find "$1" -type f ! -newer "$1/sma-conversion-check" ! -name "sma-conversion-check" -delete + # check for video files + if find "$1" -type f -iregex ".*/.*\.\(mkv\|mp4\)" | read; then + log "Post Processing Complete!" + else + log "ERROR: Post Processing failed, no video files found..." + exit 1 + fi + if [ -f "$1/sma-conversion-check" ]; then + rm "$1/sma-conversion-check" + fi + fi +} + +Main "$@" | tee -a /config/scripts/logs/video-pp.log +chmod 666 /config/scripts/logs/video-pp.log +chown abc:abc /config/scripts/logs/video-pp.log + +exit $?