Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .config/mpv/albumart.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 87 additions & 0 deletions .config/mpv/mpv.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Video output and performance
profile=high-quality # Enable high-quality playback settings
vo=gpu-next # Use modern GPU-accelerated video output
gpu-api=vulkan # Use Vulkan graphics API for better performance
taskbar-progress=no # Disable progress bar in taskbar
force-seekable=yes # Force enable seeking for all files
keep-open=always # Keep player open after playback ends
reset-on-next-file=pause # Auto-play next file in playlist
hwdec=vulkan # Enable hardware decoding with Vulkan
dither-depth=8 # Set dithering to match 8-bit displays
scale-antiring=0.6 # Reduce ringing artifacts when scaling

# Window management
autofit-larger=1280x720 # Maximum window size
autofit-smaller=640x360 # Minimum window size (same as initial)
keepaspect-window=no # Allow window to maintain fixed size regardless of video aspect ratio

# Debanding settings (remove color banding artifacts)
deband=no # Enable debanding only when needed (toggle with 'd' key)
deband-iterations=2 # Number of debanding passes
deband-threshold=64 # Banding detection threshold
deband-range=17 # Spatial radius for debanding
deband-grain=12 # Add grain to prevent oversmoothing

# On-screen display (OSD) and controls
osd-bar=no # Disable default volume bar
osc=no # Disable default on-screen controller
border=no # Remove window border
cursor-autohide-fs-only=yes # Always show cursor in windowed mode
cursor-autohide=300 # Hide cursor after 300ms in fullscreen
osd-level=1 # OSD message verbosity level
osd-duration=1000 # OSD message display time (ms)
hr-seek=yes # Enable precise seeking between keyframes

# OSD visual styling
osd-font='Verdana'
osd-font-size=20
osd-color='#FFFFFF' # White text
osd-border-color='#000000' # Black border
osd-border-size=0.6 # Border thickness
osd-blur=0.2 # Slight blur effect

# Language preferences
alang=ja,jp,jpn,en,eng # Audio language priority
slang=en,eng # Subtitle language priority

# Audio settings
volume=100 # Default volume (100%)
audio-file-auto=fuzzy # Auto-load matching external audio
volume-max=200 # Maximum volume (200%)
audio-pitch-correction=yes # Maintain pitch when changing speed

# Subtitle settings
demuxer-mkv-subtitle-preroll=yes # Preload subtitles in MKV files
sub-fix-timing=no # Don't automatically fix subtitle timing
sub-auto=all # Auto-load all external subtitles

# Subtitle styling (applies to unstyled subtitles)
sub-font='Netflix Sans Medium'
sub-font-size=40
sub-color='#FFFFFFFF' # White with full opacity
sub-border-color='#FF000000' # Black with full opacity
sub-border-size=2.0 # Thick border for readability
sub-shadow-offset=0 # No shadow
sub-spacing=0.0 # Default character spacing

# Screenshot settings
screenshot-format=png # PNG format for screenshots
screenshot-high-bit-depth=yes # Preserve video bit depth
screenshot-png-compression=1 # Low compression (faster saves)
screenshot-directory="~/Pictures/mpv-screenshots" # Save location
screenshot-template="%f-%wH.%wM.%wS.%wT-#%#00n" # File naming format

# Auto-profiles for specific content types

# WEB-DL anime profiles (auto-enable debanding for known groups)
[WEB-DL]
profile-desc=WEB-DL Anime (HatSubs, SubsPlease, HorribleSubs, Erai-raws)
profile-cond=string.match(p.filename, "HatSubs")~=nil or string.match(p.filename, "SubsPlease")~=nil or string.match(p.filename, "HorribleSubs")~=nil or string.match(p.filename, "Erai%-raws")~=nil
deband=yes

# Music playback profile
[music]
keep-open=yes # Keep player open after music ends
audio-exclusive=yes # Exclusive audio access for higher quality
audio-channels=stereo # Force stereo output
audio-normalize-downmix=yes # Normalize audio when downmixing
62 changes: 62 additions & 0 deletions .config/mpv/script-opts/osc.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Show OSC in windowed mode (yes/no)
showwindowed=yes

# Show OSC in fullscreen mode (yes/no)
showfullscreen=yes

# Controller scaling factor in windowed mode
scalewindowed=1

# Controller scaling factor in fullscreen mode
scalefullscreen=1

# Controller scaling factor when rendered on a forced window
scaleforcedwindow=2

# Scale controller with the video (yes/no)
vidscale=yes

# Duration in ms until OSC hides without mouse movement (negative value = always on)
hidetimeout=1000

# Duration of fade out in ms (0 = no fade)
fadeduration=500

# Minimum pixels the mouse must move between ticks to trigger OSC display
minmousemove=3

# Use native mpv values and disable internal OSC tracklist management (yes/no)
iamaprogrammer=no

# Default OSC font
font='mpv-osd-symbols'

# Show seekrange overlay (yes/no)
seekrange=yes

# Transparency of seekranges (0-255)
seekrangealpha=128

# Use keyframes when dragging the seekbar (yes/no)
seekbarkeyframes=yes

# Title string (supports property expansion)
title='${media-title}'

# Show title with no hide timeout on pause (yes/no)
showtitle=yes

# Display total time instead of remaining time (yes/no)
timetotal=no

