Closed HavermansStef closed 1 year ago
Just wanted to leave the keyword replaygain in here.
https://www.bobulous.org.uk/misc/Replay-Gain-in-Linux.html
You would usually write replaygain information to the file, then utilize it on playback. Different formats have different ways to store this data though.
Another approach is re-formatting your media beforehand. I found this to be very useful: https://github.com/slhck/ffmpeg-normalize
Mp3 is also often normalized by rewriting the files. I won't do this as the music collection already tries to take care to be a bit perfect copy of the cd (flac format). (I'm one of those people...) so would love to see a metadata based solution here.
But point taken thst you could normalize media today for use with jellyfin :)
I just hacked this feature into my Jellyfin installation. It's a dirty workaround :) https://blog.project-insanity.org/2019/04/10/hacking-replay-gain-audio-normalization-into-jellyfin/
I enable audio transcoding with ffmpeg and enable the replay gain audio normalization with an additional parameter: "-af volume=replaygain=track". I hardocded this into the Jellyfin source. But it works pretty good!
That should be pretty easy to hide behind a checkmark! :tada:
The question - does this only apply with transcoding though? I imagine a lot of people have that as direct play. Otherwise, spectacular work @onny!
I’ll have to look at getting things figured out for other formats later. I think FLAC does ReplayGain too?
@anthonylavado you are correct, and it's a pretty large problem to solve. I think a lot of settings are dependent on the playback being a transcode. Another example of this is that all video streams transcode audio to MP3 last I checked.
I think the correct way here is to rely on file metadata or generate metadata from the file about its replaygain values. These can be served to the client to perform corrections on the client side. Usually the most important information is the rms values for the track and for the whole album
Why in my eyes this is important: The End Of The Loudness War?
Replaygain 2 uses the newer loudness measurement algorithms:
RG2 uses BS.1770-3 for loudness measurement.
See ReplayGain 2.0 specification Jump to: navigation, search In the end measuring is one thing and then using the tagged values is another, so I just wanted to mention RG2 here because it was mentioned above.
Sources (audio files) should in my opinion stay untouched and only be tagged for example with r128gain and then normalised when played back.
There was a study (Recommendation for loudness normalization by music streaming services) for a big and popular streaming service made by Eelco Grimm in which he suggested to use album gain. The study is linked at Music Loudness Alliance. But the choice of album or track gain can be left up to the user (settings).
Anything can be done here?
Thanks @onny for the blog post and idea in the meantime. A few things have changed. Based on the pull as of Nov 24th, here what I did:
in Jellyfin.Api/Helpers/AudioHelper.cs, comment out direct play and always transcode in the code without UI : ) around line 167
+ //if (streamingRequest.Static)
+ //{
+ // var contentType = state.GetMimeType("." + state.OutputContainer, false) ?? state.GetMimeType(state.MediaPath);
+
+ // if (state.MediaSource.IsInfiniteStream)
+ // await new ProgressiveFileCopier(state.MediaPath, null, _transcodingJobHelper, CancellationToken.None)
+ // {
+ // AllowEndOfFile = false
+ // }.WriteToAsync(_httpContextAccessor.HttpContext.Response.Body, CancellationToken.None)
+ // .ConfigureAwait(false);
+
+ // return new FileStreamResult(_httpContextAccessor.HttpContext.Response.Body, contentType);
+ // }
+
+ // return FileStreamResponseHelpers.GetStaticFileResult(
+ // state.MediaPath,
+ // contentType,
+ // isHeadRequest,
+ // _httpContextAccessor.HttpContext);
+ //}
in MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs, add ffmpeg args for replaygain; round line 3521
- "{0} {1}{7}{8} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1{6} -y \"{5}\"",
+ "{0} {1}{7}{8} -threads {2}{3} {4} -af volume=replaygain=track -id3v2_version 3 -write_id3v1 1{6} -y \"{5}\"",
Doing the correction in the playback client is preferable to transcoding. When using a playback device that supports doing Replaygain (like Kodi, for example), then conceptually it seems quite simple as we would simply need to pass the metadata to the client. When I've experimented with this, Kodi doesn't apply any gain, so presumably it's not getting any metadata.
Is it as simple as I think? Is there a whitelist for tags that get passed over DLNA?
ffmpeg has already built in modules:
loudnorm: loudness normalization according to EBU R128. You can set an integrated loudness target, a loudness range target, or maximum true peak. This is recommended for publishing audio and video and it is used by broadcasters all over the world. single pass for livestreams
looks great
ffmpeg -i file_example_MP3_5MG.mp3 -filter:a loudnorm=i=-24:tp=-2:lra=7,volume=5dB file_example_MP3_5MG_proc0.mp3
coming from: https://github.com/jellyfin/jellyfin-androidtv/issues/1434
We could add a user config for it. What about transcoding only the audio?
Would be great for night-movie-mode (eliminating the need of buying AV with this feature)
There are two different types of normalisation being discussed here and it's important to be clear about them:
These could both be useful in their own right. 1 is very much the only option if audio fidelity is the main concern. Anyone even remotely an audiophile would never consider 2. However, 2 might be a good option in noisier environments when you want your playlist to sound more like a radio station.
Yeah, I'd like to toggle between applying per-album gain and per-track gain, for when I either want to listen to a whole album in sequence, or as a shuffled playlist. I know ReplayGain has both track gain and album gain (as seen in Foobar2000), so as long as the tags are there, and we have a method to apply decibel gain, it shouldn't be too difficult to switch between track and album gain.
I would really like to see this implemented, preferably without having to change my music files or source code.
I noticed that my client, Symphonium, has a beta option for "local renderer replay gain", which makes me think passing the metadata to the client could be a good option. It also seems like the simplest approach.
I also would also like to see an option for adding the normalization flags to ffmpeg (when transcoding), since I think that would be a decent way to add support without the user having to alter the source code, and hopefully wouldn't require much more work.
It would probably be easiest to start with passing through the tags from files that have them, and then figure out afterwards how to deal with files that jellyfin has to normalize itself. For example, my music library's files are normalized per-album with r128gain (replaygain tool), and so clients that support it just use those tags. Using those would already be much better than nothing.
Agreed, my library is also tagged with ReplayGain metadata so having Jellyfin use that would be a great first step (that I daresay would satisfy most users but I don't have anything to back up that statement).
I hate to be the guy that has suggestions but no PR's... but it seems to me that this has been doable with seemingly minor code changes since 2019 (i.e., three years): https://github.com/jellyfin/jellyfin/issues/537#issuecomment-481465290 and it hasn't been brought into the codebase at all.
May I suggest instead of thinking up all the possible uses that everyone might want, to start small -- add one switch to toggle the feature as shown earlier in this chain? Having some proof of ability will probably make a bunch of people happy and kick off more work in that direction towards the eventual meet-everyone's-needs goal. Release early, release often :)
For real though, though I am far from a C# expert (or even amateur, I treat it like the plague), if someone could point me in the direction of adding a switch to the user settings and using it, I'd be happy to combine that with the patch above and open a PR for it. Would love to have some loudness normalization!
After lots of trial and error and many hours, I have created an implementation of audio normalization. I would be very appreciative if people would take a look and perhaps download the branch and try it on your own system. I haven't encountered bugs but different systems should show these.
https://github.com/jellyfin/jellyfin/pull/9222
There is a front end linked on the pull page which enables the normalization behind the scenes on the webpage and adds a checkbox to enable/disable this in settings/playback/audio normalization. The front end is required for audio normalization to work.
Thanks! :)
@TelepathicWalrus how can i use this? It seems like it is merged into main?
@Y0ngg4n, the easiest way ATM is to use the docker unstable build, that is built off of the current master branch I believe. Then the options should be there 👍 at least until the next version of jellyfin is officially released
Would be nice to have, but not easy to implement. Low priority.