From 27bd7e52039fde3d64ab5d732d2432b8a4947319 Mon Sep 17 00:00:00 2001 From: TheCaptain989 Date: Sat, 6 Mar 2021 16:22:38 -0600 Subject: [PATCH] Resolves three issues Resolves issue #23, #24, and #25. --- .assets/danger.png | Bin 0 -> 947 bytes .assets/warning.png | Bin 0 -> 1310 bytes README.md | 55 ++++++++------ root/usr/local/bin/flac2mp3-vbr.sh | 3 + root/usr/local/bin/flac2mp3.sh | 114 +++++++++++++++++++++-------- 5 files changed, 120 insertions(+), 52 deletions(-) create mode 100644 .assets/danger.png create mode 100644 .assets/warning.png create mode 100644 root/usr/local/bin/flac2mp3-vbr.sh diff --git a/.assets/danger.png b/.assets/danger.png new file mode 100644 index 0000000000000000000000000000000000000000..f9d46cc203f5eedaf303da9c38aa84f51b168ff0 GIT binary patch literal 947 zcmV;k15EshP)hx6se!F`0tm8P*@fR*} zp#N8ZuI5BysU^Z8MdKEq_6Kty#QUc`FLu{}<$V5pZC%9L)j5l> z!vORr7cewgUviwc?g}tII=V-|j)VJV&@7ABKiI?T5IF)OXWI%&h<7rX z%;wtybScj_)H&vk_Bn(ZTDSNO?R|0q%an0Th{yS)EB9hh?L1$Z*NGP}kU>cIAdlvxuPG&MM-UK+FPRD~FIFj6%CsyMl z%Cx1FP`_CakAbQ%E*GXH-(84s zWyUS*0T@UwAT-gGv+WZA+L5ubZYgDQcwipe79h&EWoKKF+PH=)EwiP*SP_t@FVNMo zj1uC_(-RZTMxjtR7jj+w;Ri0G0w3gR*`Nb_cx-WPt@0Ha3_OwJr%R8A0;S#)uM7`M z(=yRMP)N?T@|i*dK>v;36CKJI!)f-W?)LTv{~16q81%*5spo*|x#_TKnULkZ&za6a zuJ^|PF2;uk8@sx?9y;|*ssvHbtV5zyKb0*U-fl>>0cO+iLMr=?|G`gvv1;Q@I|RJt z)YEYWHnp@ZQMAW0cu#~Z=FjBaXx6j$HS3C89jj%_PppFHP(~CV9=T|K-`_WTcK$2JfU{EjJJ1O zRnA;iPG5Y$*((EyMoW09ERDP@gDORRckb?<5kO;0ONPP`fL(QhJc`e+HxsKi#^QQk zWV~I{eZ09gktR_&QeNJeF>L@F?_nUbv_L3aB$Ew&BujX%U=~%&TmYH4!-uB@(ERFa z1qyrJF4$4)_^>48x7lA~<8gt)-qOn2f}{b&ik$#l8%l+_>B+^%GR&LrW9uppfXijc ziKGCUx9w^K>N5S%RF>rG$Kz-bGEQ1}e z*;AP~mMVI@q@?6Ax5of(4@D1v<}X_ylt1fm<4q*LO>Lo@qWKm;zAr6sU{ZkQ*48Xk z4+_v$Kf~YvmI1%b>or~kKsZ=dSC=&*fQh<~0_j!7!qS|{0lZ`XQB`cuBxC(HPv=;y zD{`ZdZXz80SAeFLoy98J=JP;H)zllWx>%THgU1zPU1{pX14pwEs_>BF5fp7Jt6Ez; z);)e7FmMVmo5~HdC-ECoUas)r8y2cLlVBk?vZwA7q6i6^s&NVydz?*5OMH}elqSZjYP}1g z(g@@)NDg56QsJF_7LjNc3$q;FZCw@^p)l9N2*jb%AoRx-dU}(8A!P?}9vmPNgShhj zZ!zKuBJ>+k?F2acwK5W!%3+2Y7-l%4oc=BhfX3;Rm$&SmNILx`O|3p>cfG%-*$I*M_?L{(g UkdM1^r~m)}07*qoM6N<$f+i?#!~g&Q literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 542cac7..d302c17 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -A [Docker Mod](https://github.com/linuxserver/docker-mods) for the LinuxServer.io Lidarr Docker container that adds a script to automatically convert downloaded FLAC files to MP3s using ffmpeg. Default quality is 320Kbps. +A [Docker Mod](https://github.com/linuxserver/docker-mods) for the LinuxServer.io Lidarr Docker container that uses ffmpeg and a script to automatically convert downloaded FLAC files to MP3s. Default quality is 320Kbps constant bit rate. ->**NOTE:** This mod support Linux OSes only. +>**NOTE:** This mod supports Linux OSes only. Container info: -![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/thecaptain989/lidarr-flac2mp3) +![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/thecaptain989/lidarr-flac2mp3 "Image Size") ![Docker Pulls](https://img.shields.io/docker/pulls/thecaptain989/lidarr-flac2mp3 "Container Pulls") # Installation @@ -20,39 +20,50 @@ Container info: 2. Start the container. -3. After all of the above configuration is complete, to use ffmpeg, configure a custom script from the Settings->Connect screen and type the following in the **Path** field: +3. After the above configuration is complete, to use ffmpeg, configure a custom script from Lidarr's *Settings* > *Connect* screen and type the following in the **Path** field: `/usr/local/bin/flac2mp3.sh` + *Example* + ![lidarr-flac2mp3](.assets/lidarr-custom-script.png "Lidarr Custom Script dialog") + + This will use the defaults to create a 320Kbps MP3 file. + + *For any other setting, you **must** either user one of the [included wrapper scripts](./README.md#included-wrapper-scripts) or create a custom script with the command line options you desire. See the [Syntax](./README.md#syntax) section below.* + ## Usage -New file(s) with an MP3 extension will be placed in the same directory as the original FLAC file(s). Existing MP3 files with the same track name will be overwritten. +New file(s) with an MP3 extension will be placed in the same directory as the original FLAC file(s) and have the same owner and permissions. Existing MP3 files with the same track name will be overwritten. -If you've configured the Lidarr Recycle Bin path correctly, the original video will be moved there. -![warning24] **NOTE:** If you have *not* configured the Recycle Bin, the original FLAC audio file(s) will be deleted and permanently lost. +If you've configured Lidarr's **Recycle Bin** path correctly, the original audio file will be moved there. +![danger] **NOTE:** If you have *not* configured the Recycle Bin, the original FLAC audio file(s) will be deleted and permanently lost. ### Syntax >**Note:** The **Arguments** field for Custom Scripts was removed in Lidarr release [v0.7.0.1347](https://github.com/lidarr/Lidarr/commit/b9d240924f8965ebb2c5e307e36b810ae076101e "Lidarr commit notes") due to security concerns. To support options with this version and later, a wrapper script can be manually created that will call *flac2mp3.sh* with the required arguments. -The script accepts two options which may be placed in the **Arguments** field: +The script accepts three command line options: -`[-d] [-b ]` +`[-d] [-b | -v ]` -The `-b bitrate` option, if specified, sets the output quality in bits per second. If no `-b` option is specified, the script will default to 320Kbps. +The `-b bitrate` option sets the output quality in constant bits per second (CBR). +The `-v quality` option sets the output quality using a variable bit rate (VBR) where `quality` is a value between 0 and 9, with 0 being the highest quality. See the [FFmpeg MP3 Encoding Guide](https://trac.ffmpeg.org/wiki/Encode/MP3) for more details. +If neither `-b` nor `-v` options are specified, the script will default to constant 320Kbps. The `-d` option enables debug logging. ### Examples ``` --b 320k # Output 320 kilobits per second MP3 (same as default behavior) --d -b 160k # Enable debugging, and output 160 kilobits per second MP3 +-b 320k # Output 320 kbit/s MP3 (non VBR; same as default behavior) +-v 0 # Output variable bitrate, VBR 220-260 kbit/s +-d -b 160k # Enable debugging, and output 160 kbit/s MP3 ``` -### Included Wrapper Script -For your convenience, a wrapper script to enable debugging is included in the `/usr/local/bin/` directory. -Use this script in place of the `flac2mp3.sh` mentioned in the [Installation](./README.md#installation) section above. +### Included Wrapper Scripts +For your convenience, several wrapper scripts are included in the `/usr/local/bin/` directory. +You may use any of these scripts in place of the `flac2mp3.sh` mentioned in the [Installation](./README.md#installation) section above. ``` flac2mp3-debug.sh # Enable debugging +flac2mp3-vbr.sh # Use variable bit rate, quality 0 ``` ### Example Wrapper Script @@ -67,24 +78,24 @@ Then put `/usr/local/bin/wrapper.sh` in the **Path** field in place of `/usr/loc ### Triggers The only events/notification triggers that have been tested are **On Release Import** and **On Upgrade** -![lidarr-flac2mp3](.assets/lidarr-custom-script.png "Lidarr Custom Script dialog") - ### Logs A log file is created for the script activity called: `/config/logs/flac2mp3.txt` -This log can be downloaded from the Lidarr GUI under System->Log Files +This log can be downloaded from Lidarr under *System* > *Log Files* Log rotation is performed, with 5 log files of 1MB each kept, matching Lidarr's log retention. ->![warning24] **NOTE:** If debug logging is enabled, the log file can grow very large very quickly. *Do not leave debug logging enabled permanently.* +>![danger] **NOTE:** If debug logging is enabled, the log file can grow very large very quickly. *Do not leave debug logging enabled permanently.* ## Credits This would not be possible without the following: [Lidarr](https://lidarr.audio/ "Lidarr homepage") [LinuxServer.io Lidarr](https://hub.docker.com/r/linuxserver/lidarr "Lidarr Docker container") container -[ffmpeg](https://ffmpeg.org/ "FFMpeg homepage") +[LinuxServer.io Docker Mods](https://hub.docker.com/r/linuxserver/mods "Docker Mods containers") project +[ffmpeg](https://ffmpeg.org/ "FFMpeg homepage") +Icons made by [Freepik](https://www.freepik.com) from [Flaticon](https://www.flaticon.com/) -[warning]: http://files.softicons.com/download/application-icons/32x32-free-design-icons-by-aha-soft/png/32/Warning.png "Warning" -[warning24]: http://files.softicons.com/download/toolbar-icons/24x24-free-pixel-icons-by-aha-soft/png/24x24/Warning.png "Warning" +[warning]: .assets/warning.png "Warning" +[danger]: .assets/danger.png "Danger" diff --git a/root/usr/local/bin/flac2mp3-vbr.sh b/root/usr/local/bin/flac2mp3-vbr.sh new file mode 100644 index 0000000..9fff691 --- /dev/null +++ b/root/usr/local/bin/flac2mp3-vbr.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +. /usr/local/bin/flac2mp3.sh -v 0 diff --git a/root/usr/local/bin/flac2mp3.sh b/root/usr/local/bin/flac2mp3.sh index 45d0112..0c11e2e 100644 --- a/root/usr/local/bin/flac2mp3.sh +++ b/root/usr/local/bin/flac2mp3.sh @@ -3,17 +3,19 @@ # Script to convert FLAC files to MP3 using FFMpeg # https://github.com/TheCaptain989/lidarr-flac2mp3 # Can also process MP3s and tag them appropriately -# Resultant MP3s are fully tagged +# Resultant MP3s are fully tagged and retain same permissions as original file # Dependencies: # ffmpeg # awk # stat +# chmod # Exit codes: # 0 - success; or test -# 1 - no tracks files specified on command line +# 1 - no tracks files found in environment # 2 - mkvmerge not found +# 3 - invalid command line arguments # 10 - awk script generated an error ### Variables @@ -33,25 +35,25 @@ RET=$?; [ "$RET" != 0 ] && >&2 echo "WARNING[$RET]: Unable to read recyclebin in function usage { usage=" $flac2mp3_script -Audio conversion script designed for use with Bazarr +Audio conversion script designed for use with Lidarr Source: https://github.com/TheCaptain989/lidarr-flac2mp3 Usage: - $0 [-d] [-b ] - -Arguments: - bitrate # output quality in bits per second (SI units) + $0 [-d] [-b | -v ] Options: - -d # enable debug logging - -b # set bitrate; default 320K + -d enable debug logging + -b set output quality in constant bits per second [default: 320k] + Ex: 160k, 240k, 300000 + -v set variable bitrate; quality between 0-9 + 0 is highest quality, 9 is lowest + See https://trac.ffmpeg.org/wiki/Encode/MP3 for more details Examples: - $flac2mp3_script -b 320k # Output 320 kilobits per second MP3 - (same as default behavior) - $flac2mp3_script -d -b 160k # Enable debugging, and output quality - 160 kilobits per second + $flac2mp3_script -b 320k # Output 320 kbit/s MP3 (non VBR; same as default behavior) + $flac2mp3_script -v 0 # Output variable bitrate, VBR 220-260 kbit/s + $flac2mp3_script -d -b 160k # Enable debugging and set output to 160 kbit/s " >&2 echo "$usage" } @@ -118,7 +120,7 @@ function check_rescan { return $RET } # Process options -while getopts ":db:" opt; do +while getopts ":db:v:" opt; do case ${opt} in d ) # For debug purposes only MSG="Debug|Enabling debug logging." @@ -127,27 +129,57 @@ while getopts ":db:" opt; do flac2mp3_debug=1 printenv | sort | sed 's/^/Debug|/' | log ;; - b ) # Set bitrate - flac2mp3_bitrate="$OPTARG" + b ) # Set constant bit rate + if [ -n "$flac2mp3_vbrquality" ]; then + MSG="Error|Both -b and -v options cannot be set at the same time." + echo "$MSG" | log + >&2 echo "$MSG" + usage + exit 3 + else + flac2mp3_bitrate="$OPTARG" + fi + ;; + v ) # Set variable quality + if [ -n "$flac2mp3_bitrate" ]; then + MSG="Error|Both -v and -b options cannot be set at the same time." + echo "$MSG" | log + >&2 echo "$MSG" + usage + exit 3 + else + flac2mp3_vbrquality="$OPTARG" + fi + ;; + : ) # No required argument specified + MSG="Error|Invalid option: -${OPTARG} requires an argument" + echo "$MSG" | log + >&2 echo "$MSG" + usage + exit 3 ;; - : ) - MSG="Error|Invalid option: -$OPTARG requires an argument" + * ) # Unknown option + MSG="Error|Unknown option: -${OPTARG}" echo "$MSG" | log >&2 echo "$MSG" + usage + exit 3 ;; esac done shift $((OPTIND -1)) -# Set default bitrate -[ -z "$flac2mp3_bitrate" ] && flac2mp3_bitrate="320k" +# Set default bit rate +[ -z "$flac2mp3_vbrquality" ] && [ -z "$flac2mp3_bitrate" ] && flac2mp3_bitrate="320k" +# Handle Lidarr Test event if [[ "$lidarr_eventtype" = "Test" ]]; then echo "Info|Lidarr event: $lidarr_eventtype" | log echo "Info|Script was test executed successfully." | log exit 0 fi +# Chick if called from within Lidarr if [ -z "$flac2mp3_tracks" ]; then MSG="Error|No track file(s) specified! Not called from Lidarr?" echo "$MSG" | log @@ -156,6 +188,7 @@ if [ -z "$flac2mp3_tracks" ]; then exit 1 fi +# Check for required binaries if [ ! -f "/usr/bin/ffmpeg" ]; then MSG="Error|/usr/bin/ffmpeg is required by this script" echo "$MSG" | log @@ -163,48 +196,67 @@ if [ ! -f "/usr/bin/ffmpeg" ]; then exit 2 fi -# Legacy one-liner script +# Legacy one-liner script for posterity #find "$lidarr_artist_path" -name "*.flac" -exec bash -c 'ffmpeg -loglevel warning -i "{}" -y -acodec libmp3lame -b:a 320k "${0/.flac}.mp3" && rm "{}"' {} \; #### MAIN echo "Info|Lidarr event: $lidarr_eventtype, Artist: $lidarr_artist_name ($lidarr_artist_id), Album: $lidarr_album_title ($lidarr_album_id), Export bitrate: $flac2mp3_bitrate, Tracks: $flac2mp3_tracks" | log echo "$flac2mp3_tracks" | awk -v Debug=$flac2mp3_debug \ -v Recycle="$flac2mp3_recyclebin" \ --v Bitrate=$flac2mp3_bitrate ' +-v Bitrate=$flac2mp3_bitrate \ +-v VBR=$flac2mp3_vbrquality ' BEGIN { FFMpeg="/usr/bin/ffmpeg" FS="|" RS="|" IGNORECASE=1 + if (Bitrate) { + if (Debug) print "Debug|Using constant bitrate of "Bitrate + BrCommand="-b:a "Bitrate + } else { + if (Debug) print "Debug|Using variable quality of "VBR + BrCommand="-q:a "VBR + } } /\.flac/ { + # Get each FLAC file name and create a new MP3 name Track=$1 sub(/\n/,"",Track) NewTrack=substr(Track, 1, length(Track)-5)".mp3" print "Info|Writing: "NewTrack - if (Debug) print "Debug|Executing: nice "FFMpeg" -loglevel error -i \""Track"\" "CoverCmds1"-map 0 -y -acodec libmp3lame -b:a "Bitrate" -write_id3v1 1 -id3v2_version 3 "CoverCmds2"\""NewTrack"\"" - Result=system("nice "FFMpeg" -loglevel error -i \""Track"\" "CoverCmds1"-map 0 -y -acodec libmp3lame -b:a "Bitrate" -write_id3v1 1 -id3v2_version 3 "CoverCmds2"\""NewTrack"\" 2>&1") + # Convert the track + if (Debug) print "Debug|Executing: nice "FFMpeg" -loglevel error -i \""Track"\" -c:v copy -map 0 -y -acodec libmp3lame "BrCommand" -write_id3v1 1 -id3v2_version 3 \""NewTrack"\"" + Result=system("nice "FFMpeg" -loglevel error -i \""Track"\" -c:v copy -map 0 -y -acodec libmp3lame "BrCommand" -write_id3v1 1 -id3v2_version 3 \""NewTrack"\" 2>&1") if (Result) { - print "Error|"Result" converting \""Track"\"" + print "Error|Exit code "Result" converting \""Track"\"" } else { if (Recycle=="") { - if (Debug) print "Debug|Deleting: \""Track"\"" - system("[ -s \""NewTrack"\" ] && [ -f \""Track"\" ] && rm \""Track"\"") + # No Recycle Bin, so check for non-zero size new file and delete the old one + if (Debug) print "Debug|Deleting: \""Track"\" and setting permissions on \""NewTrack"\"" + #Command="[ -s \""NewTrack"\" ] && [ -f \""Track"\" ] && chown --reference=\""Track"\" \""NewTrack"\" && chmod --reference=\""Track"\" \""NewTrack"\" && rm \""Track"\"" + Command="if [ -s \""NewTrack"\" ]; then if [ -f \""Track"\" ]; then chown --reference=\""Track"\" \""NewTrack"\"; chmod --reference=\""Track"\" \""NewTrack"\"; rm \""Track"\"; fi; fi" + if (Debug) print "Debug|Executing: "Command + system(Command) } else { + # Recycle Bin is configured, so check if it exists, append a relative path to it from the track, check for non-zero size new file, and move the old one to the Recycle Bin match(Track,/^\/?[^\/]+\//) RecPath=substr(Track,RSTART+RLENGTH) sub(/[^\/]+$/,"",RecPath) RecPath=Recycle RecPath - if (Debug) print "Debug|Moving: \""Track"\" to \""RecPath"\"" - system("[ ! -e \""RecPath"\" ] && mkdir -p \""RecPath"\"; [ -s \""NewTrack"\" ] && [ -f \""Track"\" ] && mv -t \""RecPath"\" \""Track"\"") + if (Debug) print "Debug|Moving: \""Track"\" to \""RecPath"\" and setting permissions on \""NewTrack"\"" + Command="if [ ! -e \""RecPath"\" ]; then mkdir -p \""RecPath"\"; fi; if [ -s \""NewTrack"\" ]; then if [ -f \""Track"\" ]; then chown --reference=\""Track"\" \""NewTrack"\"; chmod --reference=\""Track"\" \""NewTrack"\"; mv -t \""RecPath"\" \""Track"\"; fi; fi" + if (Debug) print "Debug|Executing: "Command + system(Command) } } } ' | log +#### END MAIN + +# Check for awk script completion RET="${PIPESTATUS[1]}" # captures awk exit status if [ $RET != "0" ]; then - # Check for script completion and non-empty file MSG="Error|Script exited abnormally. File permissions issue?" echo "$MSG" | log >&2 echo "$MSG" @@ -240,11 +292,13 @@ if [ ! -z "$lidarr_artist_id" ]; then >&2 echo "$MSG" fi else + # No config file means we can't call the API MSG="Warn|Unable to locate Lidarr config file: '$flac2mp3_config'" echo "$MSG" | log >&2 echo "$MSG" fi else + # No Artist ID means we can't call the API MSG="Warn|Missing environment variable lidarr_artist_id" echo "$MSG" | log >&2 echo "$MSG"