Syncs ReplayGain/loudness tags from Plex or Jellyfin into your music files.
5.4K
Gainbridge keeps ReplayGain/loudness tags on your music library in sync with what Plex or Jellyfin already knows, so every player that respects ReplayGain plays your library at a consistent volume.
Point it at one or more Plex or Jellyfin servers, and it periodically reads the loudness data those servers already compute and writes standard ReplayGain tags into the actual audio files - no separate loudness scan needed.
Plex and Jellyfin both analyze audio loudness for their own volume-leveling features, but that data lives in their databases, not in your files. If you ever move your library, play it through something other than Plex/Jellyfin, or just want tags that work everywhere, that analysis is locked away. Gainbridge pulls it out and writes it where it belongs: directly into the file's own ReplayGain tags (ID3 TXXX, MP4 freeform atoms, Vorbis comments).




docker compose watch
Then open:
From there, add a Plex or Jellyfin source with its server URL and an API token, optionally scope it to one library and set a sync schedule, and run a sync.
For production, pull the published image, which bundles the backend and frontend into a single container:
docker pull j3ko/gainbridge:latest
Use :edge instead of :latest to track the tip of main between releases.
docker run -d \
--name gainbridge \
-p 9210:9210 \
-v ./data:/app/data \
-v /path/to/music:/music \
-v /etc/localtime:/etc/localtime:ro \
-v /etc/timezone:/etc/timezone:ro \
j3ko/gainbridge:latest
The data/ volume mount keeps the SQLite database and log file across container restarts and upgrades. The /etc/localtime and /etc/timezone mounts match the container's timezone to the host's, so timestamps shown in the UI are in local time instead of UTC, and source schedules (schedule_cron) run at the wall-clock time you'd expect rather than UTC. See Configurationโ below for other environment variables.
Configuration lives in the top-level .env file. At minimum, review:
SQLITE_DB_FILE / LOG_FILE - paths to the SQLite database and log file, by default under the top-level data/ folder, which is bind-mounted into the backend container so it persists across restarts and redeploys.BACKEND_CORS_ORIGINS - required if the frontend is served from a different origin than the backend.TIMEZONE - IANA zone name (e.g. America/Toronto) that source schedules (schedule_cron) are evaluated in. Auto-detected from the TZ env var or the container's system timezone (see the /etc/localtime//etc/timezone mounts above) if unset - only set this to override that detection.Gainbridge is licensed under the terms of the MIT license.
Content type
Image
Digest
sha256:e4a9be1c7โฆ
Size
474.9 MB
Last updated
9 days ago
docker pull j3ko/gainbridge