Picking HDR Formats for the Screen I Actually Own: DV Boost, No HDR10+, Recyclarr as Code
My TV decodes HDR10+ and my library scores zero for it. How I pick HDR formats from the real playback chain, keep the policy in one Recyclarr file, and test it with open demo clips.
HomeLab, Media stack. Updated . 5 min read.
My TV decodes HDR10+ at 3000 nits, and my library gives HDR10+ exactly zero points. That isn't a mistake. The box in front of the TV never sends HDR10+, so paying for it in the quality scores would be paying for a feature nobody in the chain can deliver.
TL;DR: score HDR formats for the whole playback chain, not the panel. Mine is Jellyfin, then an Nvidia Shield, then a soundbar, then the TV, and the Shield outputs Dolby Vision and HDR10 only. So both 2160p profiles carry TRaSH's DV Boost (+1000) and no HDR10+ Boost. The whole policy is one Recyclarr file, and I test the chain with a demo library of open clips that I had to fix before they showed HDR at all.
The chain decides, not the TV
Here's the path every file takes:
Jellyfin -> Nvidia Shield -> Samsung Q800F soundbar -> TCL 85Q7CThe TCL arrived on 2026-09-04. On paper it does everything: Dolby Vision IQ, HDR10+, 3000 nits. The Shield in front of it does Dolby Vision and HDR10. An HDR10+ file still plays through it, but the dynamic metadata never reaches the panel. The TV sees plain HDR10.
The obvious answer is "use the TV's own Jellyfin app, then". I looked at it and kept the Shield, because it does three things I care about more than HDR10+:
- bit-perfect TrueHD and DTS-HD passthrough to the soundbar
- gigabit Ethernet, which remux-sized files need
- AI upscaling of the 1080p part of the library
I'm the only viewer, playback stays on the LAN over Ethernet, and I want Direct Play. Recent Shield playback doesn't start FFmpeg at all. Intel QSV transcoding stays configured on the NUC only as a compatibility fallback, with OpenCL HDR-to-SDR tone mapping for the odd client that needs it.
So the rule writes itself: DV Boost on both 2160p profiles, HDR10+ Boost off. If the TV app ever becomes the player, HDR10+ Boost goes in. Not before.
The policy lives in one file
Recyclarr syncs TRaSH guide quality definitions, profiles, and custom format scores into my movie and TV library managers. It has no web UI. It's one recyclarr.yml, no includes, no extra files. If a score matters, it's in that file, and the managers' UIs are just a view of it.
Four profiles, two per library:
| Library | Profile | DV Boost |
|---|---|---|
| Movies | Remux + WEB 2160p | +1000 |
| Movies | HD Bluray + WEB | - |
| TV | WEB-2160p | +1000 |
| TV | WEB-1080p | - |
All four reset unmatched scores, so a custom format I removed from the file doesn't linger in the app with an old score. The custom formats on top of the TRaSH defaults are the actual policy:
- Golden Rule UHD: x265 is allowed at 4K only with HDR or DV.
- Golden Rule HD: x265 is blocked in HD entirely.
- DV without HDR fallback: penalized. A Dolby Vision file with no HDR10 base layer has nothing to fall back on if any link in the chain can't do DV.
- SDR, non-streaming sources only: penalized for Bluray, Remux, and HDTV sources. Streaming 4K is HDR whatever the file name says, so SDR scoring on streaming sources would only punish bad naming.
The TV 1080p profile has one override in recyclarr.yml: Bluray-1080p sits inside the WEB 1080p group at equal rank. Equal rank matters. It means an older show can use either source, and neither counts as an upgrade over the other, so nothing already in the library gets replaced.
Before the 2026-09-05 change, the file got a dated copy: recyclarr.yml.bak-20260905. That copy is the whole rollback for the HDR policy.
The profile-move trap
The movie side had an older profile, UHD Bluray + WEB. I replaced it with Remux + WEB 2160p, moved all 31 movies and 8 collections across, and only then deleted the old profile. That order is the boring part.
The interesting part came on the TV side. Two shows had no 4K version for most of their run, so I moved them from WEB-2160p down to WEB-1080p. Sounds harmless. It isn't:
A 2160p file is "not in profile" on WEB-1080p.
The library manager doesn't read that as "better than needed". It reads it as "wrong", and anything that fits the profile counts as an upgrade. So a 1080p file becomes an upgrade over a 4K file, and the 4K file gets replaced. It started within a minute of the move. I caught it and cancelled it before the swap, so no 4K file was lost.
The rule I wrote down: before moving a series down a profile, unmonitor every completed season. A score system that only knows "in profile" and "not in profile" has no concept of "above profile".
A demo library to test the chain
Policy on paper is cheap. I wanted clips I could play through the exact same path and look at. So there's a Demos library in Jellyfin, type Home Videos, with trickplay and chapter images off. Home Videos lists files by name, and the Shield still plays them through the same Direct Play and passthrough path as everything else.
It holds Dolby audio test clips, a set of panel tests, and the Netflix Open Content clips: Meridian at 4K59 with its 5.1 mix, and Chimera at 4K24 and 4K59, all CC BY 4.0.
The Netflix clips are the trap. Played as they come, a TV shows them washed out, as SDR. The bucket mp4 files are 8-bit H.264 with PQ pixels, no colour tags, and no audio. The pixels are HDR, but nothing in the file says so, so every player treats them as SDR and the PQ curve reads as grey mush. A frame extract confirmed PQ with P3 primaries.
The fix was a re-encode on my PC: NVENC HEVC 10-bit at cq 18, P3 converted into the BT.2020 container, tagged HDR10. For Meridian, the 5.1 PCM track from the IMF package went in as E-AC-3 at 640k, so the demo exercises the audio path too.
The second trap came from the panel tests. I generated nine clips with jellyfin-ffmpeg: dead-pixel colour cycle, grey uniformity, 10-bit gradients, an HDR10 blooming box and starfield, HDR10 peak windows, 60 and 24 fps motion, and SMPTE bars. With libx265, the ffmpeg flags -color_primaries, -color_trc, and -colorspace alone left the mp4 without HDR tags. The encoder needs them again inside -x265-params:
-c:v libx265 -preset superfast -crf 10 -pix_fmt yuv420p10le \
-color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc \
-x265-params colorprim=bt2020:transfer=smpte2084:colormatrix=bt2020nc:hdr10=1:hdr10-opt=1:repeat-headers=1:master-display=G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1):max-cll=1000,400 \
-tag:v hvc1 -movflags +faststartThe script that builds all nine clips sits in my homelab repo, so the panel tests can be rebuilt after any change to the chain.
New demo files go straight to one data disk, not through the cache, so the mover never touches them. The whole library is also excluded from subtitle management. It's a test bench, not content.
Questions
- Does the Nvidia Shield output HDR10+?
- No. The Shield outputs Dolby Vision and HDR10, never HDR10+. An HDR10+ file still plays, but the TV gets its HDR10 base layer. So scoring HDR10+ higher buys nothing when the Shield is the player.
- Should I use DV Boost or HDR10+ Boost in Recyclarr?
- Pick the one your actual player can send to the TV. With a Shield in front of the TV, that is DV Boost. Add HDR10+ Boost only if a player that outputs HDR10+, such as the TV's own app, becomes the one you use.
- Why does my Netflix Open Content clip look washed out?
- The mp4 files in the Netflix Open Content bucket carry PQ pixels but no colour tags, so the TV treats them as SDR. Re-encode to 10-bit HEVC with BT.2020 primaries and PQ transfer tagged as HDR10.
- Why does ffmpeg with libx265 not tag my file as HDR10?
- The -color_primaries and -color_trc flags alone left the mp4 untagged. Put colorprim, transfer and colormatrix inside -x265-params as well, plus hdr10=1 and the mastering display values.