From 0a45a17e38da37a0dce44b750e722a2268ff2f99 Mon Sep 17 00:00:00 2001 From: TheCaptain989 Date: Sun, 4 Jul 2021 17:46:43 -0500 Subject: [PATCH 1/5] Release 1.2.2 - Removed dependency on sqlite - Renamed more variables to avoid name collisions - Added additional debug logging - Reordered error redirects. No functional difference. --- README.md | 1 + root/usr/local/bin/flac2mp3.sh | 195 +++++++++++++++++++-------------- 2 files changed, 111 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index b08b312..5f3d4bf 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Production Container info: ![Docker Image Size](https://img.shields.io/docker/im 2. Configure the Docker container with all the port, volume, and environment settings from the *original container documentation* here: **[linuxserver/lidarr](https://hub.docker.com/r/linuxserver/lidarr "Docker container")** 1. Add a **DOCKER_MODS** environment variable to the `docker run` command, as follows: + - Dev/test release: `-e DOCKER_MODS=thecaptain989/lidarr-flac2mp3:latest` - Stable release: `-e DOCKER_MODS=linuxserver/mods:lidarr-flac2mp3` *Example Docker CLI Configuration* diff --git a/root/usr/local/bin/flac2mp3.sh b/root/usr/local/bin/flac2mp3.sh index b157243..f589d37 100644 --- a/root/usr/local/bin/flac2mp3.sh +++ b/root/usr/local/bin/flac2mp3.sh @@ -29,8 +29,6 @@ export flac2mp3_maxlog=4 export flac2mp3_debug=0 export flac2mp3_tracks="$lidarr_addedtrackpaths" [ -z "$flac2mp3_tracks" ] && flac2mp3_tracks="$lidarr_trackfile_path" # For other event type -export flac2mp3_recyclebin=$(sqlite3 /config/lidarr.db 'SELECT Value FROM Config WHERE Key="recyclebin"') -RET=$?; [ "$RET" != 0 ] && >&2 echo "WARNING[$RET]: Unable to read recyclebin information from database \"/config/lidarr.db\"" ### Functions function usage { @@ -56,7 +54,7 @@ Examples: $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" + echo "$usage" >&2 } # Can still go over flac2mp3_maxlog if read line is too long # Must include whole function in subshell for read to work! @@ -64,14 +62,13 @@ function log {( while read do echo $(date +"%y-%-m-%-d %H:%M:%S.%1N")\|"[$flac2mp3_pid]$REPLY" >>"$flac2mp3_log" - local FILESIZE=$(stat -c %s "$flac2mp3_log") - if [ $FILESIZE -gt $flac2mp3_maxlogsize ] + local flac2mp3_filesize=$(stat -c %s "$flac2mp3_log") + if [ $flac2mp3_filesize -gt $flac2mp3_maxlogsize ] then - for i in `seq $((flac2mp3_maxlog-1)) -1 0` - do + for i in $(seq $((flac2mp3_maxlog-1)) -1 0); do [ -f "${flac2mp3_log::-4}.$i.txt" ] && mv "${flac2mp3_log::-4}."{$i,$((i+1))}".txt" done - [ -f "${flac2mp3_log::-4}.txt" ] && mv "${flac2mp3_log::-4}.txt" "${flac2mp3_log::-4}.0.txt" + [ -f "${flac2mp3_log::-4}.txt" ] && mv "${flac2mp3_log::-4}.txt" "${flac2mp3_log::-4}.0.txt" touch "$flac2mp3_log" fi done @@ -79,62 +76,66 @@ function log {( # Inspired by https://stackoverflow.com/questions/893585/how-to-parse-xml-in-bash function read_xml { local IFS=\> - read -d \< ENTITY CONTENT + read -d \< flac2mp3_xml_entity flac2mp3_xml_content } # Initiate API Rescan request function rescan { - MSG="Info|Calling Lidarr API to rescan artist" - echo "$MSG" | log - [ $flac2mp3_debug -eq 1 ] && echo "Debug|Forcing rescan of artist '$lidarr_artist_id'. Calling Lidarr API 'RefreshArtist' using POST and URL 'http://$flac2mp3_bindaddress:$flac2mp3_port$flac2mp3_urlbase/api/v1/command?apikey=(removed)'" | log - RESULT=$(curl -s -d "{name: 'RefreshArtist', artistId: $lidarr_artist_id}" -H "Content-Type: application/json" \ - -X POST http://$flac2mp3_bindaddress:$flac2mp3_port$flac2mp3_urlbase/api/v1/command?apikey=$flac2mp3_apikey) - [ $flac2mp3_debug -eq 1 ] && echo "API returned: $RESULT" | awk '{print "Debug|"$0}' | log - JOBID="$(echo $RESULT | jq -crM .id)" - if [ "$JOBID" != "null" ]; then - local RET=0 + flac2mp3_message="Info|Calling Lidarr API to rescan artist" + echo "$flac2mp3_message" | log + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Forcing rescan of artist '$lidarr_artist_id'. Calling Lidarr API 'RefreshArtist' using POST and URL '$flac2mp3_api_url/command'" | log + flac2mp3_result=$(curl -s -H "X-Api-Key: $flac2mp3_apikey" \ + -d "{\"name\": 'RefreshArtist', \"artistId\": $lidarr_artist_id}" \ + -X POST "$flac2mp3_api_url/command") + [ $flac2mp3_debug -eq 1 ] && echo "API returned: $flac2mp3_result" | awk '{print "Debug|"$0}' | log + flac2mp3_jobid="$(echo $flac2mp3_result | jq -crM .id)" + if [ "$flac2mp3_jobid" != "null" ]; then + local flac2mp3_return=0 else - local RET=1 + local flac2mp3_return=1 fi - return $RET + return $flac2mp3_return } # Check result of rescan job function check_rescan { local i=0 for ((i=1; i <= 15; i++)); do - [ $flac2mp3_debug -eq 1 ] && echo "Debug|Checking job $JOBID completion, try #$i. Calling Lidarr API using GET and URL 'http://$flac2mp3_bindaddress:$flac2mp3_port$flac2mp3_urlbase/api/command/$JOBID?apikey=(removed)'" | log - RESULT=$(curl -s -H "Content-Type: application/json" \ - -X GET http://$flac2mp3_bindaddress:$flac2mp3_port$flac2mp3_urlbase/api/v1/command/$JOBID?apikey=$flac2mp3_apikey) - [ $flac2mp3_debug -eq 1 ] && echo "API returned: $RESULT" | awk '{print "Debug|"$0}' | log - if [ "$(echo $RESULT | jq -crM .status)" = "completed" ]; then - local RET=0 + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Checking job $flac2mp3_jobid completion, try #$i. Calling Lidarr API using GET and URL '$flac2mp3_api_url/command/$flac2mp3_jobid'" | log + flac2mp3_result=$(curl -s -H "X-Api-Key: $flac2mp3_apikey" \ + -X GET "$flac2mp3_api_url/command/$flac2mp3_jobid") + [ $flac2mp3_debug -eq 1 ] && echo "API returned: $flac2mp3_result" | awk '{print "Debug|"$0}' | log + if [ "$(echo $flac2mp3_result | jq -crM .status)" = "completed" ]; then + local flac2mp3_return=0 break else - if [ "$(echo $RESULT | jq -crM .status)" = "failed" ]; then - local RET=2 + if [ "$(echo $flac2mp3_result | jq -crM .status)" = "failed" ]; then + local flac2mp3_return=2 break else - local RET=1 + # It may have timed out, so let's wait a second + local flac2mp3_return=1 + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Job not done. Waiting 1 second." | log sleep 1 fi fi done - return $RET + return $flac2mp3_return } + # Process options while getopts ":db:v:" opt; do case ${opt} in d ) # For debug purposes only - MSG="Debug|Enabling debug logging." - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Debug|Enabling debug logging." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 flac2mp3_debug=1 printenv | sort | sed 's/^/Debug|/' | log ;; 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" + flac2mp3_message="Error|Both -b and -v options cannot be set at the same time." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 usage exit 3 else @@ -143,9 +144,9 @@ while getopts ":db:v:" opt; do ;; 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" + flac2mp3_message="Error|Both -v and -b options cannot be set at the same time." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 usage exit 3 else @@ -153,16 +154,16 @@ while getopts ":db:v:" opt; do fi ;; : ) # No required argument specified - MSG="Error|Invalid option: -${OPTARG} requires an argument" - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Error|Invalid option: -${OPTARG} requires an argument" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 usage exit 3 ;; * ) # Unknown option - MSG="Error|Unknown option: -${OPTARG}" - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Error|Unknown option: -${OPTARG}" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 usage exit 3 ;; @@ -173,6 +174,40 @@ shift $((OPTIND -1)) # Set default bit rate [ -z "$flac2mp3_vbrquality" ] && [ -z "$flac2mp3_bitrate" ] && flac2mp3_bitrate="320k" +# Check for config file +if [ -f "$flac2mp3_config" ]; then + # Read Lidarr config.xml + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Reading from Lidarr config file '$flac2mp3_config'" | log + while read_xml; do + [[ $flac2mp3_xml_entity = "Port" ]] && flac2mp3_port=$flac2mp3_xml_content + [[ $flac2mp3_xml_entity = "UrlBase" ]] && flac2mp3_urlbase=$flac2mp3_xml_content + [[ $flac2mp3_xml_entity = "BindAddress" ]] && flac2mp3_bindaddress=$flac2mp3_xml_content + [[ $flac2mp3_xml_entity = "ApiKey" ]] && flac2mp3_apikey=$flac2mp3_xml_content + done < $flac2mp3_config + + [[ $flac2mp3_bindaddress = "*" ]] && flac2mp3_bindaddress=localhost + + # Build URL to Lidarr API + flac2mp3_api_url="http://$flac2mp3_bindaddress:$flac2mp3_port$flac2mp3_urlbase/api/v1" + + # Check Lidarr version + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Getting Lidarr version. Calling Lidarr API using GET and URL '$flac2mp3_api_url/system/status'" | log + flac2mp3_version=$(curl -s -H "X-Api-Key: $flac2mp3_apikey" \ + -X GET "$flac2mp3_api_url/system/status" | jq -crM .version) + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Detected Lidarr version $flac2mp3_version" | log + + # Get RecycleBin + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Getting Lidarr RecycleBin. Calling Lidarr API using GET and URL '$flac2mp3_api_url/config/mediamanagement'" | log + flac2mp3_recyclebin=$(curl -s -H "X-Api-Key: $flac2mp3_apikey" \ + -X GET "$flac2mp3_api_url/config/mediamanagement" | jq -crM .recycleBin) + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Detected Lidarr RecycleBin '$flac2mp3_recyclebin'" | log +else + # No config file means we can't call the API. Best effort at this point. + flac2mp3_message="Warn|Unable to locate Lidarr config file: '$flac2mp3_config'" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 +fi + # Handle Lidarr Test event if [[ "$lidarr_eventtype" = "Test" ]]; then echo "Info|Lidarr event: $lidarr_eventtype" | log @@ -182,18 +217,18 @@ fi # Check if called from within Lidarr if [ -z "$flac2mp3_tracks" ]; then - MSG="Error|No track file(s) specified! Not called from Lidarr?" - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Error|No track file(s) specified! Not called from Lidarr?" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 usage 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 - >&2 echo "$MSG" + flac2mp3_message="Error|/usr/bin/ffmpeg is required by this script" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 exit 2 fi @@ -244,7 +279,7 @@ BEGIN { RecPath=substr(Track,RSTART+RLENGTH) sub(/[^\/]+$/,"",RecPath) RecPath=Recycle RecPath - if (Debug) print "Debug|Moving: \""Track"\" to \""RecPath"\" and setting permissions on \""NewTrack"\"" + if (Debug) print "Debug|Recycling: \""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) @@ -256,55 +291,45 @@ BEGIN { #### END MAIN # Check for awk script completion -RET="${PIPESTATUS[1]}" # captures awk exit status -if [ $RET != "0" ]; then - MSG="Error|Script exited abnormally. File permissions issue?" - echo "$MSG" | log - >&2 echo "$MSG" +flac2mp3_return="${PIPESTATUS[1]}" # captures awk exit status +if [ $flac2mp3_return != "0" ]; then + flac2mp3_message="Error|Script exited abnormally. File permissions issue?" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 exit 10 fi # Call Lidarr API to RescanArtist -if [ ! -z "$lidarr_artist_id" ]; then - if [ -f "$flac2mp3_config" ]; then - # Read Lidarr config.xml - while read_xml; do - [[ $ENTITY = "Port" ]] && flac2mp3_port=$CONTENT - [[ $ENTITY = "UrlBase" ]] && flac2mp3_urlbase=$CONTENT - [[ $ENTITY = "BindAddress" ]] && flac2mp3_bindaddress=$CONTENT - [[ $ENTITY = "ApiKey" ]] && flac2mp3_apikey=$CONTENT - done < $flac2mp3_config - - [[ $flac2mp3_bindaddress = "*" ]] && flac2mp3_bindaddress=localhost - +if [ -n "$flac2mp3_api_url" ]; then + if [ "$lidarr_artist_id" ]; then # Scan the disk for the new audio tracks if rescan; then # Check that the rescan completed if ! check_rescan; then # Timeout or failure - MSG="Warn|Lidarr job ID $JOBID timed out or failed." - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Warn|Lidarr job ID $flac2mp3_jobid timed out or failed." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 fi else # Error from API - MSG="Error|The 'RefreshArtist' API with artist $lidarr_artist_id failed." - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Error|The 'RefreshArtist' API with artist $lidarr_artist_id failed." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 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" + # No Artist ID means we can't call the API + flac2mp3_message="Warn|Missing environment variable lidarr_artist_id" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 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" + # No URL means we can't call the API + flac2mp3_message="Warn|Unable to determine Lidarr API URL." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 fi # Cool bash feature -MSG="Info|Completed in $(($SECONDS/60))m $(($SECONDS%60))s" -echo "$MSG" | log +flac2mp3_message="Info|Completed in $(($SECONDS/60))m $(($SECONDS%60))s" +echo "$flac2mp3_message" | log From 4843b31d873cbeb183fff9b6495ae79cef09bf62 Mon Sep 17 00:00:00 2001 From: TheCaptain989 Date: Sun, 4 Jul 2021 17:55:39 -0500 Subject: [PATCH 2/5] Release 1.2.2 - Now uses the API to detect RecycleBin, removing dependency on sqlite - Fixes formatting bug with submitted JSON in curl - Adding URL quoting to curl commands - Renamed more variables to avoid name collisions - Added additional debug logging - Reordered error redirects; No functional difference. --- README.md | 1 + root/usr/local/bin/flac2mp3.sh | 195 +++++++++++++++++++-------------- 2 files changed, 111 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index b08b312..5f3d4bf 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Production Container info: ![Docker Image Size](https://img.shields.io/docker/im 2. Configure the Docker container with all the port, volume, and environment settings from the *original container documentation* here: **[linuxserver/lidarr](https://hub.docker.com/r/linuxserver/lidarr "Docker container")** 1. Add a **DOCKER_MODS** environment variable to the `docker run` command, as follows: + - Dev/test release: `-e DOCKER_MODS=thecaptain989/lidarr-flac2mp3:latest` - Stable release: `-e DOCKER_MODS=linuxserver/mods:lidarr-flac2mp3` *Example Docker CLI Configuration* diff --git a/root/usr/local/bin/flac2mp3.sh b/root/usr/local/bin/flac2mp3.sh index b157243..f589d37 100644 --- a/root/usr/local/bin/flac2mp3.sh +++ b/root/usr/local/bin/flac2mp3.sh @@ -29,8 +29,6 @@ export flac2mp3_maxlog=4 export flac2mp3_debug=0 export flac2mp3_tracks="$lidarr_addedtrackpaths" [ -z "$flac2mp3_tracks" ] && flac2mp3_tracks="$lidarr_trackfile_path" # For other event type -export flac2mp3_recyclebin=$(sqlite3 /config/lidarr.db 'SELECT Value FROM Config WHERE Key="recyclebin"') -RET=$?; [ "$RET" != 0 ] && >&2 echo "WARNING[$RET]: Unable to read recyclebin information from database \"/config/lidarr.db\"" ### Functions function usage { @@ -56,7 +54,7 @@ Examples: $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" + echo "$usage" >&2 } # Can still go over flac2mp3_maxlog if read line is too long # Must include whole function in subshell for read to work! @@ -64,14 +62,13 @@ function log {( while read do echo $(date +"%y-%-m-%-d %H:%M:%S.%1N")\|"[$flac2mp3_pid]$REPLY" >>"$flac2mp3_log" - local FILESIZE=$(stat -c %s "$flac2mp3_log") - if [ $FILESIZE -gt $flac2mp3_maxlogsize ] + local flac2mp3_filesize=$(stat -c %s "$flac2mp3_log") + if [ $flac2mp3_filesize -gt $flac2mp3_maxlogsize ] then - for i in `seq $((flac2mp3_maxlog-1)) -1 0` - do + for i in $(seq $((flac2mp3_maxlog-1)) -1 0); do [ -f "${flac2mp3_log::-4}.$i.txt" ] && mv "${flac2mp3_log::-4}."{$i,$((i+1))}".txt" done - [ -f "${flac2mp3_log::-4}.txt" ] && mv "${flac2mp3_log::-4}.txt" "${flac2mp3_log::-4}.0.txt" + [ -f "${flac2mp3_log::-4}.txt" ] && mv "${flac2mp3_log::-4}.txt" "${flac2mp3_log::-4}.0.txt" touch "$flac2mp3_log" fi done @@ -79,62 +76,66 @@ function log {( # Inspired by https://stackoverflow.com/questions/893585/how-to-parse-xml-in-bash function read_xml { local IFS=\> - read -d \< ENTITY CONTENT + read -d \< flac2mp3_xml_entity flac2mp3_xml_content } # Initiate API Rescan request function rescan { - MSG="Info|Calling Lidarr API to rescan artist" - echo "$MSG" | log - [ $flac2mp3_debug -eq 1 ] && echo "Debug|Forcing rescan of artist '$lidarr_artist_id'. Calling Lidarr API 'RefreshArtist' using POST and URL 'http://$flac2mp3_bindaddress:$flac2mp3_port$flac2mp3_urlbase/api/v1/command?apikey=(removed)'" | log - RESULT=$(curl -s -d "{name: 'RefreshArtist', artistId: $lidarr_artist_id}" -H "Content-Type: application/json" \ - -X POST http://$flac2mp3_bindaddress:$flac2mp3_port$flac2mp3_urlbase/api/v1/command?apikey=$flac2mp3_apikey) - [ $flac2mp3_debug -eq 1 ] && echo "API returned: $RESULT" | awk '{print "Debug|"$0}' | log - JOBID="$(echo $RESULT | jq -crM .id)" - if [ "$JOBID" != "null" ]; then - local RET=0 + flac2mp3_message="Info|Calling Lidarr API to rescan artist" + echo "$flac2mp3_message" | log + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Forcing rescan of artist '$lidarr_artist_id'. Calling Lidarr API 'RefreshArtist' using POST and URL '$flac2mp3_api_url/command'" | log + flac2mp3_result=$(curl -s -H "X-Api-Key: $flac2mp3_apikey" \ + -d "{\"name\": 'RefreshArtist', \"artistId\": $lidarr_artist_id}" \ + -X POST "$flac2mp3_api_url/command") + [ $flac2mp3_debug -eq 1 ] && echo "API returned: $flac2mp3_result" | awk '{print "Debug|"$0}' | log + flac2mp3_jobid="$(echo $flac2mp3_result | jq -crM .id)" + if [ "$flac2mp3_jobid" != "null" ]; then + local flac2mp3_return=0 else - local RET=1 + local flac2mp3_return=1 fi - return $RET + return $flac2mp3_return } # Check result of rescan job function check_rescan { local i=0 for ((i=1; i <= 15; i++)); do - [ $flac2mp3_debug -eq 1 ] && echo "Debug|Checking job $JOBID completion, try #$i. Calling Lidarr API using GET and URL 'http://$flac2mp3_bindaddress:$flac2mp3_port$flac2mp3_urlbase/api/command/$JOBID?apikey=(removed)'" | log - RESULT=$(curl -s -H "Content-Type: application/json" \ - -X GET http://$flac2mp3_bindaddress:$flac2mp3_port$flac2mp3_urlbase/api/v1/command/$JOBID?apikey=$flac2mp3_apikey) - [ $flac2mp3_debug -eq 1 ] && echo "API returned: $RESULT" | awk '{print "Debug|"$0}' | log - if [ "$(echo $RESULT | jq -crM .status)" = "completed" ]; then - local RET=0 + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Checking job $flac2mp3_jobid completion, try #$i. Calling Lidarr API using GET and URL '$flac2mp3_api_url/command/$flac2mp3_jobid'" | log + flac2mp3_result=$(curl -s -H "X-Api-Key: $flac2mp3_apikey" \ + -X GET "$flac2mp3_api_url/command/$flac2mp3_jobid") + [ $flac2mp3_debug -eq 1 ] && echo "API returned: $flac2mp3_result" | awk '{print "Debug|"$0}' | log + if [ "$(echo $flac2mp3_result | jq -crM .status)" = "completed" ]; then + local flac2mp3_return=0 break else - if [ "$(echo $RESULT | jq -crM .status)" = "failed" ]; then - local RET=2 + if [ "$(echo $flac2mp3_result | jq -crM .status)" = "failed" ]; then + local flac2mp3_return=2 break else - local RET=1 + # It may have timed out, so let's wait a second + local flac2mp3_return=1 + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Job not done. Waiting 1 second." | log sleep 1 fi fi done - return $RET + return $flac2mp3_return } + # Process options while getopts ":db:v:" opt; do case ${opt} in d ) # For debug purposes only - MSG="Debug|Enabling debug logging." - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Debug|Enabling debug logging." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 flac2mp3_debug=1 printenv | sort | sed 's/^/Debug|/' | log ;; 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" + flac2mp3_message="Error|Both -b and -v options cannot be set at the same time." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 usage exit 3 else @@ -143,9 +144,9 @@ while getopts ":db:v:" opt; do ;; 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" + flac2mp3_message="Error|Both -v and -b options cannot be set at the same time." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 usage exit 3 else @@ -153,16 +154,16 @@ while getopts ":db:v:" opt; do fi ;; : ) # No required argument specified - MSG="Error|Invalid option: -${OPTARG} requires an argument" - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Error|Invalid option: -${OPTARG} requires an argument" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 usage exit 3 ;; * ) # Unknown option - MSG="Error|Unknown option: -${OPTARG}" - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Error|Unknown option: -${OPTARG}" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 usage exit 3 ;; @@ -173,6 +174,40 @@ shift $((OPTIND -1)) # Set default bit rate [ -z "$flac2mp3_vbrquality" ] && [ -z "$flac2mp3_bitrate" ] && flac2mp3_bitrate="320k" +# Check for config file +if [ -f "$flac2mp3_config" ]; then + # Read Lidarr config.xml + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Reading from Lidarr config file '$flac2mp3_config'" | log + while read_xml; do + [[ $flac2mp3_xml_entity = "Port" ]] && flac2mp3_port=$flac2mp3_xml_content + [[ $flac2mp3_xml_entity = "UrlBase" ]] && flac2mp3_urlbase=$flac2mp3_xml_content + [[ $flac2mp3_xml_entity = "BindAddress" ]] && flac2mp3_bindaddress=$flac2mp3_xml_content + [[ $flac2mp3_xml_entity = "ApiKey" ]] && flac2mp3_apikey=$flac2mp3_xml_content + done < $flac2mp3_config + + [[ $flac2mp3_bindaddress = "*" ]] && flac2mp3_bindaddress=localhost + + # Build URL to Lidarr API + flac2mp3_api_url="http://$flac2mp3_bindaddress:$flac2mp3_port$flac2mp3_urlbase/api/v1" + + # Check Lidarr version + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Getting Lidarr version. Calling Lidarr API using GET and URL '$flac2mp3_api_url/system/status'" | log + flac2mp3_version=$(curl -s -H "X-Api-Key: $flac2mp3_apikey" \ + -X GET "$flac2mp3_api_url/system/status" | jq -crM .version) + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Detected Lidarr version $flac2mp3_version" | log + + # Get RecycleBin + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Getting Lidarr RecycleBin. Calling Lidarr API using GET and URL '$flac2mp3_api_url/config/mediamanagement'" | log + flac2mp3_recyclebin=$(curl -s -H "X-Api-Key: $flac2mp3_apikey" \ + -X GET "$flac2mp3_api_url/config/mediamanagement" | jq -crM .recycleBin) + [ $flac2mp3_debug -eq 1 ] && echo "Debug|Detected Lidarr RecycleBin '$flac2mp3_recyclebin'" | log +else + # No config file means we can't call the API. Best effort at this point. + flac2mp3_message="Warn|Unable to locate Lidarr config file: '$flac2mp3_config'" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 +fi + # Handle Lidarr Test event if [[ "$lidarr_eventtype" = "Test" ]]; then echo "Info|Lidarr event: $lidarr_eventtype" | log @@ -182,18 +217,18 @@ fi # Check if called from within Lidarr if [ -z "$flac2mp3_tracks" ]; then - MSG="Error|No track file(s) specified! Not called from Lidarr?" - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Error|No track file(s) specified! Not called from Lidarr?" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 usage 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 - >&2 echo "$MSG" + flac2mp3_message="Error|/usr/bin/ffmpeg is required by this script" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 exit 2 fi @@ -244,7 +279,7 @@ BEGIN { RecPath=substr(Track,RSTART+RLENGTH) sub(/[^\/]+$/,"",RecPath) RecPath=Recycle RecPath - if (Debug) print "Debug|Moving: \""Track"\" to \""RecPath"\" and setting permissions on \""NewTrack"\"" + if (Debug) print "Debug|Recycling: \""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) @@ -256,55 +291,45 @@ BEGIN { #### END MAIN # Check for awk script completion -RET="${PIPESTATUS[1]}" # captures awk exit status -if [ $RET != "0" ]; then - MSG="Error|Script exited abnormally. File permissions issue?" - echo "$MSG" | log - >&2 echo "$MSG" +flac2mp3_return="${PIPESTATUS[1]}" # captures awk exit status +if [ $flac2mp3_return != "0" ]; then + flac2mp3_message="Error|Script exited abnormally. File permissions issue?" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 exit 10 fi # Call Lidarr API to RescanArtist -if [ ! -z "$lidarr_artist_id" ]; then - if [ -f "$flac2mp3_config" ]; then - # Read Lidarr config.xml - while read_xml; do - [[ $ENTITY = "Port" ]] && flac2mp3_port=$CONTENT - [[ $ENTITY = "UrlBase" ]] && flac2mp3_urlbase=$CONTENT - [[ $ENTITY = "BindAddress" ]] && flac2mp3_bindaddress=$CONTENT - [[ $ENTITY = "ApiKey" ]] && flac2mp3_apikey=$CONTENT - done < $flac2mp3_config - - [[ $flac2mp3_bindaddress = "*" ]] && flac2mp3_bindaddress=localhost - +if [ -n "$flac2mp3_api_url" ]; then + if [ "$lidarr_artist_id" ]; then # Scan the disk for the new audio tracks if rescan; then # Check that the rescan completed if ! check_rescan; then # Timeout or failure - MSG="Warn|Lidarr job ID $JOBID timed out or failed." - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Warn|Lidarr job ID $flac2mp3_jobid timed out or failed." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 fi else # Error from API - MSG="Error|The 'RefreshArtist' API with artist $lidarr_artist_id failed." - echo "$MSG" | log - >&2 echo "$MSG" + flac2mp3_message="Error|The 'RefreshArtist' API with artist $lidarr_artist_id failed." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 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" + # No Artist ID means we can't call the API + flac2mp3_message="Warn|Missing environment variable lidarr_artist_id" + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 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" + # No URL means we can't call the API + flac2mp3_message="Warn|Unable to determine Lidarr API URL." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 fi # Cool bash feature -MSG="Info|Completed in $(($SECONDS/60))m $(($SECONDS%60))s" -echo "$MSG" | log +flac2mp3_message="Info|Completed in $(($SECONDS/60))m $(($SECONDS%60))s" +echo "$flac2mp3_message" | log From 8568b31bb1fafb5f510f9ecd91f2c0c14341b726 Mon Sep 17 00:00:00 2001 From: TheCaptain989 Date: Sun, 26 Sep 2021 14:01:03 -0500 Subject: [PATCH 3/5] Lidarr: flac2mp3 release 1.3 - Added advanced -a and -e options - Can now convert to any ffmpeg supported format - Added included script for Opus format --- README.md | 40 ++++++++--- root/etc/cont-init.d/98-flac2mp3 | 5 +- root/usr/local/bin/flac2mp3.sh | 119 +++++++++++++++++++++++++------ root/usr/local/bin/flac2opus.sh | 3 + 4 files changed, 133 insertions(+), 34 deletions(-) create mode 100644 root/usr/local/bin/flac2opus.sh diff --git a/README.md b/README.md index 5f3d4bf..1c0170e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # About 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 output quality is 320Kbps constant bit rate. +Advanced options act as a light wrapper to ffmpeg, allowing conversion to any supported audio format, including AAC, AC3, and Opus. >**NOTE:** This mod supports Linux OSes only. @@ -59,22 +60,42 @@ If you've configured Lidarr's **Recycle Bin** path correctly, the original audio >**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 three command line options: +The script accepts five command line options: -`[-d] [-b | -v ]` +`[-d] [-b | -v | -a "" -e ]` + +The `-b bitrate` option sets the output quality in constant bits per second (CBR). -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 `-a "options"` setting is used in conjunction with `-e` to set advanced ffmpeg options. The specified command line options replace all script defaults and are sent directly to ffmpeg. The `options` value must be enclosed in quotes. +![danger] **WARNING:** When using `-a`, you must specify an audio codec (via `-c:a`) or the resulting file will contain no audio. +![danger] **WARNING:** Invalid `options` could result in script failure! +See [FFmpeg Options](https://ffmpeg.org/ffmpeg.html#Options) for details on valid options. +See [Guidelines for high quality audio encoding](https://trac.ffmpeg.org/wiki/Encode/HighQualityAudio) for more information. + +The `-e extension` option sets the output file extension, and must be used in conjunction with `-a`. The `extension` may be prefixed by a dot (".") or not. + +If neither `-b`, `-v`, `-a`, or `-e` options are specified, the script will default to a constant 320Kbps MP3. The `-d` option enables debug logging. +#### Technical notes on `-a` advanced options +The `-a` option effectively makes the script a somewhat generic wrapper for ffmpeg. FFmpeg is executed once per track with only the loglevel, input filename, and output filename being set. All other options are passed unparsed to the command line. + +The exact format of the executed ffmpeg command is: +``` +ffmpeg -loglevel error -i "Original.flac" ${Options} "NewTrack${Extension}" +``` + ### Examples ``` -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 +-v 0 # Output variable bitrate MP3, VBR 220-260 kbit/s +-d -b 160k # Enable debugging, and output a 160 kbit/s MP3 +-a "-vn -c:a libopus -b:a 192K" -e .opus # Convert to Opus format, VBR 192 kbit/s, no cover art +-a "-y -map 0 -c:a aac -b:a 240K -c:v copy" -e mp4 # Convert to MP4 format, using AAC 240 kbit/s audio, cover art, overwrite file ``` ### Included Wrapper Scripts @@ -83,11 +104,12 @@ You may use any of these scripts in place of the `flac2mp3.sh` mentioned in the ``` flac2mp3-debug.sh # Enable debugging -flac2mp3-vbr.sh # Use variable bit rate, quality 0 +flac2mp3-vbr.sh # Use variable bit rate MP3, quality 0 +flac2opus.sh # Convert to Opus format using .opus extension ``` ### Example Wrapper Script -To configure the last entry from the [Examples](./README.md#examples) section above, create and save a file called `flac2mp3-custom.sh` to `/config` containing the following text: +To configure the middle entry from the [Examples](./README.md#examples) section above, create and save a file called `flac2mp3-custom.sh` to `/config` containing the following text: ```shell #!/bin/bash @@ -121,7 +143,7 @@ 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 [LinuxServer.io Docker Mods](https://hub.docker.com/r/linuxserver/mods "Docker Mods containers") project -[ffmpeg](https://ffmpeg.org/ "FFMpeg homepage") +[ffmpeg](https://ffmpeg.org/ "FFmpeg homepage") Icons made by [Freepik](https://www.freepik.com) from [Flaticon](https://www.flaticon.com/) [warning]: .assets/warning.png "Warning" diff --git a/root/etc/cont-init.d/98-flac2mp3 b/root/etc/cont-init.d/98-flac2mp3 index e8bff43..6f4a2a8 100644 --- a/root/etc/cont-init.d/98-flac2mp3 +++ b/root/etc/cont-init.d/98-flac2mp3 @@ -38,11 +38,12 @@ fi # Change ownership if [ $(stat -c '%G' /usr/local/bin/flac2mp3.sh) != "abc" ]; then echo "Changing ownership on scripts." - chown abc:abc /usr/local/bin/flac2mp3*.sh + chown abc:abc /usr/local/bin/flac2*.sh fi # Make executable if [ ! -x /usr/local/bin/flac2mp3.sh ]; then echo "Making scripts executable." - chmod +x /usr/local/bin/flac2mp3*.sh + chmod +x /usr/local/bin/flac2*.sh fi + diff --git a/root/usr/local/bin/flac2mp3.sh b/root/usr/local/bin/flac2mp3.sh index f589d37..f0488d6 100644 --- a/root/usr/local/bin/flac2mp3.sh +++ b/root/usr/local/bin/flac2mp3.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Script to convert FLAC files to MP3 using FFMpeg +# Script to convert FLAC files to MP3 using FFmpeg # Dev/test: https://github.com/TheCaptain989/lidarr-flac2mp3 # Prod: https://github.com/linuxserver/docker-mods/tree/lidarr-flac2mp3 # Resultant MP3s are fully tagged and retain same permissions as original file @@ -39,20 +39,32 @@ Audio conversion script designed for use with Lidarr Source: https://github.com/TheCaptain989/lidarr-flac2mp3 Usage: - $0 [-d] [-b | -v ] + $0 [-d] [-b | -v | -a \"\" -e ] Options: - -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 + -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 + -a \"\" advanced ffmpeg options enclosed in quotes + Specified options replace all script defaults and are sent as + entered to ffmpeg for processing. + See https://ffmpeg.org/ffmpeg.html#Options for details on valid options. + WARNING: You must specify an audio codec! + WARNING: Invalid options could result in script failure! + Requires -e option to also be specified + See https://github.com/TheCaptain989/lidarr-flac2mp3 for more details + -e file extension for output file, with or without dot + Required when -a is specified! Examples: - $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 + $flac2mp3_script -b 320k # Output 320 kbit/s MP3 (non VBR; same as default behavior) + $flac2mp3_script -v 0 # Output variable bitrate MP3, VBR 220-260 kbit/s + $flac2mp3_script -d -b 160k # Enable debugging and set output a 160 kbit/s MP3 + $flac2mp3_script -a \"-vn -c:a libopus -b:a 192K\" -e .opus # Convert to Opus format, VBR 192 kbit/s, no cover art + $flac2mp3_script -a \"-y -map 0 -c:a aac -b:a 240K -c:v copy\" -e mp4 # Convert to MP4 format, using AAC 240 kbit/s audio, cover art, overwrite file " echo "$usage" >&2 } @@ -122,7 +134,7 @@ function check_rescan { } # Process options -while getopts ":db:v:" opt; do +while getopts ":db:v:a:e:" opt; do case ${opt} in d ) # For debug purposes only flac2mp3_message="Debug|Enabling debug logging." @@ -138,6 +150,12 @@ while getopts ":db:v:" opt; do echo "$flac2mp3_message" >&2 usage exit 3 + elif [ -n "$flac2mp3_ffmpegadv" -o -n "$flac2mp3_extension" ]; then + flac2mp3_message="Error|The -a and -e options cannot be set at the same time as either -v or -b options." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 + usage + exit 3 else flac2mp3_bitrate="$OPTARG" fi @@ -149,10 +167,40 @@ while getopts ":db:v:" opt; do echo "$flac2mp3_message" >&2 usage exit 3 + elif [ -n "$flac2mp3_ffmpegadv" -o -n "$flac2mp3_extension" ]; then + flac2mp3_message="Error|The -a and -e options cannot be set at the same time as either -v or -b options." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 + usage + exit 3 else flac2mp3_vbrquality="$OPTARG" fi ;; + a ) # Set advanced options + if [ -n "$flac2mp3_vbrquality" -o -n "$flac2mp3_bitrate" ]; then + flac2mp3_message="Error|The -a and -e options cannot be set at the same time as either -v or -b options." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 + usage + exit 3 + else + flac2mp3_ffmpegadv="$OPTARG" + fi + ;; + e ) # Set file extension + if [ -n "$flac2mp3_vbrquality" -o -n "$flac2mp3_bitrate" ]; then + flac2mp3_message="Error|The -a and -e options cannot be set at the same time as either -v or -b options." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 + usage + exit 3 + else + flac2mp3_extension="$OPTARG" + fi + # Test for dot + [ "${flac2mp3_extension:0:1}" != "." ] && flac2mp3_extension=".${flac2mp3_extension}" + ;; : ) # No required argument specified flac2mp3_message="Error|Invalid option: -${OPTARG} requires an argument" echo "$flac2mp3_message" | log @@ -169,10 +217,18 @@ while getopts ":db:v:" opt; do ;; esac done +# Test for either -a and -e, but not both: logical XOR = non-equality +if [ "${flac2mp3_ffmpegadv:+data}" != "${flac2mp3_extension:+data}" ]; then + flac2mp3_message="Error|The -a and -e options must be specified together." + echo "$flac2mp3_message" | log + echo "$flac2mp3_message" >&2 + usage + exit 3 +fi shift $((OPTIND -1)) # Set default bit rate -[ -z "$flac2mp3_vbrquality" ] && [ -z "$flac2mp3_bitrate" ] && flac2mp3_bitrate="320k" +[ -z "$flac2mp3_vbrquality" -a -z "$flac2mp3_bitrate" -a -z "$flac2mp3_ffmpegadv" -a -z "$flac2mp3_extension" ] && flac2mp3_bitrate="320k" # Check for config file if [ -f "$flac2mp3_config" ]; then @@ -236,37 +292,54 @@ fi #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:-$flac2mp3_vbrquality}, Tracks: $flac2mp3_tracks" | log +flac2mp3_message="Info|Lidarr event: ${lidarr_eventtype}, Artist: ${lidarr_artist_name} (${lidarr_artist_id}), Album: ${lidarr_album_title} (${lidarr_album_id}), " +if [ -z "$flac2mp3_ffmpegadv" ]; then + flac2mp3_message+="Export bitrate: ${flac2mp3_bitrate:-$flac2mp3_vbrquality}" +else + flac2mp3_message+="Advanced options: '${flac2mp3_ffmpegadv}', File extension: ${flac2mp3_extension}" +fi +flac2mp3_message+=", Tracks: ${flac2mp3_tracks}" + +echo "${flac2mp3_message}" | log echo "$flac2mp3_tracks" | awk -v Debug=$flac2mp3_debug \ -v Recycle="$flac2mp3_recyclebin" \ --v Bitrate=$flac2mp3_bitrate \ --v VBR=$flac2mp3_vbrquality ' +-v Bitrate="$flac2mp3_bitrate" \ +-v VBR="$flac2mp3_vbrquality" \ +-v FFmpegADV="$flac2mp3_ffmpegadv" \ +-v EXT="$flac2mp3_extension" ' BEGIN { - FFMpeg="/usr/bin/ffmpeg" + FFmpeg="/usr/bin/ffmpeg" FS="|" RS="|" IGNORECASE=1 + if (EXT == "") EXT=".mp3" if (Bitrate) { if (Debug) print "Debug|Using constant bitrate of "Bitrate BrCommand="-b:a "Bitrate - } else { + } else if (VBR) { if (Debug) print "Debug|Using variable quality of "VBR BrCommand="-q:a "VBR + } else if (FFmpegADV) { + if (Debug) print "Debug|Using advanced ffmpeg options: \""FFmpegADV"\"" + if (Debug) print "Debug|Exporting with file extension "EXT } } /\.flac/ { - # Get each FLAC file name and create a new MP3 name + # Get each FLAC file name and create a new MP3 (or other) name Track=$1 sub(/\n/,"",Track) - NewTrack=substr(Track, 1, length(Track)-5)".mp3" + NewTrack=substr(Track, 1, length(Track)-5) EXT print "Info|Writing: "NewTrack + # Check for advanced options + if (FFmpegADV) FFmpegOPTS=FFmpegADV + else FFmpegOPTS="-c:v copy -map 0 -y -acodec libmp3lame "BrCommand" -write_id3v1 1 -id3v2_version 3" # 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 (Debug) print "Debug|Executing: nice "FFmpeg" -loglevel error -i \""Track"\" "FFmpegOPTS" \""NewTrack"\"" + Result=system("nice "FFmpeg" -loglevel error -i \""Track"\" "FFmpegOPTS" \""NewTrack"\" 2>&1") if (Result) { print "Error|Exit code "Result" converting \""Track"\"" } else { - if (Recycle=="") { + if (Recycle == "") { # 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"\"" diff --git a/root/usr/local/bin/flac2opus.sh b/root/usr/local/bin/flac2opus.sh new file mode 100644 index 0000000..2831e6b --- /dev/null +++ b/root/usr/local/bin/flac2opus.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +. /usr/local/bin/flac2mp3.sh -a "-c:v libtheora -map 0 -q:v 10 -c:a libopus -b:a 192K" -e .opus From 931a617946bff4b9901c5102feff38ea74c961fc Mon Sep 17 00:00:00 2001 From: TheCaptain989 Date: Sun, 26 Sep 2021 14:12:20 -0500 Subject: [PATCH 4/5] Included apt-get standardization apt-get update changes made by aptalca --- root/etc/cont-init.d/95-apt-get | 5 +++++ root/etc/cont-init.d/98-flac2mp3 | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 root/etc/cont-init.d/95-apt-get diff --git a/root/etc/cont-init.d/95-apt-get b/root/etc/cont-init.d/95-apt-get new file mode 100644 index 0000000..8e5fe66 --- /dev/null +++ b/root/etc/cont-init.d/95-apt-get @@ -0,0 +1,5 @@ +#!/usr/bin/with-contenv bash + +if [ -f /usr/bin/apt ]; then + apt-get update +fi diff --git a/root/etc/cont-init.d/98-flac2mp3 b/root/etc/cont-init.d/98-flac2mp3 index 6f4a2a8..c9caa82 100644 --- a/root/etc/cont-init.d/98-flac2mp3 +++ b/root/etc/cont-init.d/98-flac2mp3 @@ -18,7 +18,6 @@ if [ ! -f /usr/bin/ffmpeg ]; then if [ -f /usr/bin/apt ]; then # Ubuntu echo "Installing ffmpeg using apt-get" - apt-get update && \ apt-get -y install ffmpeg && \ rm -rf /var/lib/apt/lists/* elif [ -f /sbin/apk ]; then @@ -29,7 +28,6 @@ if [ ! -f /usr/bin/ffmpeg ]; then else # Unknown echo "Unknown package manager. Attempting to install ffmpeg using apt-get" - apt-get update && \ apt-get -y install ffmpeg && \ rm -rf /var/lib/apt/lists/* fi From 12feeae2b6a2860016fa4c75077c03e786f54136 Mon Sep 17 00:00:00 2001 From: TheCaptain989 Date: Mon, 27 Dec 2021 15:38:15 -0600 Subject: [PATCH 5/5] Release 1.3 - Added advanced -a and -e options - Script can now convert to any ffmpeg supported format - Added example script for Opus format --- README.md | 8 ++++---- SECURITY.md | 4 ++-- root/usr/local/bin/flac2opus.sh | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1c0170e..f5bae4d 100644 --- a/README.md +++ b/README.md @@ -94,8 +94,8 @@ ffmpeg -loglevel error -i "Original.flac" ${Options} "NewTrack${Extension}" -b 320k # Output 320 kbit/s MP3 (non VBR; same as default behavior) -v 0 # Output variable bitrate MP3, VBR 220-260 kbit/s -d -b 160k # Enable debugging, and output a 160 kbit/s MP3 --a "-vn -c:a libopus -b:a 192K" -e .opus # Convert to Opus format, VBR 192 kbit/s, no cover art --a "-y -map 0 -c:a aac -b:a 240K -c:v copy" -e mp4 # Convert to MP4 format, using AAC 240 kbit/s audio, cover art, overwrite file +-a "-c:v libtheora -map 0 -q:v 10 -c:a libopus -b:a 192k" -e .opus # Convert to Opus format, VBR 192 kbit/s, cover art +-a "-y -map 0 -c:a aac -b:a 240k -c:v copy" -e mp4 # Convert to MP4 format, using AAC 240 kbit/s audio, cover art, overwrite file ``` ### Included Wrapper Scripts @@ -105,7 +105,7 @@ You may use any of these scripts in place of the `flac2mp3.sh` mentioned in the ``` flac2mp3-debug.sh # Enable debugging flac2mp3-vbr.sh # Use variable bit rate MP3, quality 0 -flac2opus.sh # Convert to Opus format using .opus extension +flac2opus.sh # Convert to Opus format using .opus extension, 192 kbit/s, no covert art ``` ### Example Wrapper Script @@ -147,4 +147,4 @@ This would not be possible without the following: Icons made by [Freepik](https://www.freepik.com) from [Flaticon](https://www.flaticon.com/) [warning]: .assets/warning.png "Warning" -[danger]: .assets/danger.png "Danger" +[danger]: .assets/danger.png "Danger" \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md index 97dc1fc..b8a7d50 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,8 +6,8 @@ Only the latest major and minor version are supported. | Version | Supported | | ------- | ------------------ | -| 1.2.x | :heavy_check_mark: | -| < 1.2 | :x: | +| 1.3.x | :heavy_check_mark: | +| < 1.3 | :x: | ## Reporting a Vulnerability diff --git a/root/usr/local/bin/flac2opus.sh b/root/usr/local/bin/flac2opus.sh index 2831e6b..5ad9948 100644 --- a/root/usr/local/bin/flac2opus.sh +++ b/root/usr/local/bin/flac2opus.sh @@ -1,3 +1,3 @@ #!/bin/bash -. /usr/local/bin/flac2mp3.sh -a "-c:v libtheora -map 0 -q:v 10 -c:a libopus -b:a 192K" -e .opus +. /usr/local/bin/flac2mp3.sh -a "-vn -c:a libopus -b:a 192k" -e .opus