Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion source/audio_transcoder/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Transcode Audio Files
# Transcode Audio

Plugin for [Unmanic](https://github.com/Unmanic)

---
Expand All @@ -7,3 +8,43 @@ Plugin for [Unmanic](https://github.com/Unmanic)

- [Description](description.md)
- [Changelog](changelog.md)

---

### Plugin Coordination

`Transcode Audio` can be configured to work alongside other audio-manipulation plugins in two ways:

- **Minimum input channel count**: only process streams at or above a configured source channel-count threshold. This is useful when another plugin creates derived stereo streams and you only want this plugin to continue standardizing surround streams.
- **Unmanic stream ignore markers**: skip streams that have been explicitly marked by another plugin as derived or otherwise not intended for further audio-transcoder processing.

#### Recommended Marker Convention

Where the target container preserves stream metadata reliably, other plugins should write a stream `comment` tag containing semicolon-separated key/value pairs, for example:

```text
unmanic.managed=true;unmanic.source_plugin=add_extra_stereo_audio;unmanic.ignore_for=audio_transcoder
```

`Transcode Audio` currently understands these ignore markers:

- `unmanic.ignore=true`
- `unmanic_ignore=1`
- `unmanic.ignore_for=audio_transcoder`
- `unmanic.ignore_for=all`
- `unmanic_ignore_for=audio_transcoder`
- `unmanic_ignore_for=all`

The plugin reads these markers from:

- explicit stream tags with those names, when the container preserves them
- `comment`
- `description`

#### Notes For Plugin Authors

- This convention is intended for **audio streams inside media containers**, not as a universal guarantee for raw audio-only formats.
- `MKV` is the safest target for preserving these markers.
- `WebM` may preserve them depending on the muxing path and player support.
- `MP4` is more restrictive, so plugins should treat these markers as best-effort there.
- If you generate derivative stereo or commentary/helper streams, prefer marking only the derived stream rather than suppressing the whole file.
14 changes: 14 additions & 0 deletions source/audio_transcoder/changelog.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@

**<span style="color:#56adda">0.0.5</span>**
- Add smart audio filters for maximum channel count and loudness normalization, and warn when a selected codec such as MP3 is a poor fit for multichannel output
- Add new encoder libraries for FLAC, Opus, AC3, and EAC3
- Make the maximum channel-count selector codec-aware so unsupported channel layouts are clamped to the selected codec's supported limit
- Refresh the plugin description and metadata to document the current settings surface and codec channel support warnings
- Add a minimum input channel-count processing threshold so derived stereo streams can be skipped while surround streams continue to be processed
- Add support for generic Unmanic stream ignore markers and document the coordination convention for other plugin authors in the README

**<span style="color:#56adda">0.0.4</span>**
- Rebrand the plugin as Transcode Audio and add support for transcoding audio streams in video/media files while copying non-audio streams and preserving the source container

**<span style="color:#56adda">0.0.3</span>**
- Add smart output target to Basic mode so matching audio codecs can be re-encoded when they are significantly above the recommended bitrate window

**<span style="color:#56adda">0.0.2</span>**
- Update runner signatures to accept keyword helper args for Unmanic compatibility

Expand Down
112 changes: 82 additions & 30 deletions source/audio_transcoder/description.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@

---

Audio Transcoder transcodes audio streams in both audio-only files and video/media containers.

For audio-only files, the output extension is determined by the selected encoder.
For video/media files, the plugin preserves the original container and copies all non-audio streams unchanged while transcoding the audio stream or streams.

##### Links:

- [Support](https://unmanic.app/discord)
Expand All @@ -9,53 +13,101 @@

---

##### Documentation:
##### Configuration Modes:

- **Basic**: choose the target codec and encoder, optionally enable smart output target, and optionally enable the plugin's smart audio filters.
- **Standard**: exposes encoder-specific bitrate and rate-control settings, plus optional custom audio filters.
- **Advanced**: write the FFmpeg audio options directly.

---

##### Smart Features:

For information on the available encoder settings:
- MP3 encoders
- [FFmpeg - MP3](https://trac.ffmpeg.org/wiki/Encode/MP3)
- AAC
- [FFmpeg - AAC](https://trac.ffmpeg.org/wiki/Encode/AAC)
- **Smart output target** estimates a suitable destination bitrate from the source stream and the selected codec.
- **Re-encode matching codecs above target** is optional and only applies when smart output target is enabled in Basic mode.
- **Only process streams with at least this many channels** can be used to skip lower-channel-count streams such as derived stereo tracks while still processing surround streams in the same file.
- **Enable plugin's smart audio filters** exposes:
- **Set maximum channel count** to cap the output stream to `7.1`, `5.1`, `2.0`, `1.0`, or keep it the same as the source.
- **Normalise audio volume levels** to apply FFmpeg loudness normalization.
- The plugin also supports ignoring streams marked with generic Unmanic metadata markers when the container preserves stream metadata reliably.

---

##### Additional Information:
##### Codec Support:

:::warning
Object-based formats such as Dolby Atmos are not preserved by this plugin when transcoding with FFmpeg's open, channel-based encoders.
In practice, the object metadata and immersive rendering information are discarded and the output becomes a conventional channel-based stream such as `7.1`, `5.1`, or `2.0`.
This is largely a limitation of the available FFmpeg/open-source encoder stack and Dolby licensing, not just a plugin choice.
:::

| Codec | Practical Max | Good For | Avoid When | Notes |
| ------------------------- | --------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| AAC | `7.1` technically, `5.1` or below recommended | Stereo music, simple media files, broad client compatibility | `7.1` home-theater movie audio | Very widely supported, especially for stereo. `5.1` can work, but `7.1` AAC is a poor fit for movies because channel mapping and playback behavior can be unreliable. |
| FLAC | `7.1` | Lossless music, archival use, controlled playback setups | Maximum device compatibility | Best lossless option in this plugin. Great quality, but support across devices and containers is less consistent than AAC or AC3. |
| Opus | `7.1` | Efficient compression, modern clients, MKV/WebM libraries | Older devices and broad compatibility targets | Very efficient and supports high channel counts, but playback support is less consistent than AAC or AC3 in many consumer setups. |
| AC3 (Dolby Digital) | `5.1` | Movie libraries, AVR compatibility, simple surround playback | `7.1` source preservation | Good fit for home-theater use. FFmpeg's AC3 encoder is limited to `5.1`, so anything above that will be downmixed. |
| EAC3 (Dolby Digital Plus) | `5.1` in this FFmpeg-based plugin | Movie libraries, AVR compatibility, efficient surround playback | `7.1` source preservation | Similar to AC3 here, but a little more efficient. In this FFmpeg/open-encoder workflow it is effectively capped at `5.1`. |
| MP3 | `2.0` | Stereo music, simple audio files, legacy client support | Surround movie audio | Treat MP3 as stereo-only here. It is a good fit for basic stereo playback, but multichannel sources will be downmixed. |

:::note
The output file extension will always be determined by the selected audio encoder.
For example, selecting an MP3 encoder will always produce a *XXXX.mp3* file, and selecting an AAC encoder will always produce a *XXXX.m4a* file.
Codec channel limits are enforced by the plugin because they reflect FFmpeg encoder support and practical playback behavior, not arbitrary plugin rules.
When you choose a codec that supports fewer channels than the source, the output will be downmixed to the selected or supported maximum.
:::

---

##### Container Support Breakdown for Codecs:

| Audio Codec | MP4 (`.mp4`) | MKV (`.mkv`) | WebM (`.webm`) | MOV (`.mov`) | AVI (`.avi`) | TS (`.ts`) |
| ----------- | ------------ | ------------ | -------------- | ------------ | ------------ | ---------- |
| AAC | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes | ✅ Yes |
| AC-3 / EAC3 | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | ⚠️ Partial | ✅ Yes |
| MP3 | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes | ✅ Yes |
| Opus | ⚠️ Hacky | ✅ Yes | ✅ Yes | ❌ No | ❌ No | ❌ No |
| FLAC | ⚠️ Hacky | ✅ Yes | ✅ Yes | ❌ No | ❌ No | ❌ No |

:::note
**Advanced**
This table is a practical compatibility guide for common FFmpeg/container combinations, not a guarantee that every player or device will behave the same way.
Entries marked **Hacky** generally rely on combinations that may mux but are not broadly interoperable.
Entries marked **Partial** may work in some workflows but are less predictable across playback environments.
:::

---

If you set the Config mode to *"Advanced"*, the input text provides the ability to add FFmpeg commandline args in three different places:
1. **MAIN OPTIONS** - After the default generic options.
([Main Options Docs](https://ffmpeg.org/ffmpeg.html#Main-options))
1. **ADVANCED OPTIONS** - After the input file has been specified.
([Advanced Options Docs](https://ffmpeg.org/ffmpeg.html#Advanced-options))
1. **AUDIO OPTIONS** - After the audio is mapped. Here you can specify the audio encoder, its params and any additional audio options.
([Audio Options Docs](https://ffmpeg.org/ffmpeg.html#Audio-Options))
([Advanced Audio Options Docs](https://ffmpeg.org/ffmpeg.html#Advanced-Audio-options))
##### Encoder Notes:

```
- **AAC** is a good general-purpose target for music files and simpler media workflows, but it is not the best choice for high-channel-count home-theater movie audio.
- **FLAC** is the lossless option.
- **Opus** is efficient and supports multichannel output, but some playback environments are less compatible than AAC or AC3.
- **AC3 / EAC3** are useful for home-theater-oriented compatibility, but FFmpeg's available encoders here are capped below `7.1`, so the plugin enforces that same limit.
- **MP3** is best treated as a stereo-oriented target for music and simple audio files.

---

##### Advanced Mode:

If you set the config mode to **Advanced**, the input text provides the ability to add FFmpeg command-line args in three different places:

1. **Main Options**: inserted after the default generic options.
1. **Advanced Options**: inserted after the input file has been specified.
1. **Audio Options**: inserted after the audio stream is mapped. Here you specify the encoder and any additional audio options.

```bash
ffmpeg \
-hide_banner \
-loglevel info \
<CUSTOM MAIN OPTIONS HERE> \
-i /path/to/input/audio.wav \
-i /path/to/input/media.file \
<CUSTOM ADVANCED OPTIONS HERE> \
-map 0:0 -c:a:0 <CUSTOM AUDIO OPTIONS HERE> \
-y /path/to/output/audio.mp3
-map 0:a:0 -c:a:0 <CUSTOM AUDIO OPTIONS HERE> \
-y /path/to/output/media.file
```
:::

:::note
**Force transcoding**
---

Enabling the *"Force transcoding ..."* option will force a transcode of the audio stream even if it matches the selected audio codec.
##### Force Transcoding:

A file will only be forced to be transcoded once. It will then be flagged in a local `.unmanic` file to prevent it being added to the pending tasks list in a loop.
Enabling **Force transcoding even if the file is already using the desired audio codec** will re-encode matching-codec files one time.

However, a file previously flagged to be ignored by this will still be transcoded to apply any matching smart filters such as scaling, stripping data streams, etc.
:::
The plugin writes a marker so that force-transcoded files are not added back into the pending task list in a loop on subsequent scans.
6 changes: 3 additions & 3 deletions source/audio_transcoder/info.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
"compatibility": [
2
],
"description": "Transcode the audio streams of a audio file",
"description": "Transcode audio streams in audio and video media files",
"icon": "https://raw.githubusercontent.com/Unmanic/plugin.audio_transcoder/master/icon.png",
"id": "audio_transcoder",
"name": "Transcode Audio Files",
"name": "Transcode Audio",
"priorities": {
"on_library_management_file_test": 10,
"on_worker_process": 1
},
"tags": "audio,ffmpeg",
"version": "0.0.2"
"version": "0.0.5"
}
Loading
Loading