If you already have a high-end mpv setup working correctly, the next bottleneck is usually not the renderer. It is the layer that decides whether mpv opens the original file directly or whether Jellyfin pushes playback through a weaker path first. That is where Jellyfin MPV Shim matters.
For a quality-first home theater setup, the most important job of `conf.json` is not cosmetic customization. It is keeping playback aligned with what the local system already does well: direct file access, local decoding, local HDR handling, Dolby Vision-aware fallback behavior, and AVR audio passthrough. If the shim prefers transcoding or gets in the way of local file access, the quality ceiling drops immediately.
This guide focuses only on the settings that materially affect that outcome. It is based on source-level behavior, real playback logs, and a tuned Windows mpv pipeline rather than generic Jellyfin client advice.
This Jellyfin MPV Shim guide builds on a properly configured mpv setup.
If you haven’t configured mpv yet, start with the main Best mpv config 2026, and use the mpv setup guide addendum if your platform differs.
TL;DR
– Enable `direct_paths` → highest quality playback
– Use `path_substitutions` → map server paths to local files
– Disable:
– `transcode_hdr`
– `transcode_dolby_vision`
– Max out `local_kbps` / `remote_kbps`
– Let mpv handle rendering, HDR, and audio
What this article is about and what it is not
This is a guide to `conf.json` for Jellyfin MPV Shim, not a guide to the whole mpv render stack. The core mpv renderer, HDR policy, Dolby Vision-aware profile logic, and AVR audio decisions belong in `mpv.conf` or, in my case, the Best mpv config 2026.
The shim exists one layer above that. Its concern is playback selection, path handling, client behavior, and whether it cooperates with your existing mpv configuration.
That distinction matters because many people try to solve shim problems with mpv options and mpv problems with shim options. Those are different layers, and the best results come from giving each layer a narrower job.
The core principle: direct paths beat transcode-first behavior
For maximum quality, the best playback path is usually the most boring one:
1. Jellyfin identifies the original media source.
2. The shim resolves that source to a locally accessible path.
3. mpv opens the actual file directly.
4. Your local mpv configuration handles video, HDR, Dolby Vision-aware logic, subtitles, and audio passthrough.
That is the right model for a system with a tuned local mpv configuration because it avoids server-side video conversion, server-side audio conversion, HLS instability, and browser-style compatibility fallbacks.
That is why direct paths are used here. When the client machine already has local file access and a tuned mpv stack, they provide the better playback experience.
Why direct paths produce a better playback experience
The quality benefits of direct paths is straightforward.
First, direct paths preserve the original file container and streams instead of asking the server to prepare an alternate delivery path. That matters for high-bitrate remuxes, HDR titles, Dolby Vision profile fallback cases, and premium audio tracks.
Second, direct paths avoid a failure class that appears in real-world shim usage: the server exposes an HLS transcode URL, the client opens it, and the stream is less stable or fails outright. In my own testing, that weaker path ended in HTTP 500 errors. The direct-path case handed mpv the file itself and played cleanly.
Third, direct paths hand control back to the local player. If your system is already configured for gpu-next, D3D11, HDR-aware profiles, Dolby Vision-aware fallbacks, and AVR-friendly audio passthrough, that is exactly what you want.
If your system can reach the underlying media files directly, `direct_paths` should be enabled. That is the single most important `conf.json` decision for a quality-first setup.
With `direct_paths=true`, the shim attempts to resolve the media source to a path mpv can open directly rather than defaulting to a network stream or transcode URL. In practice, that gives you a cleaner handoff into your local playback chain.
If you disable it, you are more likely to end up treating Jellyfin MPV Shim like a browser client with a nicer player attached. That is not what you want on a serious local playback machine.
`remote_direct_paths` is sometimes misunderstood because people read it as a mobile or truly internet-remote feature. In reality, the meaningful question is whether the client can still access the source path in the environment where it is being used.
For a home setup where the client can still see the same mapped storage, it is reasonable to enable this as well to make sure everything works.
Why path rewriting matters so much
Newer releases of Jellyfin removed the ability of specifying the file path, so if you have a mixed environment (e.g. Jellyfin on Docker and mpv-shim on Windows), path rewriting is critical.
Jellyfin often knows the media source by a server-side path that is not usable on the client as-is. Example, if the server sees `/data/media/movies/Foo.mkv` and the Windows client actually needs `Z:\media\movies\Foo.mkv`, the shim has to translate one view of the library into the other.
Important note on path_substitutions and fork-specific behavior
The `path_substitutions` behavior described here is fork-specific and should not be assumed to be available in a stock upstream installation in the exact same way. In my setup, this is available on my fork and is part of why the direct-path workflow is so effective.
That matters because this is not just a convenience feature. It is one of the key reasons a high-end local client can outperform a more generic network-streaming path. If your shim build does not support the same behavior, you should not expect identical results from the same config.
In my configuration, the path rewrite concept is simple:
"path_substitutions": [
["/data/media", "Z:\\media"]
]That tells the client how to translate the server’s view of the library into the client’s usable local path.
Why transcode_hdr should be off in a tuned mpv setup
If your local mpv configuration already handles HDR correctly, `transcode_hdr` should usually be disabled.
That is not an anti-HDR position. It is the opposite. A high-end local mpv chain is usually better at handling HDR than a forced server-side transcode path.
Once Jellyfin starts converting HDR content on the server, you are no longer testing the quality of your local renderer path. You are testing how well the server can flatten or repack the source into something more generic. For a system designed around mpv, that is a downgrade.
Why transcode_dolby_vision should also be off here
The same logic applies even more strongly to `transcode_dolby_vision`.
mpv is not a native Dolby Vision output stack in the same sense as device-certified playback apps, but a tuned local mpv path can still do more useful things with Dolby Vision files than a generic transcode path that strips the source down to something broadly compatible.
Why audio_output is not a meaningful quality setting here
One trap in `conf.json` reviews is treating every visible key as equally important. They are not.
Some settings matter directly for playback quality and path selection. Others are closer to compatibility leftovers or front-end preferences that do not materially change the outcome on a tuned local mpv setup.
`audio_output` falls into that latter category for this style of configuration. The real audio behavior that matters lives in your mpv audio path, not here. If your goal is HDMI passthrough to an AVR, the meaningful decisions are in mpv’s WASAPI and `audio-spdif` configuration rather than in this shim-side field.
A quality-first example conf.json
This is an example of a quality-first Jellyfin MPV Shim config for a system that can reach the media files directly and already has a tuned mpv stack. Keep defaults but modify these:
"audio_output": "hdmi",
"direct_paths": true,
"enable_osc": true,
"local_kbps": 2147483,
"remote_direct_paths": true,
"remote_kbps": 2147483,
"shader_pack_enable": false,
"thumbnail_enable": false,
"transcode_dolby_vision": false,
"transcode_hdr": false,
"path_substitutions": [
["/data/media", "Z:\\media"]
]What to keep in mpv and what to keep in the shim
This separation is the best way to keep the setup understandable.
Put these decisions in mpv:
– renderer choice
– hardware decode choice
– HDR policy
– Dolby Vision-aware profile logic
– HDR10+ handling
– audio passthrough behavior
Put these decisions in the shim:
– direct path behavior
– path rewriting
– transcode avoidance policy
– basic UI and client behavior
– whether shim-managed shader packs are allowed at all
Who should use this kind of conf.json
This style of config is right for you if the following are true:
– your client machine can access the original media files directly
– your mpv config is already tuned and trusted
– your priority is original-file playback quality, not generic compatibility
– your setup includes HDR-capable playback and an AVR-friendly audio chain
– you are willing to use fork-specific functionality if it materially improves playback behavior
If those things are true, a direct-path-oriented `conf.json` is the correct design.
Who should not use this
If your client cannot access the real media files, if your environment changes between locations, if you rely on the stock upstream behavior without fork-specific path substitution support, or if your system is better served by more generic compatibility behavior, then you should not copy this config line for line.
The logic matters more than the literal values. The reason this setup works is that the architecture matches the environment.
Final thoughts
The best Jellyfin MPV Shim configuration is the one that does the least.
If your system already has:
– direct file access
– a tuned mpv renderer
– proper HDR handling
– AVR passthrough
Then the shim should not reinterpret, convert, or “improve” anything. It should simply hand the file to mpv. That is what this configuration achieves.
{
"allow_transcode_to_h265": false,
"always_transcode": false,
"audio_output": "hdmi",
"auto_play": true,
"check_updates": true,
"client_uuid": "7ded1c8e-a6f9-419c-8da7-6e28b6b90b47",
"connect_retry_mins": 0,
"direct_paths": true,
"discord_presence": false,
"display_mirroring": false,
"enable_gui": true,
"enable_osc": true,
"force_audio_codec": null,
"force_set_played": false,
"force_video_codec": null,
"fullscreen": true,
"health_check_interval": 300,
"idle_cmd": null,
"idle_cmd_delay": 60,
"idle_ended_cmd": null,
"idle_when_paused": false,
"ignore_ssl_cert": false,
"kb_debug": "~",
"kb_fullscreen": "f",
"kb_kill_shader": "k",
"kb_menu": "c",
"kb_menu_down": "down",
"kb_menu_esc": "esc",
"kb_menu_left": "left",
"kb_menu_ok": "enter",
"kb_menu_right": "right",
"kb_menu_up": "up",
"kb_next": ">",
"kb_pause": "space",
"kb_prev": "<",
"kb_stop": "q",
"kb_unwatched": "u",
"kb_watched": "w",
"lang": null,
"lang_filter": "und,eng,jpn,mis,mul,zxx",
"lang_filter_audio": false,
"lang_filter_sub": false,
"local_kbps": 2147483,
"log_decisions": true,
"media_ended_cmd": null,
"media_key_seek": false,
"media_keys": true,
"menu_mouse": true,
"mpv_ext": false,
"mpv_ext_ipc": null,
"mpv_ext_no_ovr": false,
"mpv_ext_path": null,
"mpv_ext_start": true,
"mpv_log_level": "info",
"notify_updates": true,
"play_cmd": null,
"playback_timeout": 30,
"player_name": "Theater",
"pre_media_cmd": null,
"prefer_transcode_to_h265": false,
"raise_mpv": true,
"remote_direct_paths": true,
"remote_kbps": 2147483,
"sanitize_output": true,
"screenshot_dir": "C:\\Users\\Theater\\Desktop",
"screenshot_menu": true,
"seek_down": -60,
"seek_h_exact": false,
"seek_left": -5,
"seek_right": 5,
"seek_up": 60,
"seek_v_exact": false,
"shader_pack_custom": false,
"shader_pack_enable": false,
"shader_pack_profile": null,
"shader_pack_remember": true,
"shader_pack_subtype": "hq",
"skip_credits_always": false,
"skip_credits_enable": true,
"skip_intro_always": false,
"skip_intro_enable": true,
"stop_cmd": null,
"stop_idle": false,
"subtitle_color": "#808080",
"subtitle_position": "bottom",
"subtitle_size": 70,
"svp_enable": false,
"svp_socket": null,
"svp_url": "http://127.0.0.1:9901/",
"sync_attempts": 5,
"sync_max_delay_skip": 300,
"sync_max_delay_speed": 50,
"sync_method_thresh": 2000,
"sync_osd_message": true,
"sync_revert_seek": true,
"sync_speed_attempts": 3,
"sync_speed_time": 1000,
"thumbnail_enable": false,
"thumbnail_osc_builtin": false,
"thumbnail_preferred_size": 320,
"tls_client_cert": null,
"tls_client_key": null,
"tls_server_ca": null,
"transcode_4k": false,
"transcode_av1": false,
"transcode_dolby_vision": false,
"transcode_hdr": false,
"transcode_hevc": false,
"transcode_hi10p": false,
"transcode_warning": true,
"use_web_seek": false,
"write_logs": true,
"path_substitutions": [
["/data/media", "Z:\\media"]
]
}