# Initial visibility mode (auto/yes/no)
visibility=auto

# Show window controls (auto/yes/no)
windowcontrols=auto

# Show mute button and volume slider (yes/no)
volumecontrol=yes

# Language (eng/chs)
language=eng
41 changes: 41 additions & 0 deletions .config/mpv/script-opts/thumbfast.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Socket path (leave empty for auto)
socket=

# Thumbnail path (leave empty for auto)
thumbnail=

# Maximum thumbnail generation size in pixels (scaled down to fit)
# Values are scaled when hidpi is enabled
max_height=200
max_width=200

# Scale factor for thumbnail display size (requires mpv 0.38+)
# Note that this is lower quality than increasing max_height and max_width
scale_factor=1

# Apply tone-mapping, no to disable
tone_mapping=auto

# Overlay id
overlay_id=42

# Spawn thumbnailer on file load for faster initial thumbnails
spawn_first=no

# Close thumbnailer process after an inactivity period in seconds, 0 to disable
quit_after_inactivity=0

# Enable on network playback
network=no

# Enable on audio playback
audio=no

# Enable hardware decoding
hwdec=no

# Windows only: use native Windows API to write to pipe (requires LuaJIT)
direct_io=no

# Custom path to the mpv executable
mpv_path=mpv
153 changes: 153 additions & 0 deletions .config/mpv/scripts/albumart.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
local mp = require("mp")
local msg = require("mp.msg")
local opt = require("mp.options")

local options = {
auto = true,
profile = "music",
undo_profile = "",
enable = false,
cover_path = "~/.config/mpv/albumart.jpg",
font_size = "24",
font_color = "#fafafa",
ignore_embedded_cover = false,
}

opt.read_options(options, "musicmode")
msg.info("musicmode options loaded")

local musicMode = false
local temp_cover_path = "/tmp/mpv_music_cover.jpg"

local function get_metadata()
local metadata = mp.get_property_native("metadata") or {}
local info = {
title = mp.get_property("media-title") or mp.get_property("filename"),
artist = metadata.artist or "Unknown Artist",
album = metadata.album or "Unknown Album",
date = metadata.date or "",
genre = metadata.genre or "",
track = metadata.track or "",
}
msg.info(string.format("metadata fetched: %s - %s", info.artist, info.title))
return info
end

local function create_cover_with_info()
local info = get_metadata()
local cover_path = mp.command_native({ "expand-path", options.cover_path })
msg.info("creating cover with info")

local texts = {}
table.insert(texts, string.format('"%s"', info.title))
table.insert(texts, string.format("by %s", info.artist))
table.insert(texts, string.format("Album: %s", info.album))

local magick_cmd = { "magick", cover_path }
table.insert(magick_cmd, "-fill")
table.insert(magick_cmd, options.font_color)
table.insert(magick_cmd, "-pointsize")
table.insert(magick_cmd, options.font_size)
table.insert(magick_cmd, "-font")
table.insert(magick_cmd, "Source-Han-Serif-CN")

for i, text in ipairs(texts) do
table.insert(magick_cmd, "-draw")
table.insert(magick_cmd, string.format("text 64,%d '%s'", 192 + (i - 1) * 35, text))
end
table.insert(magick_cmd, temp_cover_path)

msg.info(string.format("executing imagemagick command: %s", table.concat(magick_cmd, " ")))

local result = mp.command_native({
name = "subprocess",
args = magick_cmd,
capture_stdout = true,
capture_stderr = true,
})

if result.status ~= 0 then
msg.error(string.format("imagemagick failed: %s", result.stderr))
end

return result.status == 0
end

local function loadCoverWithInfo()
msg.info("loading cover with info")
if create_cover_with_info() then
msg.info("using generated cover with info")
mp.commandv("video-add", temp_cover_path, "select")
else
msg.info("falling back to plain cover")
mp.commandv("video-add", mp.command_native({ "expand-path", options.cover_path }), "select")
end
end

local function is_audio_file()
if mp.get_property("track-list/0/type") == "audio" then
return true
elseif mp.get_property("track-list/0/albumart") == "yes" then
return true
end
return false
end

local function shouldUsePresetCover()
if not is_audio_file() then
return false
end
if options.ignore_embedded_cover then
return true
else
local tracks = mp.get_property_native("track-list")
for _, track in ipairs(tracks) do
if track.type == "video" then
return false
end
end
return true
end
end

local function toggle_music_mode()
if musicMode then
msg.info("deactivating music mode")
if options.undo_profile ~= "" then
mp.commandv("apply-profile", options.undo_profile)
end
mp.osd_message("Music Mode disabled")
else
msg.info("activating music mode")
if options.profile ~= "" then
mp.commandv("apply-profile", options.profile)
end
mp.osd_message("Music Mode enabled")
end

musicMode = not musicMode
mp.set_property_bool("user-data/music_mode/active", musicMode)

if musicMode and shouldUsePresetCover() then
mp.add_timeout(0.1, loadCoverWithInfo)
end
end

local function file_loaded()
if shouldUsePresetCover() then
if options.auto and not musicMode then
toggle_music_mode()
end
if musicMode then
loadCoverWithInfo()
end
elseif musicMode and options.undo_profile ~= "" then
toggle_music_mode()
end
end

if options.enable then
toggle_music_mode()
end

mp.register_event("file-loaded", file_loaded)
Loading