Summary
FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandHdrToSdr/1.0.0/index.ts applies a single, hardcoded, CPU-only filter to every video stream it processes:
-vf zscale=t=linear:npl=100,format=yuv420p
This is the only HDR→SDR option in the repo (verified: only one version folder exists, no alternate/newer implementation, and no separate GPU-native tonemap plugin exists elsewhere in the tree).
The gap
zscale runs on the CPU. For any flow using a hardware-accelerated decode pipeline (e.g. -hwaccel cuda -hwaccel_output_format cuda, keeping the decoded frame resident on the GPU for a fully hardware-accelerated decode→filter→encode chain), inserting this plugin forces an implicit download of every frame to system memory for the CPU filter, then a re-upload back to the GPU for encoding — even though ffmpeg builds Tdarr already ships/uses commonly include GPU-native tonemap filters that could do this entirely on-device:
tonemap_cuda
tonemap_opencl
tonemap_vaapi
(Confirmed available via ffmpeg -filters on a current jellyfin-ffmpeg 7.1.x build.)
Suggested fix
Add a GPU-native code path (e.g. an input selecting cpu / cuda / opencl / vaapi, mirroring how ffmpegCommandSetVideoEncoder already branches on hardware type) that uses the matching tonemap_* filter and keeps the frame on-device end to end when the flow's decode step is already hardware-accelerated, falling back to the current zscale behavior for CPU-decode flows.
Happy to submit a PR with this if it's a welcome direction — wanted to raise it as an issue first in case there's context/reasoning behind the current CPU-only implementation I'm missing.
Summary
FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandHdrToSdr/1.0.0/index.tsapplies a single, hardcoded, CPU-only filter to every video stream it processes:This is the only HDR→SDR option in the repo (verified: only one version folder exists, no alternate/newer implementation, and no separate GPU-native tonemap plugin exists elsewhere in the tree).
The gap
zscaleruns on the CPU. For any flow using a hardware-accelerated decode pipeline (e.g.-hwaccel cuda -hwaccel_output_format cuda, keeping the decoded frame resident on the GPU for a fully hardware-accelerated decode→filter→encode chain), inserting this plugin forces an implicit download of every frame to system memory for the CPU filter, then a re-upload back to the GPU for encoding — even thoughffmpegbuilds Tdarr already ships/uses commonly include GPU-native tonemap filters that could do this entirely on-device:tonemap_cudatonemap_opencltonemap_vaapi(Confirmed available via
ffmpeg -filterson a currentjellyfin-ffmpeg7.1.x build.)Suggested fix
Add a GPU-native code path (e.g. an input selecting
cpu/cuda/opencl/vaapi, mirroring howffmpegCommandSetVideoEncoderalready branches on hardware type) that uses the matchingtonemap_*filter and keeps the frame on-device end to end when the flow's decode step is already hardware-accelerated, falling back to the currentzscalebehavior for CPU-decode flows.Happy to submit a PR with this if it's a welcome direction — wanted to raise it as an issue first in case there's context/reasoning behind the current CPU-only implementation I'm missing.