flan 6334f3f4da Apply the community-rating floor to rated titles as well
The audience tag admitted any title whose official rating sat at or below the
ceiling, with no quality condition at all. The community-rating floor was only
consulted when a title had no usable rating. On a real library that let 21
poorly reviewed but mildly rated titles through - Norbit, Cats, Super Mario
Bros., Rocky V, Cool as Ice among them - none of which belong in a library whose
entire purpose is to be smaller than the one it was carved out of. A ceiling
answers whether a title is suitable; it says nothing about whether it is worth
offering.

MinCommunityRating now applies to rated titles, alongside the existing
MinCommunityRatingWhenUnrated for titles with no rating to judge. The two are
separate settings because an unrated title carries more uncertainty and may
warrant a higher bar. A rated title with no community rating at all now fails,
which is deliberate: with neither a score to check nor a reputation to weigh,
there is nothing to decide on.

Verified against the live library: a full pass over 2778 titles settles at 561
tagged, and the 21 are not re-added.
2026-09-19 23:35:13 +00:00

Jellyfin Audience

A Jellyfin plugin that repairs ratings the server cannot parse, and maintains an audience tag so a user account can be narrowed to a manageable subset of a large library.

It runs in-process as a scheduled task. It needs no API key, no credential file and no external service.

Why it exists

Ratings Jellyfin cannot parse are a hole in parental controls

Jellyfin resolves an OfficialRating string to a numeric score. When it cannot, the item takes the same path as an unrated one, and unrated items are visible to everyone by default unless an account explicitly blocks unrated content.

That is not a theoretical problem. A real library scanned for this contained Singapore board ratings (M18, NC16, R21) on adult titles. Jellyfin could not parse any of them, so no age ceiling would have hidden them. It cuts the other way too: TP (Spain) and L (Brazil) both mean "all ages", and titles carrying them were being hidden from children as though unrated.

This plugin remaps those strings to their documented US equivalents and locks the result.

Allowed Tags fails closed

Narrowing an account with Allowed Tags is the right mechanism, but it is a whitelist: anything without the tag is invisible. A library that keeps growing would leave that account frozen at whatever was tagged on the day it was set up. So the tagging pass has to run on a schedule, not once.

What it does not do

It does not guess a rating from genre, synopsis, or anything else about the content. A wrong guess fails open, and failing open is the one outcome parental controls exist to prevent. Ratings it cannot map are logged as warnings and left untouched, for a person to decide.

Configuration

Dashboard, then Plugins, then Audience.

Setting Default Meaning
Enabled on Master switch for the scheduled task
RepairRatings on Remap unparseable board ratings
ApplyTags on Maintain the audience tag
TagName grandma Tag applied to matching titles
MaxRatingScore 14 Rating ceiling for tagging. Inclusive
MinCommunityRatingWhenUnrated 6.0 Community-rating floor for titles with no usable rating
RespectManualUntag on Honour the ledger, so manual untagging sticks

The US rating ladder is 0 G and TV-G, 7 TV-Y7, 10 PG and TV-PG, 13 PG-13, 14 TV-14, 17 R and TV-MA. Note that Jellyfin 10.11 rescored TV-PG from 13 to 10, so a ceiling carried over from an older install will not behave the way it used to.

MinCommunityRatingWhenUnrated is a weak gate on obscure titles, where a perfect score can rest on a handful of votes. It is a starting filter, not a verdict.

Curating the result

The rule is a first pass, not an opinion. To remove something, untag it in the Jellyfin UI. The ledger records that the item was tagged once, so the next run sees a deliberate removal and leaves it alone.

Turning off RespectManualUntag makes every run re-apply the rule, which undoes curation. It exists for the case where you want to reset and start again.

Building

Needs the .NET 9 SDK. On a machine where it is a user-local install rather than a system package, it will not be on the PATH of a non-interactive shell:

export DOTNET_ROOT="$HOME/.dotnet"
export PATH="$DOTNET_ROOT:$PATH"
dotnet build Jellyfin.Plugin.Audience/Jellyfin.Plugin.Audience.csproj -c Release

The output is Jellyfin.Plugin.Audience/bin/Release/net9.0/Jellyfin.Plugin.Audience.dll.

Installing

Copy the DLL and meta.json into a folder named Audience_1.0.0.0 inside Jellyfin's plugins directory, then restart the server. The plugin appears under Dashboard, Plugins, and its task appears under Scheduled Tasks as "Repair ratings and apply audience tags".

targetAbi is 10.11.0.0. That is deliberate and is not a mistake on a 12.x server: a plugin built against Jellyfin.Controller 10.11.11 loads and runs on Jellyfin 12.0. Do not raise it without confirming the newer package exists and the result still loads.

Releasing

To publish through a Jellyfin plugin catalog, zip the DLL and meta.json, host the zip, and add a repository manifest entry whose sourceUrl points at it. The sourceUrl must end in .zip, and the checksum field must be the MD5 of the actual published archive. No manifest is committed here, because a manifest carrying a placeholder checksum or a URL with nothing behind it produces a broken install for anyone who adds it.

Licence

GPL-3.0.

S
Description
Jellyfin plugin: repairs unparseable parental ratings and maintains an audience tag for reduced libraries
Readme
49 KiB
Languages
C# 70.1%
HTML 29.9%