Merge pull request #1017 from TheCaptain989/lidarr-flac2mp3

lidarr: flac2mp3 release 2.4.3
This commit is contained in:
aptalca 2025-03-19 09:42:15 -04:00 committed by GitHub
commit 6a70b45f80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 200 additions and 120 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 947 B

BIN
.assets/notes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -3,8 +3,8 @@
.gitignore
.github
.gitattributes
.vscode
.assets
hooks
READMETEMPLATE.md
README.md
SECURITY.md

View File

@ -20,7 +20,7 @@ jobs:
echo "BASEIMAGE=${{ env.BASEIMAGE }}" >> $GITHUB_OUTPUT
echo "MODNAME=${{ env.MODNAME }}" >> $GITHUB_OUTPUT
# **** If the mod needs to be versioned, set the versioning logic below. Otherwise leave as is. ****
MOD_VERSION="2.4.0"
MOD_VERSION="2.4.3"
echo "MOD_VERSION=${MOD_VERSION}" >> $GITHUB_OUTPUT
outputs:
GITHUB_REPO: ${{ steps.outputs.outputs.GITHUB_REPO }}

206
README.md
View File

@ -1,23 +1,23 @@
# 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 (or other format) 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, Opus, and many others.
A [Batch Mode](./README.md#batch-mode) is also supported that allows usage outside of Lidarr.
A [Batch Mode](#batch-mode) is also supported that allows usage outside of Lidarr.
>**NOTE:** This mod supports Linux OSes only.
> [!NOTE]
> This mod supports Linux OSes only.
Production Container info: ![Docker Image Size](https://img.shields.io/docker/image-size/linuxserver/mods/lidarr-flac2mp3 "Container Size")
[![linuxserver/docker-mods/mods/lidarr-flac2mp3](https://img.shields.io/badge/dynamic/json?logo=github&url=https%3A%2F%2Fraw.githubusercontent.com%2Fthecaptain989%2Fghcr-pulls%2Fmaster%2Findex.json&query=%24%5B%3F(%40.owner%3D%3D%22linuxserver%22%20%26%26%20%40.repo%3D%3D%22docker-mods%22%20%26%26%20%40.image%3D%3D%22mods%22%20%26%26%20%40.tag%3D%3D%22lidarr-flac2mp3%22)%5D.pulls&label=ghcr%20pulls&color=1572A4)](https://github.com/linuxserver/docker-mods/pkgs/container/mods)
<!-- markdownlint-disable -->
Production Container info: [![Docker Image Size](https://img.shields.io/docker/image-size/linuxserver/mods/lidarr-flac2mp3)](https://hub.docker.com/r/linuxserver/mods/tags?name=lidarr-flac2mp3 "Docker image size")
[![linuxserver/docker-mods/mods/lidarr-flac2mp3](https://img.shields.io/badge/dynamic/json?logo=github&url=https%3A%2F%2Fthecaptain989.github.io%2Fghcr-pulls%2Flidarr-flac2mp3.json&query=%24.pulls&label=ghcr%20pulls&color=1572A4)](https://github.com/linuxserver/docker-mods/pkgs/container/mods "GitHub package pulls")
Development Container info:
![Docker Image Size](https://img.shields.io/docker/image-size/thecaptain989/lidarr-flac2mp3 "Container Size")
![Docker Pulls](https://img.shields.io/docker/pulls/thecaptain989/lidarr-flac2mp3?logo=docker "Container Pulls")
[![GitHub Super-Linter](https://github.com/TheCaptain989/lidarr-flac2mp3/actions/workflows/linter.yml/badge.svg)](https://github.com/TheCaptain989/lidarr-flac2mp3/actions/workflows/linter.yml "Linter Job")
[![Docker Image Size](https://img.shields.io/docker/image-size/thecaptain989/lidarr-flac2mp3)](https://hub.docker.com/r/thecaptain989/lidarr-flac2mp3 "Docker image size")
[![Docker Pulls](https://img.shields.io/docker/pulls/thecaptain989/lidarr-flac2mp3?logo=docker)](https://hub.docker.com/r/thecaptain989/lidarr-flac2mp3 "Docker container pulls")
[![Build Image](https://github.com/TheCaptain989/lidarr-flac2mp3/actions/workflows/BuildImage.yml/badge.svg)](https://github.com/TheCaptain989/lidarr-flac2mp3/actions/workflows/BuildImage.yml "BuildImage Job")
<!-- markdownlint-restore -->
# Installation
1. Pull the [linuxserver/lidarr](https://hub.docker.com/r/linuxserver/lidarr "LinuxServer.io's Lidarr container") docker image from GitHub Container Registry or Docker Hub:
`docker pull lscr.io/linuxserver/lidarr:latest`
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. 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 "Lidarr Docker container")**
1. Add a **DOCKER_MODS** environment variable to your `compose.yml` file or `docker run` command, as follows:
- Stable release: `DOCKER_MODS=linuxserver/mods:lidarr-flac2mp3`
- Dev/test release: `DOCKER_MODS=thecaptain989/lidarr-flac2mp3:latest`
@ -44,7 +44,8 @@ Development Container info:
restart: unless-stopped
```
*Example Docker Run Command*
<details>
<summary>Example Docker Run Command</summary>
```shell
docker run -d \
@ -61,29 +62,45 @@ Development Container info:
lscr.io/linuxserver/lidarr
```
</details>
<details>
<summary>Synology Screenshot</summary>
*Example Synology Configuration*
![flac2mp3](.assets/lidarr-synology.png "Synology container settings")
</details>
2. Start the container.
3. Configure a custom script from Lidarr's *Settings* > *Connect* screen and type the following in the **Path** field:
2. Configure a custom script from Lidarr's *Settings* > *Connect* screen and type the following in the **Path** field:
`/usr/local/bin/flac2mp3.sh`
*Example*
<details>
<summary>Screenshot</summary>
*Example Custom Script*
![lidarr-flac2mp3](.assets/lidarr-custom-script.png "Lidarr Custom Script dialog")
</details>
This will use the defaults to create a 320Kbps MP3 file.
*For any other setting, you **must** use one of the supported methods to pass arguments to the script. See the [Command-Line Syntax](./README.md#command-line-syntax) section below.*
> [!IMPORTANT]
> For any other setting, you **must** use one of the supported methods to pass arguments to the script. See the [Command-Line Syntax](#command-line-syntax) section below.
# Usage
New file(s) will be placed in the same directory as the original FLAC file(s) (unless redirected with the `--output` option below) with permissions preserved. Existing files with the same track name will be overwritten. Owner is preserved if the script is executed as root.
By default, 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. This behavior may be modified with the `--keep-file` option.
> [!TIP]
> By default, if you've configured Lidarr's **Recycle Bin** path correctly, the original audio file will be moved there.
> [!CAUTION]
> If you have *not* configured the Recycle Bin, the original FLAC audio file(s) will be deleted and permanently lost. This behavior may be modified with the `--keep-file` option.
## Command-Line 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.
> [!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.
### Options and Arguments
The script may be called with optional command-line arguments.
@ -91,27 +108,33 @@ The script may be called with optional command-line arguments.
The syntax for the command-line is:
`flac2mp3 [{-b|--bitrate} <bitrate> | {-v|--quality} <quality> | {-a|--advanced} "<options>" {-e|--extension} <extension>] [{-f|--file} <audio_file>] [{-k|--keep-file}] [{-o|--output} <directory>] [{-r|--regex} '<regex>'] [{-t|--tags} <taglist>] [{-l|--log} <log_file>] [{-d|--debug} [<level>]]`
Where:
<details>
<summary>Table of Command-Line Arguments</summary>
Option|Argument|Description
---|---|---
-b, --bitrate|\<bitrate\>|Sets the output quality in constant bits per second (CBR).<br/>Examples: 160k, 240k, 300000<br/>**Note:** May not be specified with `-v`, `-a`, or `-e`.
-v, --quality|\<quality\>|Sets the output variable bit rate (VBR).<br/>Specify a value between 0 and 9, with 0 being the highest quality.<br/>See the [FFmpeg MP3 Encoding Guide](https://trac.ffmpeg.org/wiki/Encode/MP3) for more details.<br/>**Note:** May not be specified with `-b`, `-a`, or `-e`.
-a, --advanced<!-- markdownlint-disable-line MD013 -->|\"\<options\>\"|Advanced ffmpeg options.<br />The specified `options` replace all script defaults and are sent directly to ffmpeg.<br/>The `options` value must be enclosed in quotes.<br/>See [FFmpeg Options](https://ffmpeg.org/ffmpeg.html#Options) for details on valid options, and [Guidelines for high quality audio encoding](https://trac.ffmpeg.org/wiki/Encode/HighQualityAudio) for suggested usage.<br/>**Note:** Requires the `-e` option to also be specified. May not be specified with `-v` or `-b`.<br/>![warning] **WARNING:** You must specify an audio codec (by including a `-c:a <codec>` ffmpeg option) or the resulting file will contain no audio!<br/>![warning] **WARNING:** Invalid `options` could result in script failure!
-e, --extension|\<extension\>|Sets the output file extension.<br/>The extension may be prefixed by a dot (".") or not.<br/>Example: .ogg<br/>**Note:** Requires the `-a` option to also be specified. May not be specified with `-v` or `-b`.
-f, --file|<audio_file>|If included, the script enters **[Batch Mode](./README.md#batch-mode)** and converts the specified audio file.<br/>![warning] **WARNING:** Do not use this argument when called from Lidarr!
-o, --output|\<directory\>|Converted audio file(s) are saved to `directory` instead of being located in the same directory as the source audio file.<br/>The path will be created if it does not exist.
-k, --keep-file| |Do not delete the source file or move it to the Lidarr Recycle bin.<br/>**Note:** This also disables importing the new files into Lidarr after conversion.
-r, --regex|'\<regex\>'|Sets the regular expression used to select input files.<br/>The `regex` value should be enclosed in single quotes and escaped properly.<br/>Defaults to `[.]flac$`.
-l, --log|\<log_file\>|The log filename<br/>Default of /config/log/flac2mp3.txt
-t, --tags|\<taglist\>|Comma separated list of metadata tags to apply automated corrections to.<br/>See [Metadata Corrections](./README.md#metadata-corrections) section.
-d, --debug|\[\<level\>\]|Enables debug logging. Level is optional.<br/>Default of 1 (low).<br/>2 includes JSON and FFmpeg output.<br/>3 contains even more JSON output.
--help| |Display help and exit.
--version| |Display version and exit.
`-b`, `--bitrate`|`<bitrate>`|Sets the output quality in constant bits per second (CBR).<br/>Examples: 160k, 240k, 300000<br/>**Note:** May not be specified with `-v`, `-a`, or `-e`.
`-v`, `--quality`|`<quality>`|Sets the output variable bit rate (VBR).<br/>Specify a value between 0 and 9, with 0 being the highest quality.<br/>See the [FFmpeg MP3 Encoding Guide](https://trac.ffmpeg.org/wiki/Encode/MP3) for more details.<br/>**Note:** May not be specified with `-b`, `-a`, or `-e`.
`-a`, `--advanced`<!-- markdownlint-disable-line MD013 -->|`"<options>"`|Advanced ffmpeg options.<br />The specified `options` replace all script defaults and are sent directly to ffmpeg.<br/>The `options` value must be enclosed in quotes.<br/>See [FFmpeg Options](https://ffmpeg.org/ffmpeg.html#Options) for details on valid options, and [Guidelines for high quality audio encoding](https://trac.ffmpeg.org/wiki/Encode/HighQualityAudio) for suggested usage.<br/>**Note:** Requires the `-e` option to also be specified. May not be specified with `-v` or `-b`.<br/>![warning] **WARNING:** You must specify an audio codec (by including a `-c:a <codec>` ffmpeg option) or the resulting file will contain no audio!<br/>![warning] **WARNING:** Invalid `options` could result in script failure!
`-e`, `--extension`|`<extension>`|Sets the output file extension.<br/>The extension may be prefixed by a dot (".") or not.<br/>Example: .ogg<br/>**Note:** Requires the `-a` option to also be specified. May not be specified with `-v` or `-b`.
`-f`, `--file`|`<audio_file>`|If included, the script enters **[Batch Mode](#batch-mode)** and converts the specified audio file.<br/>![note] **Do not** use this argument when called from Lidarr!
`-o`, `--output`|`<directory>`|Converted audio file(s) are saved to `directory` instead of being located in the same directory as the source audio file.<br/>The path will be created if it does not exist.
`-k`, `--keep-file`| |Do not delete the source file or move it to the Lidarr Recycle bin.<br/>**Note:** This also disables importing the new files into Lidarr after conversion.
`-r`, `--regex`|`'<regex>'`|Sets the regular expression used to select input files.<br/>The `regex` value should be enclosed in single quotes and escaped properly.<br/>Defaults to `[.]flac$`.
`-l`, `--log`|`<log_file>`|The log filename<br/>Default of /config/log/flac2mp3.txt
`-t`, `--tags`|`<taglist>`|Comma separated list of metadata tags to apply automated corrections to.<br/>See [Metadata Corrections](#metadata-corrections) section.
`-d`, `--debug`|`[<level>]`|Enables debug logging. Level is optional.<br/>Default of 1 (low).<br/>2 includes JSON and FFmpeg output.<br/>3 contains even more JSON output.
`--help`| |Display help and exit.
`--version`| |Display version and exit.
</details>
If neither `-b`, `-v`, `-a`, or `-e` options are specified, the script will default to a constant 320Kbps MP3.
#### Technical notes on advanced options
<details>
<summary>Advanced Options Details</summary>
The `-a` option effectively makes the script a 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:
@ -120,17 +143,20 @@ The exact format of the executed ffmpeg command is:
ffmpeg -loglevel error -nostdin -i "input.flac" ${options} "output.${extension}"
```
</details>
#### Technical notes on regular expressions
<details>
<summary>Regular Expression Details</summary>
<!-- textlint-disable terminology -->
By default, the script only matches and interacts with FLAC files (specifically, files ending in ".flac"). The `-r` option allows the script to match on a user specified regular expression (i.e. "regex") pattern.
By default, the script only matches and interacts with FLAC files (specifically, files ending in ".flac"). The `--regex` option allows the script to match on a user specified regular expression (i.e. "regex") pattern.
<!-- textlint-enable -->
Files are passed to the script with the full Linux path intact. (Ex: `/path/to/audio/a-ha/Hunting High and Low/01 Take on Me.mp3`). Craft your regular expression with this in mind.
![warning] **NOTE:** Escaping special regular expression characters (like a dot `.`) requires a double backslash or a character class. A character class (i.e. `[.]`) is recommended because backslashes can be stripped by the bash shell and getting this right can be confusing.
For example, to convert all audio files to AAC audio files, use the following options:
```shell
@ -139,7 +165,14 @@ For example, to convert all audio files to AAC audio files, use the following op
Regular expression syntax is beyond the scope of this document. See this [tutorial](https://www.regular-expressions.info/tutorial.html "Regular Expressions Tutorial") for more information. Regular expression patterns may be tested [here](http://regexstorm.net/tester "regex tester").
</details>
> [!TIP]
> Escaping special regular expression characters (like a dot `.`) requires a double backslash or a character class. A character class (i.e. `[.]`) is recommended because backslashes can be stripped by the bash shell and getting this right can be confusing.
## Examples
<details>
<summary>Command-line Examples</summary>
```shell
-b 320k # Output 320 kbit/s MP3 (non-VBR; same as default behavior)
@ -159,12 +192,21 @@ Regular expression syntax is beyond the scope of this document. See this [tutor
# Place the converted file(s) in the specified directory and do not delete the original audio file(s)
```
</details>
## Wrapper Scripts
To supply arguments to the script, you must either use one of the included wrapper scripts, create a custom wrapper script, or set the `FLAC2MP3_ARGS` [environment variable](./README.md#environment-variable).
To supply arguments to the script, you must either use one of the included wrapper scripts, create a custom wrapper script, or set the `FLAC2MP3_ARGS` [environment variable](#environment-variable).
> [!TIP]
> If you followed the Linuxserver.io recommendations when configuring your container, the `/config` directory will be mapped to an external storage location.
> It is therefore recommended to place custom scripts in the `/config` directory so they will survive container updates, but they may be placed anywhere that is accessible by Lidarr.
### 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.
You may use any of these scripts in place of the `flac2mp3.sh` mentioned in the [Installation](#installation) section above.
<details>
<summary>List of scripts</summary>
```shell
flac2mp3-debug.sh # Enable debugging, level 1
@ -174,8 +216,13 @@ flac2opus.sh # Convert to Opus format using .opus extension, 192 kbi
flac2alac.sh # Convert to Apple Lossless using an .m4a extension
```
</details>
### Example Wrapper Script
To configure an entry from the [Examples](./README.md#examples) section above, create and save a file called `flac2mp3-custom.sh` to `/config` containing the following text:
<details>
<summary>Example Script</summary>
To configure an entry from the [Examples](#examples) section above, create and save a file called `flac2mp3-custom.sh` to `/config` containing the following text:
```shell
#!/bin/bash
@ -189,68 +236,93 @@ Make it executable:
chmod +x /config/flac2mp3-custom.sh
```
Then put `/config/flac2mp3-custom.sh` in the **Path** field in place of `/usr/local/bin/flac2mp3.sh` mentioned in the [Installation](./README.md#installation) section above.
Then put `/config/flac2mp3-custom.sh` in the **Path** field in place of `/usr/local/bin/flac2mp3.sh` mentioned in the [Installation](#installation) section above.
>**Note:** If you followed the Linuxserver.io recommendations when configuring your container, the `/config` directory will be mapped to an external storage location. It is therefore recommended to place custom scripts in the `/config` directory so they will survive container updates, but they may be placed anywhere that is accessible by Lidarr.
</details>
## Environment Variable
The `flac2mp3.sh` script also allows the use of arguments provided by the `FLAC2MP3_ARGS` environment variable. This allows advanced use cases without having to provide a custom script.
The script can also read arguments from the `FLAC2MP3_ARGS` environment variable. This allows advanced use cases without having to provide a custom wrapper script.
For example, the following value in your `docker run` command would convert any .mp3 to Opus:
Make sure to correctly use quotes and/or escape special characters when using this method. (See [regular expression notes](#technical-notes-on-regular-expressions) above.)
```shell
-e FLAC2MP3_ARGS='-a "-vn -c:a libopus -b:a 192k" -e .opus -r "[.]mp3$"'
```
> [!NOTE]
> The environment variable is *only* used when **no** command-line arguments are present. **Any** command-line argument will disable the use of the environment variable.
Make sure to correctly use quotes and/or escape special characters when using this method. (See [regular expression notes](./README.md#technical-notes-on-regular-expressions) above.)
In Docker Compose, the previous command would need an extra `$` to match the end-of-line:
<details>
<summary>Example Docker Compose</summary>
For example, the following lines in your `compose.yml` file would convert any .mp3 to Opus, and would need an extra `$` to escape the end-of-line regular expression match:
```yaml
environment:
- FLAC2MP3_ARGS=-a "-vn -c:a libopus -b:a 192k" -e .opus -r '[.]mp3$$'
```
</details>
<details>
<summary>Example Docker Run Command</summary>
In a `docker run` command, it would be:
```shell
-e FLAC2MP3_ARGS='-a "-vn -c:a libopus -b:a 192k" -e .opus -r "[.]mp3$"'
```
</details>
<details>
<summary>Synology Screenshot</summary>
*Example Synology Configuration*
![flac2mp3](.assets/lidarr-synology-2.png "Synology container settings")
>**NOTE:** The environment variable settings are *only* used when **no** command-line arguments are present. **Any** command-line argument will disable the use of the environment variable.
</details>
## Triggers
The only events/notification triggers that are supported are **On Release Import** and **On Upgrade**
The only events/notification triggers that are supported are **On Release Import** and **On Upgrade**. The script will log an error if executed by any other trigger.
## Batch Mode
Batch mode allows the script to be executed independently of Lidarr. It converts the file specified on the command-line and ignores any environment variables that are normally expected to be set by the music management program.
Using this function, you can easily process all of your audio files in any subdirectory at once. See the [Batch Example](./README.md#batch-example) below.
Using this function, you can easily process all of your audio files in any subdirectory at once. See the [Batch Example](#batch-example) below.
### Script Execution Differences in Batch Mode
Because the script is not called from within Lidarr, expect the following behavior while in Batch Mode:
* *The filename must be specified on the command-line*<br/>(The `-f` option places the script in Batch Mode)
* *The filename must be specified on the command-line*<br/>The `-f` option places the script in Batch Mode.
* *Lidarr APIs are not called and its database is not updated.*<br/>This may require a manual import of converted music files or an artist rescan.
* *Original audio files are deleted.*<br/>The Recycle Bin function is not available. (Modifiable using the `-k` option.)
* *Original audio files are deleted.* (Modifiable using the `-k` option.)<br/>The Recycle Bin function is not available.
### Batch Example
<details>
<summary>Batch Mode Example</summary>
To convert all .FLAC files in the `/music` directory to Apple Lossless Audio Codec (ALAC), enter the following at the Linux command-line:
```shell
find /music/ -type f -name "*.flac" | while read file; do /usr/local/bin/flac2mp3.sh -f "$file" -a "-c:a alac" -e m4a; done
```
</details>
## Metadata Corrections
**This feature is not meant for general purpose use.** It is only documented here for completeness.
<details>
<summary>Metadata Tag Details</summary>
List of supported tags and metadata corrections that are applied:
|Tag|Original|Correction
|---|---|---
|title|Parenthesis for live\|remix, etc. "()"|Square brackets "\[]"
|disc|1|1/1
|genre|/Pop/|"Pop"
| |/Indie/|"Alternative & Indie"
| |/Industrial/|"Industrial Rock"
| |/Electronic/|"Electronica & Dance"
| |/Punk\|Alternative/|"Alternative & Punk"
| |/Rock/|"Rock"
Tag|Original|Correction
---|---|---
`title`|Parenthesis for live\|remix, etc. "()"|Square brackets "\[]"
`disc`|1|1/1
`genre`|/Pop/|"Pop"
&nbsp;|/Indie/|"Alternative & Indie"
&nbsp;|/Industrial/|"Industrial Rock"
&nbsp;|/Electronic/|"Electronica & Dance"
&nbsp;|/Punk\|Alternative/|"Alternative & Punk"
&nbsp;|/Rock/|"Rock"
</details>
## Logs
By default, a log file is created for the script activity called:
@ -260,11 +332,13 @@ By default, a log file is created for the script activity called:
This log can be downloaded from Lidarr under *System* > *Log Files*. The log filename can be modified with the `--log` command-line option.
Log rotation is performed, with 5 log files of 1MB each kept, matching Lidarr's log retention.
>![danger] **NOTE:** If debug logging is enabled with a level above 1, the log file can grow very large very quickly and is much more likely to be rotated. *Do not leave high-level debug logging enabled permanently.*
> [!CAUTION]
> If debug logging is enabled with a level above 1, the log file can grow very large very quickly and is much more likely to be rotated. *Do not leave high-level debug logging enabled permanently.*
# Uninstall
To completely remove the mod:
1. Delete the custom script from Lidarr's *Settings* > *Connect* screen that you created in the [Installation](./README.md#installation) section above.
1. Delete the custom script from Lidarr's *Settings* > *Connect* screen that you created in the [Installation](#installation) section above.
2. Stop and delete the Lidarr container.
3. Exclude the **DOCKER_MODS** environment variable from your `compose.yaml` file or the `docker run` command when re-creating the Lidarr container.
@ -281,4 +355,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"
[note]: .assets/notes.png "Note"

View File

@ -6,24 +6,27 @@
# Resultant MP3s are fully tagged and retain same permissions as original file
# Dependencies:
# ffmpeg
# ffprobe
# awk
# curl
# jq
# stat
# nice
# basename
# dirname
# printenv
# chmod
# tr
# sed
# From ffmpeg package:
# ffmpeg
# ffprobe
# From jq package:
# jq
# Generally always available:
# awk
# curl
# stat
# nice
# basename
# dirname
# printenv
# chmod
# tr
# sed
# Exit codes:
# 0 - success; or test
# 1 - no audio tracks detected
# 2 - ffmpeg not found
# 2 - ffmpeg, ffprobe, or jq not found
# 3 - invalid command line arguments
# 4 - log file is not writable
# 5 - specified audio file not found
@ -52,8 +55,12 @@ export flac2mp3_debug=0
export flac2mp3_keep=0
export flac2mp3_type=$(printenv | sed -n 's/_eventtype *=.*$//p')
# Usage function
# Usage functions
function usage {
usage="Try '$flac2mp3_script --help' for more information."
echo "$usage" >&2
}
function long_usage {
usage="
$flac2mp3_script Version: $flac2mp3_ver
Audio conversion script designed for use with Lidarr
@ -103,7 +110,7 @@ Options:
[default: \.flac$]
-t, --tags <taglist> Comma separated list of metadata tags to apply
automated corrections to.
Supports: disc, genre
Supports: title, disc, genre
-l, --log <log_file> log filename
[default: /config/log/flac2mp3.txt]
-d, --debug [<level>] Enable debug logging
@ -137,7 +144,7 @@ Examples:
directory and do not delete the original
audio file(s)
"
echo "$usage" >&2
echo "$usage"
}
# Check for environment variable arguments
@ -164,7 +171,7 @@ while (( "$#" )); do
fi
;;
--help ) # Display usage
usage
long_usage
exit 0
;;
--version ) # Display version
@ -331,7 +338,8 @@ elif [[ "${flac2mp3_type,,}" = "lidarr" ]]; then
[ -z "$flac2mp3_tracks" ] && flac2mp3_tracks="$lidarr_trackfile_path"
else
# Called in an unexpected way
echo -e "Error|Unknown or missing '*_eventtype' environment variable: ${flac2mp3_type}\nNot called from Lidarr.\nTry using Batch Mode option: -f <file>"
echo -e "Error|Unknown or missing '*_eventtype' environment variable: ${flac2mp3_type}\nNot called from Lidarr. Try using Batch Mode option: -f <file>" >&2
usage
exit 7
fi
@ -531,11 +539,12 @@ function import_tracks {
}
# Get track media info from ffprobe
function ffprobe {
[ $flac2mp3_debug -ge 2 ] && echo "Debug|Executing: /usr/bin/ffprobe -hide_banner -loglevel $flac2mp3_ffmpeg_log -print_format json=compact=1 -show_format -show_entries \"format=tags : format_tags=title,disc,genre\" -i \"$1\"" | log
local flac2mp3_ffcommand="/usr/bin/ffprobe -hide_banner -loglevel $flac2mp3_ffmpeg_log -print_format json=compact=1 -show_format -show_entries \"format=tags : format_tags=title,disc,genre\" -i \"$1\""
[ $flac2mp3_debug -ge 1 ] && echo "Debug|Executing: $flac2mp3_ffcommand" | log
unset flac2mp3_ffprobe_json
flac2mp3_ffprobe_json=$(/usr/bin/ffprobe -hide_banner -loglevel $flac2mp3_ffmpeg_log -print_format json=compact=1 -show_format -show_entries "format=tags : format_tags=title,disc,genre" -i "$1")
flac2mp3_ffprobe_json=$(eval $flac2mp3_ffcommand 2>&1)
flac2mp3_return=$?; [ $flac2mp3_return -ne 0 ] && {
flac2mp3_message="Error|[$flac2mp3_return] ffprobe error when inspecting track: \"$1\""
flac2mp3_message=$(echo -e "[$flac2mp3_return] ffprobe error when inspecting file: \"$1\"\nffprobe returned: $flac2mp3_ffprobe_json" | awk '{print "Error|"$0}')
echo "$flac2mp3_message" | log
echo "$flac2mp3_message" >&2
}
@ -567,7 +576,7 @@ fi
# Check that the log file exists
if [ ! -f "$flac2mp3_log" ]; then
echo "Info|Creating a new log file: $flac2mp3_log"
touch "$flac2mp3_log" 2>&1
touch "$flac2mp3_log"
fi
# Check that the log file is writable
@ -578,24 +587,20 @@ if [ ! -w "$flac2mp3_log" ]; then
fi
# Check for required binaries
if [ ! -f "/usr/bin/ffmpeg" ]; then
flac2mp3_message="Error|/usr/bin/ffmpeg is required by this script"
echo "$flac2mp3_message" | log
echo "$flac2mp3_message" >&2
end_script 2
fi
if [ ! -f "/usr/bin/ffprobe" ]; then
flac2mp3_message="Error|/usr/bin/ffprobe is required by this script"
echo "$flac2mp3_message" | log
echo "$flac2mp3_message" >&2
end_script 2
fi
for flac2mp3_file in "/usr/bin/ffmpeg" "/usr/bin/ffprobe" "/usr/bin/jq"; do
if [ ! -f "$flac2mp3_file" ]; then
flac2mp3_message="Error|$flac2mp3_file is required by this script"
echo "$flac2mp3_message" | log
echo "$flac2mp3_message" >&2
end_script 2
fi
done
# Log Debug state
if [ $flac2mp3_debug -ge 1 ]; then
flac2mp3_message="Debug|Enabling debug logging level ${flac2mp3_debug}. Starting ${lidarr_eventtype^} run."
echo "$flac2mp3_message" | log
echo "$flac2mp3_message"
echo "$flac2mp3_message" >&2
fi
# Log FLAC2MP3_ARGS usage
@ -653,7 +658,7 @@ elif [ -f "$flac2mp3_config" ]; then
# Check for localhost
[[ $flac2mp3_bindaddress = "*" ]] && flac2mp3_bindaddress=localhost
# Strip leading and trailing forward slashes from URL base
# Strip leading and trailing forward slashes from URL base (see issue #44)
flac2mp3_urlbase="$(echo "$flac2mp3_urlbase" | sed -re 's/^\/+//; s/\/+$//')"
# Build URL to Lidarr API
@ -699,7 +704,7 @@ fi
# If specified, check if destination folder exists and create if necessary
if [ "$flac2mp3_output" -a ! -d "$flac2mp3_output" ]; then
[ $flac2mp3_debug -ge 1 ] && echo "Debug|Destination directory does not exist. Creating: $flac2mp3_output" | log
mkdir -p "$flac2mp3_output" >&2
mkdir -p "$flac2mp3_output"
flac2mp3_return=$?; [ $flac2mp3_return -ne 0 ] && {
flac2mp3_message="Error|[$flac2mp3_return] mkdir returned an error. Unable to create output directory."
echo "$flac2mp3_message" | log
@ -829,7 +834,7 @@ for flac2mp3_track in $flac2mp3_tracks; do
esac
done
# shellcheck disable=SC2090
[ $flac2mp3_debug -ge 1 ] && echo "Debug|New metadata: echo ${flac2mp3_ffmpeg_metadata//-metadata /}" | log
[ $flac2mp3_debug -ge 1 ] && echo "Debug|New metadata: ${flac2mp3_ffmpeg_metadata//-metadata /}" | log
else
echo "Warn|ffprobe did not return any data when querying track: \"$flac2mp3_track\"" | log
flac2mp3_exitstatus=12
@ -838,10 +843,11 @@ for flac2mp3_track in $flac2mp3_tracks; do
# Convert the track
echo "Info|Writing: $flac2mp3_newTrack" | log
[ $flac2mp3_debug -ge 1 ] && echo "Debug|Executing: nice /usr/bin/ffmpeg -loglevel $flac2mp3_ffmpeg_log -nostdin -i \"$flac2mp3_track\" $flac2mp3_ffmpeg_opts $flac2mp3_ffmpeg_metadata\"$flac2mp3_newTrack\"" | log
eval nice /usr/bin/ffmpeg -loglevel $flac2mp3_ffmpeg_log -nostdin -i \"$flac2mp3_track\" $flac2mp3_ffmpeg_opts $flac2mp3_ffmpeg_metadata\"$flac2mp3_newTrack\" 2>&1 | log
flac2mp3_ffcommand="nice /usr/bin/ffmpeg -loglevel $flac2mp3_ffmpeg_log -nostdin -i \"$flac2mp3_track\" $flac2mp3_ffmpeg_opts $flac2mp3_ffmpeg_metadata\"$flac2mp3_newTrack\""
[ $flac2mp3_debug -ge 1 ] && echo "Debug|Executing: $flac2mp3_ffcommand" | log
flac2mp3_result=$(eval $flac2mp3_ffcommand 2>&1)
flac2mp3_return=$?; [ $flac2mp3_return -ne 0 ] && {
flac2mp3_message="Error|[$flac2mp3_return] ffmpeg error when converting track: \"$flac2mp3_track\" to \"$flac2mp3_newTrack\""
flac2mp3_message=$(echo -e "[$flac2mp3_return] ffmpeg error when converting track: \"$flac2mp3_track\" to \"$flac2mp3_newTrack\"\nffmpeg returned: $flac2mp3_result" | awk '{print "Error|"$0}')
echo "$flac2mp3_message" | log
echo "$flac2mp3_message" >&2
flac2mp3_exitstatus=13
@ -861,9 +867,9 @@ for flac2mp3_track in $flac2mp3_tracks; do
if [ "$(id -u)" -eq 0 ]; then
# Set owner
[ $flac2mp3_debug -ge 1 ] && echo "Debug|Changing owner of file \"$flac2mp3_newTrack\"" | log
chown --reference="$flac2mp3_track" "$flac2mp3_newTrack" >&2
flac2mp3_result=$(chown --reference="$flac2mp3_track" "$flac2mp3_newTrack")
flac2mp3_return=$?; [ $flac2mp3_return -ne 0 ] && {
flac2mp3_message="Error|[$flac2mp3_return] Error when changing owner of track: \"$flac2mp3_newTrack\""
flac2mp3_message=$(echo -e "[$flac2mp3_return] Error when changing owner of file: \"$flac2mp3_newTrack\"\nchown returned: $flac2mp3_result" | awk '{print "Error|"$0}')
echo "$flac2mp3_message" | log
echo "$flac2mp3_message" >&2
flac2mp3_exitstatus=15
@ -873,9 +879,9 @@ for flac2mp3_track in $flac2mp3_tracks; do
[ $flac2mp3_debug -ge 1 ] && echo "Debug|Unable to change owner of track when running as user '$(id -un)'" | log
fi
# Set permissions
chmod --reference="$flac2mp3_track" "$flac2mp3_newTrack" >&2
flac2mp3_result=$(chmod --reference="$flac2mp3_track" "$flac2mp3_newTrack")
flac2mp3_return=$?; [ $flac2mp3_return -ne 0 ] && {
flac2mp3_message="Error|[$flac2mp3_return] Error when changing permissions of track: \"$flac2mp3_newTrack\""
flac2mp3_message=$(echo -e "[$flac2mp3_return] Error when changing permissions of file: \"$flac2mp3_newTrack\"\nchmod returned: $flac2mp3_result" | awk '{print "Error|"$0}')
echo "$flac2mp3_message" | log
echo "$flac2mp3_message" >&2
flac2mp3_exitstatus=15
@ -887,12 +893,12 @@ for flac2mp3_track in $flac2mp3_tracks; do
continue
fi
# Skip the rest of the loop if in batch mode, just delete the track
# Skip the rest of the loop if in batch mode, just delete the file
if [ "$flac2mp3_type" = "batch" ]; then
[ $flac2mp3_debug -ge 1 ] && echo "Debug|Deleting: \"$flac2mp3_track\"" | log
rm "$flac2mp3_track" >&2
flac2mp3_result=$(rm "$flac2mp3_track")
flac2mp3_return=$?; [ $flac2mp3_return -ne 0 ] && {
flac2mp3_message="Error|[$flac2mp3_return] Error when deleting track: \"$flac2mp3_track\""
flac2mp3_message=$(echo -e "[$flac2mp3_return] Error when deleting file: \"$flac2mp3_track\"\nrm returned: $flac2mp3_result" | awk '{print "Error|"$0}')
echo "$flac2mp3_message" | log
echo "$flac2mp3_message" >&2
flac2mp3_exitstatus=16
@ -937,14 +943,14 @@ elif [ -n "$flac2mp3_api_url" ]; then
# Build JSON data for all tracks
# NOTE: Tracks with empty track IDs will not appear in the resulting JSON and will therefore not be imported into Lidarr
[ $flac2mp3_debug -ge 1 ] && echo "Debug|Building JSON data to import" | log
export flac2mp3_json=$(echo $flac2mp3_result | jq -jcrM "
export flac2mp3_json=$(echo $flac2mp3_result | jq -jcM "
map(
select(.path | inside(\"$flac2mp3_import_list\")) |
{path, \"artistId\":$lidarr_artist_id, \"albumId\":$lidarr_album_id, albumReleaseId,\"trackIds\":[.tracks[].id], quality, \"disableReleaseSwitching\":false}
)
")
# Import new files into Lidarr
# Import new files into Lidarr (see issue #39)
import_tracks
flac2mp3_return=$?; [ $flac2mp3_return -ne 0 ] && {
flac2mp3_message="Error|[$flac2mp3_return] Lidarr error when importing the new tracks!"
@ -954,7 +960,7 @@ elif [ -n "$flac2mp3_api_url" ]; then
}
flac2mp3_jobid="$(echo $flac2mp3_result | jq -crM .id)"
# Check status of job
# Check status of job (see issue #39)
check_job
flac2mp3_return=$?; [ $flac2mp3_return -ne 0 ] && {
case $flac2mp3_return in