My mpv setup: player settings, a keybind map, a uosc theme, and the scripts I run.
| Playing, with the interface showing |
|---|
![]() |
Important
Two things are deliberately missing: the shaders, too large to commit, and the uosc folder, taken from upstream. uosc carries one local change kept in patches/ rather than a fork: run just patch after installing or updating it, or the menu reverts to stock.
Moonlight: dark, low-contrast, thin, set in uosc.conf.
| At rest: the minimized timeline alone | Woken: top bar, controls, timeline |
|---|---|
![]() |
![]() |
TAB toggles the whole interface, SHIFT+TAB just the bottom bar. The timeline colours recognised ranges, so the OP, the ED and the preview read as bands rather than ticks.
patches/uosc-cascade-menu.patch makes uosc's menu behave like a native context menu: opens where you clicked, cascades by depth instead of centring and sliding, walks in and out on hover. The folder is gitignored, so patches/apply.py reapplies it after every uosc update.
just first-run sets up mpv, uosc, the shaders, your keyboard layout and AniList automatically, then shows a receipt before anything runs. first-run.py is standard library only: python first-run.py works with no just installed.
| Mode | Where mpv goes | The config |
|---|---|---|
here |
this repo folder | read in place, edits are live at once |
system |
the mpv you already have | copied beside that executable |
portable |
a folder you name | copied there, nothing else touched |
Pick here if you'll keep editing the config.
| Start | The first question | The receipt, before anything runs |
|---|---|---|
![]() |
![]() |
![]() |
| Tool | Needed for | Without it |
|---|---|---|
| mpv | everything | nothing runs |
| ffmpeg | F4 subtitle index, subtitle export, chapter remux |
those three fail silently at the moment you press |
| Python 3.8+ | just patch, the AniList scripts, first-run.py |
no uosc patch and no AniList |
| uv | just setup, which vendors requests and guessit |
first-run.py falls back to pip |
| just | the recipes below | run the command inside each recipe by hand |
mpv has no official Windows binary; pick a build from mpv.io/installation.
By hand instead: copy portable_config/ next to mpv.exe, add uosc and shaders yourself.
%%{init: {"theme": "base", "themeVariables": {"darkMode": true, "background": "#0D0E17", "textColor": "#EEEEFA", "treeView": {"labelColor": "#EEEEFA", "lineColor": "#30363d", "iconColor": "#8b949e"}}}}%%
treeView-beta
portable_config/
mpv.conf
input.conf
profiles.conf
fonts.conf
fonts/
script-opts/
uosc.conf ## the theme
scripts/
uosc/ ## add from upstream, then: just patch
shaders/ ## add your own
Anime4K shaders must sit in shaders/Anime4K/, the name profiles.conf and CTRL+1 through CTRL+7 expect. F6's keyboard layout is set in keybind-visualizer.conf, shipped as abnt2 (Brazilian); change it to ansi, iso or jis.
Thirteen, the interface ones all on the Moonlight palette.
An on-screen keyboard on F6, read live from input-bindings. Hover a key or type to search; ≡ marks anything that also lives in the uosc menu.
Searching every binding for delay |
Hovering a single key |
|---|---|
![]() |
![]() |
mpv can't detect your keyboard layout: pick ansi, iso, abnt2, jis, or add your own.
| File | Purpose |
|---|---|
keybind-visualizer.conf |
Selects the layout and points at the layouts file |
keybind-visualizer-layouts.json |
The layout definitions; edit to move keys or add a layout |
Fullscreen, clickable index of every subtitle line with timestamps, on F4. Type to filter, click a line or arrow to it and press Enter.
| Every line of the track, the one playing highlighted | Filtered down to the lines that match |
|---|---|
![]() |
![]() |
Builds uosc's menu from input.conf's #! comments, adding icons and hover descriptions with two extra tokens; nothing in uosc itself is touched. Entries become checkboxes or radio groups automatically, re-read every time the menu opens.
| Every entry with its icon and key | The hovered entry explained under the cascade |
|---|---|
![]() |
![]() |
| Fonts as a radio group | The Anime4K presets, six levels deep |
|---|---|
![]() |
![]() |
| Speeds as a radio group | Subtitle placement, the live one marked |
|---|---|
![]() |
![]() |
| Every loudness filter as a checkbox | The colour controls |
|---|---|
![]() |
![]() |
The syntax, for when you edit the tree
g cycle interpolation #! Video @movie > Interpolation @animation ?Resamples frames to the display rate
# #! Video > ---| Token | Does |
|---|---|
@name |
A Material Icons Rounded ligature, on any part of the path |
?text |
What the entry does, shown under the menu on hover, next to the command it runs |
--- |
A separator under the last entry of the level it sits in, so Video > ---, one level up |
Right-click opens it at the pointer; MENU or the uosc menu button open it centred.
A uosc front end for chapters.lua on c: every chapter listed with its timestamp, add/rename/delete from the menu, and a check against YouTube's chapter rules.
| Every chapter, and what can be done to them | The YouTube rules, checked one by one |
|---|---|
![]() |
![]() |
Shows which sub-select.lua rule picked the current subtitle track, on ALT+SHIFT+s, with a switch to turn it off.
| Which rule picked the track showing right now |
|---|
![]() |
One font for every subtitle, ASS or plain text: mirrors sub-font into a FontName override so F8 and Subtitle > Font pick it consistently. u toggles whether ASS styling can override it.
One shape and palette for every on-screen message, used by every script here instead of raw mp.osd_message.
| The message a keybind leaves on screen | Work that takes a while, with the same spinner uosc uses |
|---|---|
![]() |
![]() |
busy spins for slow work instead of fading; clear removes a message outright, for a script that draws its own interface next.
ALT+F5 resets playback (zoom, pan, aspect, speed, delays, subtitles, colour, shaders) without reloading the file. Volume and mute are left alone.
F3 lists everything currently off this config's own default: audio filters, deinterlace, speed, subtitle overrides, shaders and more. The default for each is snapshotted once at startup, from whatever mpv.conf actually set, so nothing here is a guessed factory value. Click an entry to put just that one back.
| Everything not at default right now |
|---|
![]() |
A pause glyph in the top right, replacing CogentRedTester's mid-screen version with one that matches the interface.
Auto-skips chapters named opening, ending, credits or preview; F11 turns it off for a badly named release.
F5 relaunches the player on the same file at the same position, so a config edit can be tested without losing your place.
F10 toggles it. Watched means everything sitting before the furthest file you opened, so going back to an earlier episode to rewatch a detail still leaves it watched, and nothing moves until the playlist reaches the end of its last file or you close mpv. script-opts/watched-folder.conf sets the folder name, whether it sits next to each file or is one fixed destination for everything, and whether require_eof narrows watched down to the files that actually played to the end.
anilistUpdater is AzuredBlue's, marking episodes watched at 85%. Everything below is local, so an upstream pull reverts it.
| Everything the panel knows about the file playing |
|---|
![]() |
n opens the panel; CTRL+n marks it watched without opening anything. Wrong guess? Search or paste a URL/id from the same panel.
Token setup: open the authorize link, approve it, copy the token AniList shows, press CTRL+n on the panel's link row. Stored encrypted under %LOCALAPPDATA%\mpv-anilist\ rather than as a plain text file, tied to the Windows account.
| File | What it holds |
|---|---|
mpv.conf |
Languages, OSC/window behaviour, subtitle styling, video output, tone mapping |
input.conf |
Every keybind, plus the uosc menu |
profiles.conf |
Conditional profiles |
fonts.conf |
Legacy; loaded Windows fonts before fonts/ replaced it |
| Bindings grouped by keyboard row | The menu, written on the same lines |
|---|---|
![]() |
![]() |
profiles.conf swaps the shader chain and subtitle styling when the path contains Animation, plus profiles for audio-only files and upscaling.
Most run off playback events, no keypress needed.
%%{init: {"theme": "base", "themeVariables": {"darkMode": true, "background": "#0D0E17", "mainBkg": "#141726", "primaryColor": "#141726", "primaryTextColor": "#EEEEFA", "primaryBorderColor": "#7386d0", "secondaryColor": "#252A42", "secondaryTextColor": "#EEEEFA", "secondaryBorderColor": "#8A9BE0", "tertiaryColor": "#252A42", "tertiaryTextColor": "#EEEEFA", "tertiaryBorderColor": "#79c0ff", "lineColor": "#7386d0", "textColor": "#EEEEFA", "titleColor": "#EEEEFA", "nodeBorder": "#7386d0", "nodeTextColor": "#EEEEFA", "clusterBkg": "#12131f", "clusterBorder": "#30363d", "edgeLabelBackground": "#141726", "arrowheadColor": "#7386d0", "border1": "#7386d0", "border2": "#8b949e", "errorBkgColor": "#252A42", "errorTextColor": "#EEEEFA", "fontFamily": "Mulish, system-ui, sans-serif", "fontSize": "14px"}}}%%
flowchart TB
subgraph opens["When a file opens"]
direction TB
p["profiles.conf picks a profile"] --> s["sub-select picks tracks"] --> a["autoload queues the folder"]
end
subgraph plays["While it plays"]
direction TB
t["thumbfast seekbar previews"] --> k["F6 keybinds, F4 sub index"]
end
subgraph ends["As it ends"]
direction TB
n["anilistUpdater at 85%"] --> w["watched-folder on finish"]
end
opens --> plays --> ends
The ten scripts I did not write
Each carries an added header line naming its upstream, so a file on disk always says where it came from. Beyond that, the three at the top differ; the rest are stock.
| Script | Source | What it does | Local change |
|---|---|---|---|
thumbfast.lua |
po5 | Seekbar hover thumbnails | Expands ~~/ in mpv_path; a 10s watchdog kills a hung spawn |
sub-export.lua |
kelciour | Extracts the current subtitle next to the video | Runs in the background rather than freezing the player; spinner and percentage from ffmpeg's own progress; themed messages |
skip-to-silence.lua |
detuur | Jumps to the next silence, usually the OP's end | F9 rather than F3; themed message |
anilistUpdater |
AzuredBlue | Marks the episode watched on AniList at 85% | Rewritten around the player |
autoload.lua |
mpv | Queues the neighbouring files in the folder | Stock; directory_mode=ignore, so the playlist never descends into watched/ |
chapters.lua |
mar04 | Create, edit and save chapters | Stock; driven by chapters-menu.lua rather than its own bindings |
clipshot.lua |
ObserverOfTime | Screenshot straight to the clipboard | Stock |
sub-select.lua |
CogentRedTester | Picks audio and subtitle tracks by rules | Publishes its rules and its match over user-data, for sub-select-menu.lua |
reactive_vf_bypass.lua |
allecsc | Keeps the SVP filter chain honest | Stock |
reactive_vf_bypass_keyword.lua |
allecsc | The same, matched by keyword | Stock |
Formatted with the repo's stylua settings, so a diff against upstream is mostly reindentation.
Scripts kept but not loaded
Tried and dropped, kept for reference in scripts/.unused/, which mpv skips: autodeint.lua, better-chapter.lua, inputevent.lua, memo.lua, mute-on-specific-subtitle-words.js, osc.lua, pause-indicator-middle.lua, sub-bilingual.lua.
Shaders, Anime4K among them, are too large to commit; shaders_list.txt names them. Fonts sit in fonts/, which loads faster than the Windows font folder.


























