.\" mp3rgain - Lossless MP3 volume adjustment .\" Copyright (c) 2025 M-Igashi .\" Licensed under MIT License .TH MP3RGAIN 1 "October 22, 2026" "mp3rgain 3.12.0" "User Commands" .SH NAME mp3rgain \- lossless MP3/AAC volume adjustment (modern mp3gain replacement) .SH SYNOPSIS .B mp3rgain [\fIOPTIONS\fR] \fIFILE\fR... .SH DESCRIPTION .B mp3rgain adjusts MP3 and AAC volume without re-encoding by modifying the .I global_gain field in each frame. This preserves audio quality while achieving permanent volume changes. .PP Changes are lossless and reversible. For MP3, undo data is stored in APEv2 tags. For AAC in an MP4/M4A container, it is stored in iTunes freeform metadata tags. For a raw ADTS .I .aac stream, which has no container to hold them, it is stored in an ID3v2 tag. .PP .B mp3rgain is a replacement for the classic .BR mp3gain (1) tool, written in Rust. It accepts mp3gain's options and adds lossless AAC gain adjustment, BS.1770 loudness analysis and recursive directory processing. See .B COMPATIBILITY for the few behaviours that differ. .PP Without an action option, .B mp3rgain analyzes each file and prints the recommended track and album gain without modifying anything .RB ( \-e leaves out the album gain). When several actions are given, only one runs, in this order of precedence: .BR \-x , .BR "\-s d" , .BR "\-s c" , .BR \-u , .B \-a (unless .BR \-e ), .B \-r (and .BR "\-a \-e" ), .BR \-l , .BR \-g . For example, .B \-r\ \-g\ 2 applies track gain and ignores .BR \-g . .PP Each file is processed once, however many times it is named: listed twice, through a symbolic link alongside its target, or found under overlapping .B \-R directories. The first name given is the one reported, and a note on standard error says how many were skipped. .SH OPTIONS .SS "Gain Options" .TP .BI \-g " i" Apply gain of .I i steps without analysis. Each step equals 1.5 dB (fixed by the MP3 specification). Positive values increase volume, negative values decrease it. Existing .B REPLAYGAIN_* values and .B MP3GAIN_ALBUM_MINMAX are shifted by the gain actually applied, as mp3gain does, so they still describe the audio afterwards (not with .BR "\-s s" , which writes no tags). .TP .BI \-d " n" Modify the suggested gain by .I n dB. With .B \-r or .B \-a it shifts the target relative to the reference level (89 dB, or the .B \-\-rg2 / .B \-\-r128 target), rounded to whole 1.5 dB steps; with .B \-\-tags\-only it is applied exactly. Without an action it shifts the recommendation the analysis prints. .TP .BI \-l " channel gain" Apply gain to one channel only. .I channel is 0 for left or 1 for right. .I gain is the number of steps. MP3 only; on AAC files this is an error. It is also an error on mono and joint-stereo MP3s, as in mp3gain: a joint-stereo frame may code mid and side rather than left and right, so the change would reach both channels. The file is left unchanged. Existing .B REPLAYGAIN_* tags are left unchanged, as in mp3gain, so they no longer describe the audio afterwards. .TP .BI \-m " i" Modify the suggested gain by integer .I i steps, in addition to any .BR \-d . Used with .B \-r or .BR \-a . .SS "ReplayGain Analysis" .TP .B \-r Analyze and apply track gain. Each file is normalized individually to the reference level, 89 dB with the default ReplayGain 1.0 analysis. .TP .B \-a Analyze and apply album gain. All files given on the command line are treated as one album and normalized together, which is the same rule as .BR mp3gain (1)'s .BR \-a . Use .B \-\-album\-by or .B \-\-album\-depth to split one invocation into several albums instead. .TP .BI \-\-album\-by " how" With .BR \-a , choose what counts as one album instead of pooling every file into one, so a whole library can be album\-tagged in a single run. Cannot be combined with .BR \-e . .RS .TP .B dir One album per parent directory. .B \-\-per\-directory is an alias for this. Works on untagged libraries, but a release whose discs live in subdirectories is scanned as one album per disc. .TP .B tag One album per release, keyed on MUSICBRAINZ_ALBUMID when present and otherwise on ALBUMARTIST (or ARTIST) plus ALBUM. Handles discs in subdirectories and a tree of mixed depth in one pass. Files carrying no ALBUM tag fall back to directory grouping and are reported rather than pooled together. When two releases share one artist and album string, a repeated track number inside the group is reported with the directories involved. .RE .IP An album that fails analysis is reported and the run continues with the next one. In JSON output the results appear in an .B albums array, each entry carrying either .B directory or .BR album_artist / album_title depending on how the group was formed. Albums are analyzed concurrently, so the worker threads stay busy across album boundaries. The JSON report and the exit status stay deterministically ordered, exactly as under .BR "\-j 1" . Text and TSV output is written as each album finishes, so its group order follows completion rather than the order the albums were given in. Each album's block is still emitted whole and its rows stay in file order. Use .B \-j 1 when the output has to be byte-reproducible between runs. .IP In .B dir mode, sibling directories that share an ALBUM tag and look like discs of one release are reported, since that grouping writes a separate album gain per disc. Two different editions of the same album are left alone: they are already grouped correctly by directory. .TP .BI \-\-album\-depth " n" With .B \-a and .BR \-R , one album per directory .I n levels below each directory argument. This is the grouping unit for a library that is not tagged: it needs no shell expansion, has no command-line length limit, and behaves the same on Windows, where .B */* is not expanded into arguments at all. .B \-\-album\-depth 0 makes each directory argument one album, .B 1 groups one level below it, and .B 2 suits an .I Artist/Album tree. A file shallower than .I n levels groups at the deepest directory it has. Descending deeper than .I n is what keeps a multi\-disc release together: at .B \-\-album\-depth 2 over .IR Artist/Album , .I disc1 and .I disc2 both group at .IR Artist/Album . When directory arguments overlap, the deepest one owns the file. Mutually exclusive with .B \-\-album\-by and .BR \-\-per\-directory . .TP .B \-\-rg2 Measure loudness with the ReplayGain 2.0 algorithm (ITU-R BS.1770 integrated loudness, gated) against the \-18 LUFS reference instead of the default ReplayGain 1.0 algorithm. The reference corresponds to the same perceived level as the classic 89 dB SPL reference; only the measurement is different. The gain applied to the audio is still rounded to whole 1.5 dB steps. Combines with .BR \-r , .BR \-a , .BR \-e , .BR \-d , .BR \-m , .BR \-k , .B \-\-true\-peak and .BR \-\-tags\-only . Mutually exclusive with .BR \-\-r128 . .TP .B \-\-r128 Like .BR \-\-rg2 , but normalizes to the EBU R128 broadcast target of \-23 LUFS. Mutually exclusive with .BR \-\-rg2 . .TP .B \-\-true\-peak Measure the true peak (ITU-R BS.1770-4 Annex 2) for the \fBREPLAYGAIN_*_PEAK\fR tags instead of the sample peak. The decoded signal is oversampled 4x below 88.2 kHz and 2x at or above it, so inter-sample peaks are caught and the value can exceed 1.0. Requires .B \-\-rg2 or .BR \-\-r128 ; the default ReplayGain 1.0 analysis keeps mp3gain's sample peak. .TP .B \-\-tags\-only Write the analysis to \fBREPLAYGAIN_*\fR tags and leave the audio untouched, the way .BR loudgain (1) and .BR rsgain (1) work. The frame-level .I global_gain fields are not modified, so a listener can still turn ReplayGain off in their player. The tag holds the full gain rather than a residual, and no \fBMP3GAIN_UNDO\fR, \fBMP3GAIN_MINMAX\fR or \fBMP3GAIN_ALBUM_MINMAX\fR is written since there is no gain change to undo or describe; an existing undo tag is kept. Requires .BR \-r , .B \-a or .BR \-e , and cannot be combined with .BR \-g , .BR \-l , .BR \-u , .BR \-w , .B \-x or .BR "\-s c" / "\-s d" / "\-s s" . .B \-d and .B \-m shift the written value instead of the applied gain, and apply exactly (no 1.5 dB step rounding, since a tag holds a float). .B \-k caps the written value at the file's headroom so a player applying the tag cannot clip. .TP .B \-e Skip album analysis even when processing multiple files. On its own it only analyzes, as .BR mp3gain (1) does: each file's track gain is printed and the album gain is not. Like the plain analysis, it writes nothing to the file. With .B \-a it analyzes and applies track gain like .BR \-r , and with .B \-\-tags\-only it writes track tags like .BR "\-r \-\-tags\-only" . .RB ( mp3gain (1) applies nothing with .BR "\-a \-e" .) .TP .B \-\-skip\-errors Continue album analysis .RB ( \-a ) past files that fail to read instead of aborting. Failed files are reported and excluded from the album gain calculation. .TP .BI \-i " n" Which audio track of a multi-track MP4 file to analyze (default: 0). Gain, undo and ReplayGain tags always apply to the first audio track, which is the one players apply the file's ReplayGain tags to, so a value other than 0 is accepted only for analysis: combining it with .BR \-r , .BR \-a , .BR \-g , .BR \-l , .BR \-u , .B \-s d or .B \-\-tags\-only is an error, with or without .BR \-n . The .I global_gain range in the analysis output, and .BR \-x , always describe the first audio track. .SS "Undo and Tag Operations" .TP .B \-u Undo gain changes using the stored undo tag (APEv2 or ID3v2 for MP3, an iTunes freeform atom for AAC in MP4, ID3v2 for raw ADTS). The .B REPLAYGAIN_* values are removed as well, since they described the adjusted audio. Every audio frame is restored exactly, except frames whose .I global_gain was clamped at 0 or 255. The file as a whole is byte-identical to the original only when no ID3v2 tag was written: with the default MP3 layout, an existing ID3v2 tag stays rewritten as ID3v2.4 and a file that had none keeps an empty ID3v2 header. A file that was never adjusted is an error, and so is an undo tag with different left and right values on a mono or joint-stereo MP3: mp3gain writes one when it refuses .B \-l on such a file, without changing the audio. .TP .BI \-s " mode" Stored tag handling mode: .RS .TP .B c Check/show stored tag information. .TP .B d Delete stored tag information, the undo tag included. Combined with \fB\-u\fR, the frame-level gain is undone first, then the remaining tags are deleted; deleting alone would destroy the undo information. .TP .B s Skip stored tags: write no undo or ReplayGain tags, in any container, so the change cannot be undone with \fB\-u\fR. .TP .B r Force recalculation, ignoring stored tags (the default; kept for mp3gain compatibility). Overrides \fB\-s R\fR. .TP .B R Reuse stored ReplayGain tags with \fB\-r\fR/\fB\-a\fR instead of re-analyzing, rescanning only files whose tags are missing. This is mp3gain's default behavior. In album mode, one file with missing album tags, or album tags that disagree, rescans the whole album. Ignored with \fB\-s r\fR, \fB\-d\fR/\fB\-m\fR, \fB\-\-rg2\fR/\fB\-\-r128\fR, or when a stored tag came from a BS.1770 analysis. .TP .B i Put every MP3 tag in ID3v2 TXXX frames, \fBMP3GAIN_UNDO\fR and \fBMP3GAIN_MINMAX\fR included (\fBMP3GAIN_ALBUM_MINMAX\fR exists only in APEv2, so it is not written). Without \fBi\fR or \fBa\fR, MP3 tags are split since 3.2.0: \fBREPLAYGAIN_*\fR in ID3v2, \fBMP3GAIN_*\fR in APEv2. .TP .B a Put every MP3 tag in APEv2, which is mp3gain's layout and was the default before 3.2.0. .RE .IP .B i and .B a affect MP3 only: AAC in MP4 always uses freeform atoms and raw ADTS always uses ID3v2. If both are given, the last one wins. .SS "Analysis Options" .TP .B \-x Only find and display the maximum amplitude of the file. Does not apply any changes. .SS "Behavior Options" .TP .B \-p Preserve the original file modification time after writing. .TP .B \-c Do not print clipping warnings. .TP .B \-k Prevent clipping by automatically limiting gain. With .B \-r or .B \-a the limit comes from the decoded peak and is rounded down to whole steps, so a file that already clips can end up attenuated. With .B \-g it only stops any frame's .I global_gain from exceeding 255; the decoded peak is not measured. Without .BR \-k , a gain that would clip is applied anyway and a warning is printed; .B mp3rgain never prompts. .TP .B \-w Wrap gain values around instead of clamping when they exceed the valid range (0\-255). Disables the clipping check. .TP .B \-t Use a temporary file for writing. Accepted for compatibility and has no effect: since 2.9.6 every write goes to a temporary file that replaces the original. .TP .B \-f Assume MPEG 2 Layer III. Accepted for compatibility but has no effect. .TP .B \-q Quiet mode. Suppress most output. .TP .B \-R Process directories recursively, collecting files with the extensions .IR .mp3 , .IR .m4a , .I .aac and .I .mp4 (case-insensitive). Symbolic links to directories are not followed. Without .BR \-R , a directory argument is not expanded. .TP \fB\-j\fR \fIn\fR, \fB\-\-threads\fR \fIn\fR Number of worker threads for the per-file work: analysis, gain application, undo and tag writes. Default is the number of available CPUs; 0 also means auto, and 1 forces the legacy serial path. See also the .B MP3RGAIN_THREADS environment variable. .IP With more than one thread, the .B text and .B tsv output is written as each unit finishes, so a program reading the output can start parsing before the run ends. Rows therefore appear in completion order rather than in the order the files were given. A unit is never split or interleaved with another, and .B json is unaffected: its records stay in input order at every thread count. .TP .BR \-n ", " \-\-dry\-run Dry-run mode. Show what would be done without making changes. .TP .BI \-o " format" Output format: .BR text " (default)," .BR json ", or" .BR tsv " (tab-separated values; " db " is an alias)." .B \-o not followed by one of these words selects .BR tsv , as in mp3gain. .B tsv prints the mp3gain-compatible header and one row per file, with the .B File column holding the path as given on the command line. The rows are also emitted while applying gain .RB ( \-r ", " \-a ", " \-g ", " \-l ). The .B Max Amplitude column uses mp3gain's 16-bit sample scale (peak multiplied by 32768) in the default ReplayGain 1.0 mode, and the ReplayGain float peak (the value written to REPLAYGAIN_*_PEAK) under .BR \-\-rg2 " and " \-\-r128 . Without an action, .B json reports frame statistics only (frame count, MPEG version, channel mode and the .I global_gain range), not the loudness analysis. .TP .BR \-v ", " \-\-version Show version information and exit. (\fB\-v\fR is not verbose mode.) .TP .BR \-h ", " \-\-help Show help message and exit. .SH EXAMPLES .TP .B mp3rgain song.mp3 Show the recommended gain, peak and .I global_gain range without modifying the file. .TP .B mp3rgain \-g 2 song.mp3 Apply +2 steps (+3.0 dB). .TP .B mp3rgain \-g \-3 song.mp3 Apply \-3 steps (\-4.5 dB). .TP .B mp3rgain \-r song.mp3 Analyze and apply track gain (ReplayGain). .TP .B mp3rgain \-a *.mp3 Analyze and apply album gain, treating all the files as one album. .TP .B mp3rgain \-a \-\-album\-by=tag \-R /music Album gain for a whole library, one album per release. .TP .B mp3rgain \-a \-\-tags\-only *.mp3 Write album and track ReplayGain tags without modifying the audio. .TP .B mp3rgain \-u song.mp3 Undo previous gain changes. .TP .B mp3rgain \-k \-g 5 song.mp3 Apply gain, limited so that no frame's global_gain exceeds 255. .TP .B mp3rgain \-n \-r *.mp3 Preview track gain changes without modifying files. .TP .B mp3rgain \-r \-n \-o json song.mp3 Report the track gain that would be applied, in JSON. .TP .B mp3rgain \-R /path/to/music Analyze all audio files in a directory tree. .SH GAIN VALUES Each gain step corresponds to 1.5 dB (20\(mulog10(2)/4 = 1.5051 dB), which is fixed by the MP3 specification. The .I global_gain field has a valid range of 0\-255, limiting the effective gain adjustment. .PP Common gain values: .RS .nf Steps dB 1 +1.5 2 +3.0 3 +4.5 \-1 \-1.5 \-2 \-3.0 .fi .RE .SH REPLAYGAIN By default .B mp3rgain implements the original ReplayGain 1.0 algorithm: .IP \(bu 2 Equal-loudness filter (Yule-Walker + Butterworth high-pass) .IP \(bu 2 RMS calculation in 50ms windows .IP \(bu 2 95th percentile statistical analysis .IP \(bu 2 89 dB reference level .PP This gives the same values as the original mp3gain. Tools based on ITU-R BS.1770 (rsgain, loudgain, foobar2000's scanner, ffmpeg's loudnorm filter) measure loudness differently, so their values differ unless .B \-\-rg2 or .B \-\-r128 is used. .PP On AAC, .B mp3rgain may report a higher peak than .BR rsgain (1) or foobar2000 while the gain values agree. Lossy AAC decodes to samples that can exceed full scale, and decoders disagree about whether to clamp them: .B mp3rgain reports the decoded signal as it is, which is the headroom a float playback path actually needs. See the peak section of .I COMPARISON.md for the measurements. .SH SUPPORTED FORMATS .TP .B MP3 MPEG-1, MPEG-2 and MPEG-2.5 Layer III: reading, analyzing, and modifying gain. .TP .B AAC/M4A/MP4 AAC-LC: lossless bitstream gain adjustment and undo, including the audio track of a video MP4. .TP .B AAC (raw ADTS, .aac) Lossless bitstream gain adjustment and undo, as for AAC in MP4. Undo and .B REPLAYGAIN_* go into an ID3v2 tag, since a raw stream has no container for them. .TP .B HE-AAC, ALAC, DRM-protected M4P Recognized but not adjustable. Reported as skipped, without affecting the exit status of a batch. HE-AAC (v1 and v2, in MP4 or raw ADTS) is skipped because the gain would reach the AAC core and not the SBR high band, and the decoder used for analysis does not reconstruct that band either. Undo still works on HE-AAC files adjusted by earlier versions. .TP .B FLAC, Ogg, Opus, WAV Not supported. Named on the command line they fail with an error; .B \-R ignores them. .SH ENVIRONMENT .TP .B MP3RGAIN_THREADS Number of worker threads, equivalent to .BR \-j . The explicit .B \-j flag takes precedence. A value of 0 means auto (number of available CPUs). .SH FILES For MP3 the .B REPLAYGAIN_* values are stored in ID3v2 .B TXXX frames and the .B MP3GAIN_* values in an APEv2 tag, which is where each family's readers look; see .BR \-s " a and " \-s " i to put both in one container." For AAC in MP4 both families go into iTunes freeform atoms (with lowercase names, such as .BR mp3rgain_undo ), and for raw ADTS into ID3v2. The values written are: .TP .B REPLAYGAIN_TRACK_GAIN Track gain in dB. After gain is applied, the residual relative to the adjusted audio. .TP .B REPLAYGAIN_TRACK_PEAK Track peak, linear, where 1.0 is full scale. Can exceed 1.0. .TP .B REPLAYGAIN_ALBUM_GAIN Album gain in dB (with .BR \-a ). .TP .B REPLAYGAIN_ALBUM_PEAK Album peak, linear (with .BR \-a ). .TP .B REPLAYGAIN_ALGORITHM .B ITU\-R BS.1770 under .B \-\-rg2 and .BR \-\-r128 ; not written by the default ReplayGain 1.0 analysis. .TP .B MP3GAIN_UNDO Information required to restore original gain values. .TP .B MP3GAIN_MINMAX Minimum and maximum .I global_gain values of the file. .TP .B MP3GAIN_ALBUM_MINMAX Minimum and maximum .I global_gain values across the album (MP3 with .BR \-a , APEv2 only). .PP Every write goes to a temporary file .RI .mp3rgain_temp_ pid _ n . ext in the same directory, which is synced to disk and then renamed over the original, so a failure leaves the original untouched. The original's permissions are copied to the new file. A symbolic link is written through: the temporary file is created next to the link's target and replaces it, so the link stays a link. Hard links are not carried over, as with any rename: the name given gets the new file and every other hard link keeps the old audio. Two hard-link names listed together are two files, and each ends up with its own adjusted copy. .PP A read-only file is refused with an error and left as it was whenever a command would change it, as in mp3gain, even when running as root. A command with nothing to write succeeds on it. .SH EXIT STATUS .TP .B 0 Success. Files skipped as unsupported (HE-AAC, ALAC, M4P) do not change this. An unknown short option, such as .BR \-Z , only prints a warning, as in mp3gain. .TP .B 1 Error occurred (invalid arguments, unknown long option, file not found, etc.). A batch in which any single file failed exits 1, including the read-only commands (plain analysis, .BR \-s " c and " \-x ), so a scripted scan cannot mistake an unreadable file for a clean run. .SH SECURITY .B mp3rgain is written in Rust, and its source contains no .B unsafe blocks. It does not contain the C code behind the published mp3gain and aacgain CVEs (mpglib, mpglibDBL, .IR apetag.c , faad2, mp4v2), so those bugs do not carry over. .SH COMPATIBILITY .B mp3rgain is designed as a drop-in replacement for the original .BR mp3gain (1) and works with existing scripts and integrations (e.g., the beets replaygain plugin). The audio frames it writes for .B \-g are byte-identical to mp3gain's, including the CRCs of CRC-protected frames. Differences to be aware of: .IP \(bu 2 Stored analysis is re-computed by default; use .B \-s\ R for mp3gain's reuse behaviour. .IP \(bu 2 .B "\-a \-e" applies track gain, where mp3gain applies nothing. .IP \(bu 2 A gain that may clip is applied with a warning instead of an interactive prompt. .IP \(bu 2 The plain analysis never writes tags. .IP \(bu 2 .B \-u removes existing .B REPLAYGAIN_* tags, where mp3gain adjusts them. .IP \(bu 2 Since 3.2.0, MP3 ReplayGain tags go to ID3v2 instead of APEv2; .B \-s\ a restores mp3gain's layout. .IP \(bu 2 A file listed more than once is processed once. mp3gain processes it once per listing: .B \-g\ 2 on a file listed twice moves the audio by 4 steps and records 2 in the undo tag. .IP \(bu 2 A symbolic link is written through to its target; mp3gain replaces the link with a modified copy. .SH SEE ALSO .BR mp3gain (1), .BR rsgain (1), .BR loudgain (1), .BR vorbisgain (1) .PP Project homepage: https://github.com/M-Igashi/mp3rgain .SH AUTHORS .B mp3rgain is written by M-Igashi. .PP Original mp3gain by Glen Sawyer. .SH LICENSE MIT License. See LICENSE file in the source distribution.