A containerized service that watches a source folder and automatically transcodes audio files to multiple formats simultaneously.
Perfect for maintaining a music library in multiple formats -- lossless for archival, lossy for portable devices -- without lifting a finger. Drop a FLAC into your source folder and get ALAC, MP3, AAC, and Opus copies instantly.
.lrc lyrics with Whisper speech-to-text fallback1. Create a config.yaml file:
source:
path: /music/flac
outputs:
- name: alac
codec: alac
path: /music/alac
- name: mp3-256
codec: mp3
bitrate: 256k
path: /music/mp3
- name: aac-256
codec: aac
bitrate: 256k
path: /music/aac
2. Create a docker-compose.yml:
services:
audio-transcoder:
image: drumsergio/audio-transcoder:0.5.1
container_name: audio_transcoder
environment:
- TZ=Europe/Madrid
- CONFIG_FILE=/app/config.yaml
volumes:
- ./config.yaml:/app/config.yaml:ro
- /path/to/flac:/music/flac:ro
- /path/to/alac:/music/alac
- /path/to/mp3:/music/mp3
- /path/to/aac:/music/aac
restart: unless-stopped
3. Start the service:
docker compose up -d
docker run -d \
--name audio_transcoder \
-e TZ=Europe/Madrid \
-e CONFIG_FILE=/app/config.yaml \
-v ./config.yaml:/app/config.yaml:ro \
-v /path/to/flac:/music/flac:ro \
-v /path/to/mp3:/music/mp3 \
--restart unless-stopped \
drumsergio/audio-transcoder:0.5.1
Configuration is provided via a YAML file. Set the CONFIG_FILE environment variable to its path inside the container.
# Source folder containing original audio files
source:
path: /music/flac
# Output destinations -- define as many as you need
outputs:
# Lossless ALAC for Apple devices
- name: alac
codec: alac
path: /music/alac
include_artwork: true
# High-quality MP3 for broad compatibility
- name: mp3-320
codec: mp3
bitrate: 320k
path: /music/mp3-320
include_artwork: true
# Balanced MP3 for portable devices
- name: mp3-192
codec: mp3
bitrate: 192k
path: /music/mp3-192
include_artwork: true
# AAC for modern devices
- name: aac-256
codec: aac
bitrate: 256k
path: /music/aac
include_artwork: true
# Opus for streaming (best quality-to-size ratio)
- name: opus-128
codec: opus
bitrate: 128k
path: /music/opus
# Optional settings
settings:
# Delete all outputs and re-encode on startup
force_reencode: false
# Maximum time to wait for a file to become stable (seconds)
stability_timeout: 60
# Minimum time a file must be unchanged before processing (seconds)
min_stable_seconds: 1.0
# Auto-fetch synced .lrc lyrics (default: true)
fetch_lyrics: true
# Use Whisper local transcription as fallback when no lyrics found online (default: true)
whisper_fallback: true
# Whisper model size: tiny, base, small, medium, large (default: base)
whisper_model: base
| Codec | Extension | Bitrate | Artwork | Description |
|---|---|---|---|---|
alac | .m4a | N/A | Yes | Lossless, Apple compatible |
aac | .m4a | 64k--320k | Yes | Lossy, excellent quality |
mp3 | .mp3 | 64k--320k | Yes | Lossy, universal support |
opus | .opus | 32k--256k | No | Lossy, best quality/size |
flac | .flac | N/A | Yes | Lossless, open format |
wav | .wav | N/A | No | Lossless, uncompressed |
You can alternatively provide configuration as a JSON string via the CONFIG_JSON environment variable:
environment:
- CONFIG_JSON={"source":{"path":"/music/flac"},"outputs":[{"name":"mp3","codec":"mp3","bitrate":"256k","path":"/music/mp3"}]}
.lrc lyrics from online databases; falls back to Whisper transcription when no lyrics are found.Source folder hierarchy is automatically mirrored in all outputs. Both flat and nested structures work out of the box -- no configuration needed.
Source: Output (MP3):
/music/flac/ /music/mp3/
├── Artist A/ ├── Artist A/
│ ├── Album 1/ │ ├── Album 1/
│ │ ├── 01 - Track.flac │ │ ├── 01 - Track.mp3
│ │ └── 02 - Track.flac │ │ └── 02 - Track.mp3
│ └── Album 2/ │ └── Album 2/
│ └── 01 - Song.flac │ └── 01 - Song.mp3
└── Artist B/ └── Artist B/
└── Live Album/ └── Live Album/
└── 01 - Intro.flac └── 01 - Intro.mp3
When source files or directories are deleted, the corresponding outputs and empty directories are cleaned up automatically.
The service includes multiple guards to prevent data loss:
A built-in verification tool checks that all outputs are in sync with the source:
# Basic sync check
docker exec audio_transcoder python /app/tools/verify_sync.py --config /app/config.yaml
# Thorough check including duration comparison
docker exec audio_transcoder python /app/tools/verify_sync.py --config /app/config.yaml --check-duration -v
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
# Run tests with coverage
pytest
docker build -t audio-transcoder:dev .
| Project | Description |
|---|---|
| slskd-transform | Bulk upgrade your music library from lossy to lossless via Soulseek |
| telegram-slskd-local-bot | Automated music discovery and download via Telegram |
| jellyfin-encoder | Automatic 720p HEVC/AV1 transcoding for Jellyfin |
This project is licensed under the GNU General Public License v3.0 -- see the LICENSE file for details.
Contributions are welcome. Please open an issue to discuss significant changes before submitting a pull request.
git checkout -b feat/amazing-feature)pytest)git commit -m 'feat: add amazing feature')git push origin feat/amazing-feature)Content type
Image
Digest
sha256:3dac43ed3…
Size
2.9 GB
Last updated
5 months ago
docker pull drumsergio/audio-transcoder