├── fonts ├── oscc.ttf ├── Ubuntu-B.ttf ├── Ubuntu-C.ttf ├── Ubuntu-L.ttf ├── Ubuntu-M.ttf ├── Ubuntu-R.ttf ├── Samsungsans.ttf ├── Ubuntu-BI.ttf ├── Ubuntu-LI.ttf ├── Ubuntu-MI.ttf ├── Ubuntu-RI.ttf ├── SamsungOne-400.ttf ├── SamsungOne-700.ttf ├── modernx-osc-icon.ttf ├── Product Sans Bold.ttf ├── SamsungsansMedium.ttf ├── Product Sans Italic.ttf ├── Product Sans Regular.ttf ├── SamsungSharpSans-Bold.ttf ├── Product Sans Bold Italic.ttf └── Material-Design-Iconic-Font.ttf ├── removed_conf ├── lua-settings │ ├── playlistmanager.conf │ └── stats.conf ├── scripts │ ├── equalizer.lua │ ├── ontop-playback.lua │ ├── pause-when-minimize.lua │ ├── open-file-dialog.lua │ ├── autoloop.lua │ ├── auto-save-state.lua │ ├── nextfile.lua │ ├── pause-minimize.lua │ ├── blur-edges.lua │ ├── seek-to.lua │ ├── autoload.lua.bac │ ├── autoload2.lua.bac │ ├── audio-balance.lua │ ├── lin.autoload2.lua │ ├── lin.autoload1.lua │ ├── firequalizer15.lua │ ├── encode.lua │ └── gestures.lua ├── README.md ├── shaders │ ├── SSimDownscaler.glsl │ ├── SSimSuperRes.glsl │ ├── CAS.glsl │ ├── NVSharpen.glsl │ └── AdaptiveSharp.glsl └── input.options ├── scripts ├── autosave.lua ├── local-state.lua ├── clock.lua ├── easycrop.lua ├── youtube-quality.lua ├── autocrop.lua └── visualizer.lua ├── lua-settings └── osc.conf ├── KEY_basic.md ├── README.md ├── mpv.conf └── KEY.md /fonts/oscc.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/oscc.ttf -------------------------------------------------------------------------------- /fonts/Ubuntu-B.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Ubuntu-B.ttf -------------------------------------------------------------------------------- /fonts/Ubuntu-C.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Ubuntu-C.ttf -------------------------------------------------------------------------------- /fonts/Ubuntu-L.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Ubuntu-L.ttf -------------------------------------------------------------------------------- /fonts/Ubuntu-M.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Ubuntu-M.ttf -------------------------------------------------------------------------------- /fonts/Ubuntu-R.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Ubuntu-R.ttf -------------------------------------------------------------------------------- /fonts/Samsungsans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Samsungsans.ttf -------------------------------------------------------------------------------- /fonts/Ubuntu-BI.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Ubuntu-BI.ttf -------------------------------------------------------------------------------- /fonts/Ubuntu-LI.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Ubuntu-LI.ttf -------------------------------------------------------------------------------- /fonts/Ubuntu-MI.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Ubuntu-MI.ttf -------------------------------------------------------------------------------- /fonts/Ubuntu-RI.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Ubuntu-RI.ttf -------------------------------------------------------------------------------- /fonts/SamsungOne-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/SamsungOne-400.ttf -------------------------------------------------------------------------------- /fonts/SamsungOne-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/SamsungOne-700.ttf -------------------------------------------------------------------------------- /fonts/modernx-osc-icon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/modernx-osc-icon.ttf -------------------------------------------------------------------------------- /fonts/Product Sans Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Product Sans Bold.ttf -------------------------------------------------------------------------------- /fonts/SamsungsansMedium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/SamsungsansMedium.ttf -------------------------------------------------------------------------------- /fonts/Product Sans Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Product Sans Italic.ttf -------------------------------------------------------------------------------- /fonts/Product Sans Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Product Sans Regular.ttf -------------------------------------------------------------------------------- /fonts/SamsungSharpSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/SamsungSharpSans-Bold.ttf -------------------------------------------------------------------------------- /fonts/Product Sans Bold Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Product Sans Bold Italic.ttf -------------------------------------------------------------------------------- /removed_conf/lua-settings/playlistmanager.conf: -------------------------------------------------------------------------------- 1 | [osc-conf] 2 | playlist_savepath=C:\\Users\\PC4466\\Desktop\\ 3 | playlist_header_lang= 4 | -------------------------------------------------------------------------------- /removed_conf/scripts/equalizer.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/removed_conf/scripts/equalizer.lua -------------------------------------------------------------------------------- /fonts/Material-Design-Iconic-Font.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thisisshihan/mpv-player-config-snad/HEAD/fonts/Material-Design-Iconic-Font.ttf -------------------------------------------------------------------------------- /removed_conf/lua-settings/stats.conf: -------------------------------------------------------------------------------- 1 | [osc-conf] 2 | duration=4 3 | redraw_delay=1 4 | persistent_overlay=no 5 | plot_perfdata=yes 6 | plot_vsync_ratio=yes 7 | plot_vsync_jitter=yes 8 | flush_graph_data=yes 9 | font=Source Sans Pro 10 | font_mono=Source Sans Pro 11 | font_size=8 12 | font_color=FFFFFF 13 | border_size=0.4 14 | border_color=262626 15 | alpha=78 16 | plot_bg_border_color=0000FF 17 | plot_bg_color=262626 18 | plot_color=FFFFFF -------------------------------------------------------------------------------- /removed_conf/scripts/ontop-playback.lua: -------------------------------------------------------------------------------- 1 | --makes mpv disable ontop when pausing and re-enable it again when resuming playback 2 | --please note that this won't do anything if ontop was not enabled before pausing 3 | 4 | local was_ontop = false 5 | 6 | mp.observe_property("pause", "bool", function(name, value) 7 | local ontop = mp.get_property_native("ontop") 8 | if value then 9 | if ontop then 10 | mp.set_property_native("ontop", false) 11 | was_ontop = true 12 | end 13 | else 14 | if was_ontop and not ontop then 15 | mp.set_property_native("ontop", true) 16 | end 17 | was_ontop = false 18 | end 19 | end) 20 | -------------------------------------------------------------------------------- /removed_conf/scripts/pause-when-minimize.lua: -------------------------------------------------------------------------------- 1 | -- This script pauses playback when minimizing the window, and resumes playback 2 | -- if it's brought back again. If the player was already paused when minimizing, 3 | -- then try not to mess with the pause state. 4 | 5 | local did_minimize = false 6 | 7 | mp.observe_property("window-minimized", "bool", function(name, value) 8 | local pause = mp.get_property_native("pause") 9 | if value == true then 10 | if pause == false then 11 | mp.set_property_native("pause", true) 12 | did_minimize = true 13 | end 14 | elseif value == false then 15 | if did_minimize and (pause == true) then 16 | mp.set_property_native("pause", false) 17 | end 18 | did_minimize = false 19 | end 20 | end) 21 | -------------------------------------------------------------------------------- /scripts/autosave.lua: -------------------------------------------------------------------------------- 1 | -- autosave.lua 2 | -- 3 | -- Periodically saves "watch later" data during playback, rather than only saving on quit. 4 | -- This lets you easily recover your position in the case of an ungraceful shutdown of mpv (crash, power failure, etc.). 5 | -- 6 | -- You can configure the save period by creating a "lua-settings" directory inside your mpv configuration directory. 7 | -- Inside the "lua-settings" directory, create a file named "autosave.conf". 8 | -- The save period can be set like so: 9 | -- 10 | -- save_period=30 11 | -- 12 | -- This will set the save period to once every 30 seconds of playback, time while paused is not counted towards the save period timer. 13 | -- The default save period is 30 seconds. 14 | local options = require 'mp.options' 15 | 16 | local o = { 17 | save_period = 30 18 | } 19 | 20 | options.read_options(o) 21 | 22 | local mp = require 'mp' 23 | 24 | local function save() 25 | mp.command("write-watch-later-config") 26 | end 27 | 28 | local save_period_timer = mp.add_periodic_timer(o.save_period, save) 29 | 30 | local function pause(name, paused) 31 | if paused then 32 | save_period_timer:stop() 33 | else 34 | save_period_timer:resume() 35 | end 36 | end 37 | 38 | mp.observe_property("pause", "bool", pause) 39 | -------------------------------------------------------------------------------- /removed_conf/README.md: -------------------------------------------------------------------------------- 1 | repl.lua. 2 | ======== 3 | 4 | Keybindings 5 | ----------- 6 | 7 | | Key | Action | 8 | | ---: | :--- | 9 | | ` | Show the REPL | 10 | | Esc | Hide the REPL | 11 | | Enter | Run the typed command | 12 | | Shift + Enter | Type a literal newline character | 13 | | Ctrl + , Ctrl + | Move cursor to previous/next word | 14 | | , | Navigate command history | 15 | | PgUp | Go to the first command in the history | 16 | | PgDn | Stop navigating command history | 17 | | Insert | Toggle insert mode | 18 | | Shift + Insert | Paste text (uses the primary selection on X11) | 19 | | Tab | Complete the command or property name at the cursor | 20 | | Ctrl + C | Clear current line | 21 | | Ctrl + K | Delete text from the cursor to the end of the line | 22 | | Ctrl + L | Clear all log messages from the console | 23 | | Ctrl + U | Delete text from the cursor to the beginning of the line | 24 | | Ctrl + V | Paste text (uses the clipboard on X11) | 25 | | Ctrl + W | Delete text from the cursor to the beginning of the current word | 26 | 27 | Commands 28 | -------- 29 | 30 | | Command | Action | 31 | | :--- | :--- | 32 | | ``script-message-to repl type ""`` | Show the REPL and pre-fill it with the provided text | 33 | 34 | Known issues 35 | -------------------------------------------------------------------------------- /removed_conf/scripts/open-file-dialog.lua: -------------------------------------------------------------------------------- 1 | -- To the extent possible under law, the author(s) have dedicated all copyright 2 | -- and related and neighboring rights to this software to the public domain 3 | -- worldwide. This software is distributed without any warranty. See 4 | -- for a copy of the CC0 5 | -- Public Domain Dedication, which applies to this software. 6 | 7 | utils = require 'mp.utils' 8 | 9 | function open_file_dialog() 10 | local was_ontop = mp.get_property_native("ontop") 11 | if was_ontop then mp.set_property_native("ontop", false) end 12 | local res = utils.subprocess({ 13 | args = {'powershell', '-NoProfile', '-Command', [[& { 14 | Trap { 15 | Write-Error -ErrorRecord $_ 16 | Exit 1 17 | } 18 | Add-Type -AssemblyName PresentationFramework 19 | 20 | $u8 = [System.Text.Encoding]::UTF8 21 | $out = [Console]::OpenStandardOutput() 22 | 23 | $ofd = New-Object -TypeName Microsoft.Win32.OpenFileDialog 24 | $ofd.Multiselect = $true 25 | 26 | If ($ofd.ShowDialog() -eq $true) { 27 | ForEach ($filename in $ofd.FileNames) { 28 | $u8filename = $u8.GetBytes("$filename`n") 29 | $out.Write($u8filename, 0, $u8filename.Length) 30 | } 31 | } 32 | }]]}, 33 | cancellable = false, 34 | }) 35 | if was_ontop then mp.set_property_native("ontop", true) end 36 | if (res.status ~= 0) then return end 37 | 38 | local first_file = true 39 | for filename in string.gmatch(res.stdout, '[^\n]+') do 40 | mp.commandv('loadfile', filename, first_file and 'replace' or 'append') 41 | first_file = false 42 | end 43 | end 44 | 45 | mp.add_key_binding('ctrl+o', 'open-file-dialog', open_file_dialog) 46 | -------------------------------------------------------------------------------- /lua-settings/osc.conf: -------------------------------------------------------------------------------- 1 | # mpv OSC configuration file by snad 2 | # https://github.com/thisisshihan/mpv-player-config-snad 3 | 4 | showwindowed=yes 5 | showfullscreen=yes 6 | scalewindowed=1 7 | scalefullscreen=1 8 | scaleforcedwindow=1 9 | vidscale=yes 10 | valign=0.8 11 | halign=0.0 12 | hidetimeout=500 13 | fadeduration=200 14 | minmousemove=3 15 | deadzonesize=0.9 16 | seekbarstyle=knob 17 | layout=box 18 | boxalpha=127 19 | title=mpv.snad ~ ${?filename:[${playlist-pos-1}/${playlist-count}] ${filename}}${!filename:No file.} 20 | seekbarhandlesize=1.0 21 | 22 | # Options 23 | # ------- 24 | # osc=yes 25 | # layout=box # box, slimbox, bottombar and topbar (defaul: bottombar) 26 | # boxalpha=127 # 0-255 (default: 80) 27 | # deadzonesize=0.9 # mouse movable area without showing osc 28 | # timetotal=no # Show total time instead remaining time (defaul: no) 29 | # timems=no # Show time with millisecond 30 | # boxmaxchars=80 # default: 80 31 | # visibility=auto # Default: auto (auto hide/show on mouse move) Also supports never and always 32 | # seekbarstyle=slider # Sets the style of the seekbar, slider (diamond marker), knob (circle marker with guide), or bar (fill). (Default: slider) 33 | # seekbarhandlesize=0.6 # Default: 0.6, Size ratio of the seek handle if seekbarstyle is set to diamond or knob. This is relative to the full height of the seekbar. 34 | # seekbarkeyframes # Default: yes, Controls the mode used to seek when dragging the seekbar. If set to yes, default seeking mode is used (usually keyframes, but player defaults and heuristics can change it to exact). If set to no, exact seeking on mouse drags will be used instead. Keyframes are preferred, but exact seeks may be useful in cases where keyframes cannot be found. Note that using exact seeks can potentially make mouse dragging much slower. 35 | -------------------------------------------------------------------------------- /removed_conf/scripts/autoloop.lua: -------------------------------------------------------------------------------- 1 | -- mpv issue 5222 2 | -- Automatically set loop-file=inf for duration <= given length. Default is 5s 3 | -- Use autoloop_duration=n in script-opts/autoloop.conf to set your preferred length 4 | -- Alternatively use script-opts=autoloop-autoloop_duration=n in mpv.conf (takes priority) 5 | -- Also disables the save-position-on-quit for this file, if it qualifies for looping. 6 | 7 | 8 | require 'mp.options' 9 | 10 | function getOption() 11 | -- Use recommended way to get options 12 | local options = {autoloop_duration = 5} 13 | read_options(options) 14 | autoloop_duration = options.autoloop_duration 15 | 16 | 17 | -- Keep old way just for compatibility (remove lines 15-27 soon) 18 | if autoloop_duration ~= 5 then 19 | return 20 | end 21 | 22 | local opt = tonumber(mp.get_opt("autoloop-duration")) 23 | if not opt then 24 | return 25 | end 26 | print("Depracted configuration! Please use script-opts directory to set auto_loop duration") 27 | print("Or use 'script-opts=autoloop-autoloop_duration' in mpv.conf") 28 | autoloop_duration = opt 29 | -- Remove lines 15-27 soon 30 | end 31 | 32 | function set_loop() 33 | local duration = mp.get_property_native("duration") 34 | 35 | -- Checks whether the loop status was changed for the last file 36 | was_loop = mp.get_property_native("loop-file") 37 | 38 | -- Cancel operation if there is no file duration 39 | if not duration then 40 | return 41 | end 42 | 43 | -- Loops file if was_loop is false, and file meets requirements 44 | if not was_loop and duration <= autoloop_duration then 45 | mp.set_property_native("loop-file", true) 46 | mp.set_property_bool("file-local-options/save-position-on-quit", false) 47 | -- Unloops file if was_loop is true, and file does not meet requirements 48 | elseif was_loop and duration > autoloop_duration then 49 | mp.set_property_native("loop-file", false) 50 | end 51 | end 52 | 53 | 54 | getOption() 55 | mp.register_event("file-loaded", set_loop) 56 | -------------------------------------------------------------------------------- /KEY_basic.md: -------------------------------------------------------------------------------- 1 | ----------------------------------- 2 | # Basic Keybindings of [mpv.snad](https://github.com/thisisshihan/mpv-player-config-snad/blob/mpv-config-snad-windows-ubuntu-linux-macos/README.md) 3 | 4 | ## 5 | **Touchpad Gesture** _(swipe with two finger)_
6 | ![s2](https://github.com/thisisshihan/screenshots/blob/master/touchpadGesture2.png) 7 | 8 | ## 9 | **Keyboard Control** 10 | 11 | | | | 12 | | ---: | --- | 13 | | ESC TAB BACKSPACE
ENTER SPACE | **Keys** | 14 | | ENTER | Exit | 15 | | ESC | Exit | 16 | | Q | Save Video Position and Quit to Watch Later | 17 | | SPACE | Pause | 18 | | F | Change Full Screen / Windowed Mode | 19 | | Mouse Button | Change Full Screen / Windowed Mode | 20 | | | Foward 3s | 21 | | | Backward 3s | 22 | | | Foward 6s | 23 | | | Backward 6s | 24 | | CTRL + | Foward 30s | 25 | | CTRL + | Backward 30s | 26 | | CTRL + | Foward 60s | 27 | | CTRL + | Backward 60s | 28 | | SHIFT + | Foward 300s | 29 | | SHIFT + | Backward 300s | 30 | | SHIFT + | Foward 600s | 31 | | SHIFT + | Backward 600s | 32 | | * | Volume Up (Keypad) | 33 | | / | Volume Down (Keypad) | 34 | | " | Volume Up (Key) | 35 | | / | Volume Down (Key) | 36 | | Mouse Wheel | Volume Up (Key) | 37 | | Mouse Wheel | Volume Down (Key) | 38 | | P | Show Playlist | 39 | | CTRL + P | Save Playlist | 40 | | S | Save Screenshot to Desktop | 41 | | D | Enable / Disable DeInterlace | 42 | | J | Change Subtitle Track | 43 | | K | Change Audio Track | 44 | | L | Enable / Disable Repeat Playlist | 45 | | : | Enable / Disable Repeat Current File | 46 | | M | Enable / Disable Mute | 47 | | < | Jump Previous item in Playlist | 48 | | > | Jump Next item in Playlist | 49 | 50 | # 51 | -------------------------------------------------------------------------------- /removed_conf/scripts/auto-save-state.lua: -------------------------------------------------------------------------------- 1 | -- Runs write-watch-later-config periodically 2 | 3 | local options = require 'mp.options' 4 | local o = { save_interval = 60 } 5 | options.read_options(o) 6 | 7 | local function save() 8 | if mp.get_property_bool("resume-playback") then 9 | mp.command("write-watch-later-config") 10 | end 11 | end 12 | 13 | local function save_if_pause(_, pause) 14 | if pause then save() end 15 | end 16 | 17 | local function pause_timer_while_paused(_, pause) 18 | if pause then timer:stop() else timer:resume() end 19 | end 20 | 21 | -- This function runs on file-loaded, registers two callback functions, and 22 | -- then they run delete-watch-later-config when appropriate. 23 | local function delete_watch_later(event) 24 | local path = mp.get_property("path") 25 | 26 | -- Temporarily disables save-position-on-quit while eof-reached is true, so 27 | -- state isn't saved at EOF when keep-open=yes 28 | local function eof_reached(_, eof) 29 | if not can_delete then 30 | return 31 | elseif eof then 32 | print("Deleting state (eof-reached)") 33 | mp.commandv("delete-watch-later-config", path) 34 | mp.set_property("save-position-on-quit", "no") 35 | else 36 | mp.set_property("save-position-on-quit", "yes") 37 | end 38 | end 39 | 40 | local function end_file(event) 41 | mp.unregister_event(end_file) 42 | mp.unobserve_property(eof_reached) 43 | 44 | if not can_delete then 45 | can_delete = true 46 | elseif event["reason"] == "eof" or event["reason"] == "stop" then 47 | print("Deleting state (end-file "..event["reason"]..")") 48 | mp.commandv("delete-watch-later-config", path) 49 | end 50 | end 51 | 52 | mp.observe_property("eof-reached", "bool", eof_reached) 53 | mp.register_event("end-file", end_file) 54 | end 55 | 56 | mp.set_property("save-position-on-quit", "yes") 57 | 58 | can_delete = true 59 | mp.register_script_message("skip-delete-state", function() can_delete = false end) 60 | 61 | timer = mp.add_periodic_timer(o.save_interval, save) 62 | mp.observe_property("pause", "bool", pause_timer_while_paused) 63 | 64 | mp.observe_property("pause", "bool", save_if_pause) 65 | mp.register_event("file-loaded", delete_watch_later) 66 | 67 | -------------------------------------------------------------------------------- /scripts/local-state.lua: -------------------------------------------------------------------------------- 1 | -- this lua script written by snad 2 | -- this lua is a part of 3 | -- https://github.com/thisisshihan/mpv-player-config-snad 4 | 5 | 6 | local opts = require("mp.options") 7 | --local assdraw = require 'mp.assdraw' 8 | --local msg = require 'mp.msg' 9 | --local utils = require 'mp.utils' 10 | 11 | function round_size(num) 12 | mib = (num/(1024*1024)) 13 | if mib < 1024 then 14 | rounded = math.floor(mib) 15 | dec = (mib-math.floor(mib)) 16 | decpoint = math.floor(dec*1000) 17 | return rounded+decpoint/1000 18 | elseif mib > 1024 then 19 | gib = mib / 1024 20 | rounded = math.floor(gib) 21 | dec = (gib-math.floor(gib)) 22 | decpoint = math.floor(dec*1000) 23 | return rounded+decpoint/1000 24 | else 25 | return mib 26 | end 27 | end 28 | 29 | function unit(sizeoffile) 30 | mib = sizeoffile/(1024*1024) 31 | if mib < 1024 then 32 | return " MiB" 33 | else 34 | return " GiB" 35 | end 36 | end 37 | 38 | local settings = { 39 | --set title of window with stripped name 40 | titleStripped = true, 41 | titlePrefix1 = "mpv", 42 | titlePrefix2 = ".sn", 43 | titlePrefix3 = "ad ~ ", 44 | titleSuffix = "", 45 | } 46 | 47 | function on_loaded() 48 | filename = mp.get_property("filename") 49 | plpos = mp.get_property("playlist-pos-1") 50 | plcou = mp.get_property("playlist-count") 51 | --timepos = mp.get_property("time-pos") 52 | --dura = mp.get_property("duration") 53 | filewid = mp.get_property("width") 54 | filehig = mp.get_property("height") 55 | filesize = round_size(mp.get_property("file-size")) 56 | osdStatus = mp.get_property("osd-status-msg") 57 | --filesizeunit = unit(mp.get_property("file-size")) 58 | if settings.titleStripped then 59 | mp.set_property("title", settings.titlePrefix1..settings.titlePrefix2..settings.titlePrefix3.."["..plpos.."/"..plcou.."] "..osdStatus.." ~ "..filename.." ~ ".."["..filewid.."x"..filehig.."] ~ "..filesize..filesizeunit..settings.titleSuffix) 60 | else 61 | mp.set_property("title", settings.titlePrefix1..settings.titlePrefix2..settings.titlePrefix3..filename) 62 | end 63 | end 64 | 65 | mp.register_event("file-loaded", on_loaded) 66 | -------------------------------------------------------------------------------- /scripts/clock.lua: -------------------------------------------------------------------------------- 1 | -- Mozbugbox's lua utilities for mpv 2 | -- Copyright (c) 2015-2018 mozbugbox@yahoo.com.au 3 | -- Licensed under GPL version 3 or later 4 | 5 | --[[ 6 | Show current time on video 7 | Usage: c script_message show-clock [true|yes] 8 | --]] 9 | 10 | local msg = require("mp.msg") 11 | local utils = require("mp.utils") -- utils.to_string() 12 | local assdraw = require('mp.assdraw') 13 | 14 | local update_timeout = 10 -- in seconds 15 | 16 | -- Class creation function 17 | function class_new(klass) 18 | -- Simple Object Oriented Class constructor 19 | local klass = klass or {} 20 | function klass:new(o) 21 | local o = o or {} 22 | setmetatable(o, self) 23 | self.__index = self 24 | return o 25 | end 26 | return klass 27 | end 28 | 29 | -- print content of a lua table 30 | function print_table(tbl) 31 | msg.info(utils.to_string(tbl)) 32 | end 33 | 34 | -- Show OSD Clock 35 | local OSDClock = class_new() 36 | function OSDClock:_show_clock() 37 | -- Show wall clock on bottom left corner 38 | local osd_w, osd_h, aspect = mp.get_osd_size() 39 | 40 | local scale = 1 41 | local fontsize = tonumber(mp.get_property("options/osd-font-size")) / scale 42 | fontsize = math.floor(fontsize) 43 | -- msg.info(fontsize) 44 | -- 45 | local now = os.date("%H:%M") 46 | local ass = assdraw:ass_new() 47 | ass:new_event() 48 | ass:an(1) 49 | ass:append(string.format("{\\fs%d}", fontsize)) 50 | ass:append(now) 51 | ass:an(0) 52 | mp.set_osd_ass(osd_w, osd_h, ass.text) 53 | -- msg.info(ass.text, osd_w, osd_h) 54 | end 55 | 56 | function clear_osd() 57 | local osd_w, osd_h, aspect = mp.get_osd_size() 58 | mp.set_osd_ass(osd_w, osd_h, "") 59 | end 60 | 61 | function OSDClock:toggle_show_clock(val) 62 | local trues = {["true"]=true, ["yes"] = true} 63 | if self.tobj then 64 | if trues[val] ~= true then 65 | self.tobj:kill() 66 | self.tobj = nil 67 | clear_osd() 68 | end 69 | elseif val == nil or trues[val] == true then 70 | self:_show_clock() 71 | local tobj = mp.add_periodic_timer(update_timeout, 72 | function() self:_show_clock() end) 73 | self.tobj = tobj 74 | end 75 | end 76 | 77 | local osd_clock = OSDClock:new() 78 | function toggle_show_clock(v) 79 | osd_clock:toggle_show_clock(v) 80 | end 81 | 82 | mp.add_key_binding("", "show-clock", toggle_show_clock) 83 | 84 | -------------------------------------------------------------------------------- /removed_conf/scripts/nextfile.lua: -------------------------------------------------------------------------------- 1 | local msg = require('mp.msg') 2 | local assdraw = require('mp.assdraw') 3 | 4 | local script_name = "nextfile" 5 | 6 | local settings = { 7 | 8 | --filetypes,{'mp4','mkv'} for specific or {''} for all filetypes 9 | filetypes = {'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp', 10 | 'mp3', 'wav', 'ogv', 'flac', 'm4a', 'wma', 'jpg', 'gif', 'png', 'jpeg', 'webp'}, 11 | 12 | --linux(true)/windows(false)/auto(nil) 13 | linux_over_windows = nil, 14 | 15 | --at end of directory jump to start and vice versa 16 | allow_looping = true, 17 | 18 | } 19 | --check os 20 | if settings.linux_over_windows==nil then 21 | local o = {} 22 | if mp.get_property_native('options/vo-mmcss-profile', o) ~= o then 23 | settings.linux_over_windows = false 24 | else 25 | settings.linux_over_windows = true 26 | end 27 | end 28 | 29 | function nexthandler() 30 | movetofile(true) 31 | end 32 | 33 | function prevhandler() 34 | movetofile(false) 35 | end 36 | 37 | function escapepath(dir, escapechar) 38 | return string.gsub(dir, escapechar, '\\'..escapechar) 39 | end 40 | 41 | function movetofile(forward) 42 | if mp.get_property('filename'):match("^%a%a+:%/%/") then return end 43 | local pwd = mp.get_property('working-directory') 44 | local relpath = mp.get_property('path') 45 | if not pwd or not relpath then return end 46 | 47 | local path = utils.join_path(pwd, relpath) 48 | local file = mp.get_property("filename") 49 | local dir = utils.split_path(path) 50 | 51 | local search = ' ' 52 | for w in pairs(settings.filetypes) do 53 | if settings.linux_over_windows then 54 | search = search.."*."..settings.filetypes[w]..' ' 55 | else 56 | search = search..'"'..escapepath(dir, '"').."*."..settings.filetypes[w]..'" ' 57 | end 58 | end 59 | 60 | local popen, err = nil, nil 61 | if settings.linux_over_windows then 62 | popen, err = io.popen('cd "'..escapepath(dir, '"')..'";ls -1p'..search..'2>/dev/null') 63 | else 64 | popen, err = io.popen('dir /b'..(search:gsub("/", "\\"))) 65 | end 66 | if popen then 67 | local found = false 68 | local memory = nil 69 | local lastfile = true 70 | local firstfile = nil 71 | for dirx in popen:lines() do 72 | if found == true then 73 | mp.commandv("loadfile", dir..dirx, "replace") 74 | lastfile=false 75 | break 76 | end 77 | if dirx == file then 78 | found = true 79 | if not forward then 80 | lastfile=false 81 | if settings.allow_looping and firstfile==nil then 82 | found=false 83 | else 84 | if firstfile==nil then break end 85 | mp.commandv("loadfile", dir..memory, "replace") 86 | break 87 | end 88 | end 89 | end 90 | memory = dirx 91 | if firstfile==nil then firstfile=dirx end 92 | end 93 | if lastfile and firstfile and settings.allow_looping then 94 | mp.commandv("loadfile", dir..firstfile, "replace") 95 | end 96 | if not found and memory then 97 | mp.commandv("loadfile", dir..memory, "replace") 98 | end 99 | popen:close() 100 | else 101 | mp.msg.error("could not scan for files: "..(err or "")) 102 | end 103 | end 104 | 105 | mp.add_key_binding('shift+RIGHT', 'nextfile', nexthandler) 106 | mp.add_key_binding('shift+LEFT', 'previousfile', prevhandler) -------------------------------------------------------------------------------- /removed_conf/scripts/pause-minimize.lua: -------------------------------------------------------------------------------- 1 | -- AUTHORS: detuur, zaza42 2 | -- License: MIT 3 | -- link: https://github.com/detuur/mpv-scripts 4 | 5 | -- This script minimises and pauses the window when 6 | -- the boss key (default 'b') is pressed. 7 | -- Can be overwriten in input.conf as follows: 8 | -- KEY script-binding boss-key 9 | -- xdotool is required on Xorg(Linux) 10 | 11 | local platform = nil --set to 'linux', 'windows' or 'macos' to override automatic assign 12 | if not platform then 13 | local o = {} 14 | if mp.get_property_native('options/vo-mmcss-profile', o) ~= o then 15 | platform = 'windows' 16 | elseif mp.get_property_native('options/input-app-events', o) ~= o then 17 | platform = 'macos' 18 | else 19 | platform = 'linux' 20 | end 21 | end 22 | 23 | utils = require 'mp.utils' 24 | 25 | -- TODO: macOS implementation? 26 | function boss_key() 27 | mp.set_property_native("pause", true) 28 | if platform == 'windows' then 29 | mp.command([[run cmd /c echo m > \\.\pipe\mpv-boss-key-]]..utils.getpid()) 30 | elseif platform == 'linux' then 31 | utils.subprocess({ args = {'xdotool', 'getactivewindow', 'windowminimize'} }) 32 | end 33 | end 34 | 35 | -- Windows is a princess (a very ugly one at that) and needs an external process 36 | -- to minimize mpv, with which we communicate through named pipes. I spent an 37 | -- entire day shouting at my screen to arrive at the code below. This went 38 | -- through several complete rewrites as every iteration broke in subtly 39 | -- different ways. Did you know that Powershell and CMD's echo commands behave 40 | -- slightly differently, one refusing to properly write to some streams where 41 | -- the other doesn't? Did you know Powershell's Events and any kind of async 42 | -- is absolute DOG SHIT which will happily chooch in an interactive session only 43 | -- to shit in your face when put inside a script? Honestly I could write several 44 | -- kb about the bullshit I've encountered but it's past midnight and I just want 45 | -- to watch my weeb shit. Fuck you microsoft. 46 | if platform == 'windows' then 47 | utils.subprocess_detached({ 48 | args = {'powershell', '-NoProfile', '-Command', [[&{ 49 | $bosspid = ]]..utils.getpid()..[[ 50 | # Construct the named pipe's name 51 | $pipename = -join('mpv-boss-key-',$bosspid) 52 | $fullpipename = -join("\\.\pipe\", $pipename) 53 | # This will run in a separate thread 54 | $minimizeloop = { 55 | param($pipename, $bosspid) 56 | # Create the named pipe 57 | $pipe = new-object System.IO.Pipes.NamedPipeServerStream($pipename) 58 | # Compile the Win32 API function call 59 | $signature='[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);' 60 | $showWindowAsync = Add-Type -memberDefinition $signature -name "Win32ShowWindowAsync" -namespace Win32Functions -passThru 61 | # The core loop 62 | while($true) { 63 | $pipe.WaitForConnection() 64 | if ($pipe.ReadByte() -ne 109) { 65 | break 66 | } 67 | $pipe.Disconnect() 68 | $showWindowAsync::ShowWindowAsync((Get-Process -id $bosspid).MainWindowHandle, 2) 69 | } 70 | $pipe.Dispose() 71 | } 72 | # Exiting this monstrosity (THANKS POWERSHELL FOR BROKEN ASYNC) is surprisingly 73 | # cumbersome. It took literal hours to find something that didn't spontaneously 74 | # combust. Fuck windows. 75 | $bossproc = Get-Process -pid $bosspid -ErrorAction SilentlyContinue 76 | $exitsequence = { 77 | &{echo q > $fullpipename} 2> $null 78 | [Environment]::Exit(0) 79 | } 80 | if ((-Not $bossproc) -or $bossproc.HasExited) { $exitsequence.Invoke() } 81 | # Begin watching for events until boss closes 82 | Start-Job -ScriptBlock $minimizeloop -Name "mpvminloop" -ArgumentList $pipename,$bosspid 83 | while($true) { 84 | Start-Sleep 1 85 | if ($bossproc.HasExited) { $exitsequence.Invoke() } 86 | } 87 | }]]}}) 88 | end 89 | 90 | mp.add_key_binding('', 'pause-minimize', boss_key) -------------------------------------------------------------------------------- /removed_conf/scripts/blur-edges.lua: -------------------------------------------------------------------------------- 1 | local options = require 'mp.options' 2 | 3 | local opts = { 4 | blur_radius = 10, 5 | blur_power = 10, 6 | minimum_black_bar_size = 3, 7 | mode = "all", 8 | active = true, 9 | reapply_delay = 0.5, 10 | watch_later_fix = false, 11 | } 12 | options.read_options(opts) 13 | 14 | local active = opts.active 15 | local applied = false 16 | 17 | function set_lavfi_complex(filter) 18 | if not filter and mp.get_property("lavfi-complex") == "" then return end 19 | local force_window = mp.get_property("force-window") 20 | local sub = mp.get_property("sub") 21 | mp.set_property("force-window", "yes") 22 | if not filter then 23 | mp.set_property("lavfi-complex", "") 24 | mp.set_property("vid", "1") 25 | else 26 | if not opts.watch_later_fix then 27 | mp.set_property("vid", "no") 28 | end 29 | mp.set_property("lavfi-complex", filter) 30 | end 31 | mp.set_property("sub", "no") 32 | mp.set_property("force-window", force_window) 33 | mp.set_property("sub", sub) 34 | end 35 | 36 | function set_blur() 37 | if applied then return end 38 | if not mp.get_property("video-out-params") then return end 39 | local video_aspect = mp.get_property_number("video-aspect") 40 | local ww, wh = mp.get_osd_size() 41 | 42 | if math.abs(ww/wh - video_aspect) < 0.05 then return end 43 | if opts.mode == "horizontal" and ww/wh < video_aspect then return end 44 | if opts.mode == "vertical" and ww/wh > video_aspect then return end 45 | 46 | local par = mp.get_property_number("video-params/par") 47 | local height = mp.get_property_number("video-params/h") 48 | local width = mp.get_property_number("video-params/w") 49 | 50 | local split = "[vid1] split=3 [a] [v] [b]" 51 | local crop_format = "crop=%s:%s:%s:%s" 52 | 53 | local stack_direction, crop_1, crop_2, blur_size 54 | if ww/wh > video_aspect then 55 | blur_size = math.min(math.floor(((ww/wh)*height/par-width)/2), width/2) 56 | crop_1 = string.format(crop_format, blur_size, height, "0", "0") 57 | crop_2 = string.format(crop_format, blur_size, height, width - blur_size, "0") 58 | stack_direction = "h" 59 | else 60 | blur_size = math.min(math.floor(((wh/ww)*width*par-height)/2), height/2) 61 | crop_1 = string.format(crop_format, width, blur_size, "0", "0") 62 | crop_2 = string.format(crop_format, width, blur_size, "0", height - blur_size) 63 | stack_direction = "v" 64 | end 65 | if blur_size < math.max(1, opts.minimum_black_bar_size) then return end 66 | local lr = math.min(opts.blur_radius, math.floor(blur_size/2)-1) 67 | local cr = math.min(opts.blur_radius, math.floor(blur_size/4)-1) 68 | local blur = string.format("boxblur=lr=%i:lp=%i:cr=%i:cp=%i", 69 | lr, opts.blur_power, cr, opts.blur_power) 70 | 71 | zone_1 = string.format("[a] %s,%s [a_fin]", crop_1, blur) 72 | zone_2 = string.format("[b] %s,%s [b_fin]", crop_2, blur) 73 | 74 | local par_fix = "" 75 | if par ~= 1 then 76 | par_fix = ",setsar=ratio=" .. tostring(par) .. ":max=10000" 77 | end 78 | 79 | stack = string.format("[a_fin] [v] [b_fin] %sstack=3%s [vo]", stack_direction, par_fix) 80 | filter = string.format("%s;%s;%s;%s", split, zone_1, zone_2, stack) 81 | set_lavfi_complex(filter) 82 | applied = true 83 | end 84 | 85 | function unset_blur() 86 | set_lavfi_complex() 87 | applied = false 88 | end 89 | 90 | local reapplication_timer = mp.add_timeout(opts.reapply_delay, set_blur) 91 | reapplication_timer:kill() 92 | 93 | function reset_blur(k,v) 94 | unset_blur() 95 | reapplication_timer:kill() 96 | reapplication_timer:resume() 97 | end 98 | 99 | function toggle() 100 | if active then 101 | active = false 102 | unset_blur() 103 | mp.unobserve_property(reset_blur) 104 | else 105 | active = true 106 | set_blur() 107 | local properties = { "osd-width", "osd-height", "path" } 108 | for _, p in ipairs(properties) do 109 | mp.observe_property(p, "native", reset_blur) 110 | end 111 | end 112 | end 113 | 114 | if active then 115 | active = false 116 | toggle() 117 | end 118 | 119 | mp.add_key_binding(b, "toggle-blur", toggle) 120 | mp.add_key_binding(B, "set-blur", set_blur) 121 | mp.add_key_binding(b, "unset-blur", unset_blur) -------------------------------------------------------------------------------- /removed_conf/scripts/seek-to.lua: -------------------------------------------------------------------------------- 1 | local assdraw = require 'mp.assdraw' 2 | local active = false 3 | local cursor_position = 1 4 | local time_scale = {60*60*10, 60*60, 60*10, 60, 10, 1, 0.1, 0.01, 0.001} 5 | 6 | local ass_begin = mp.get_property("osd-ass-cc/0") 7 | local ass_end = mp.get_property("osd-ass-cc/1") 8 | 9 | local history = { {} } 10 | for i = 1, 9 do 11 | history[1][i] = 0 12 | end 13 | local history_position = 1 14 | 15 | -- timer to redraw periodically the message 16 | -- to avoid leaving bindings when the seeker disappears for whatever reason 17 | -- pretty hacky tbh 18 | local timer = nil 19 | local timer_duration = 3 20 | 21 | function show_seeker() 22 | local prepend_char = {'','',':','',':','','.','',''} 23 | local str = '' 24 | for i = 1, 9 do 25 | str = str .. prepend_char[i] 26 | if i == cursor_position then 27 | str = str .. '{\\b1}' .. history[history_position][i] .. '{\\r}' 28 | else 29 | str = str .. history[history_position][i] 30 | end 31 | end 32 | mp.osd_message("Seek to: " .. ass_begin .. str .. ass_end, timer_duration) 33 | end 34 | 35 | function copy_history_to_last() 36 | if history_position ~= #history then 37 | for i = 1, 9 do 38 | history[#history][i] = history[history_position][i] 39 | end 40 | history_position = #history 41 | end 42 | end 43 | 44 | function change_number(i) 45 | -- can't set above 60 minutes or seconds 46 | if (cursor_position == 3 or cursor_position == 5) and i >= 6 then 47 | return 48 | end 49 | if history[history_position][cursor_position] ~= i then 50 | copy_history_to_last() 51 | history[#history][cursor_position] = i 52 | end 53 | shift_cursor(false) 54 | end 55 | 56 | function shift_cursor(left) 57 | if left then 58 | cursor_position = math.max(1, cursor_position - 1) 59 | else 60 | cursor_position = math.min(cursor_position + 1, 9) 61 | end 62 | end 63 | 64 | function current_time_as_sec(time) 65 | local sec = 0 66 | for i = 1, 9 do 67 | sec = sec + time_scale[i] * time[i] 68 | end 69 | return sec 70 | end 71 | 72 | function time_equal(lhs, rhs) 73 | for i = 1, 9 do 74 | if lhs[i] ~= rhs[i] then 75 | return false 76 | end 77 | end 78 | return true 79 | end 80 | 81 | function seek_to() 82 | copy_history_to_last() 83 | mp.commandv("osd-bar", "seek", current_time_as_sec(history[history_position]), "absolute") 84 | --deduplicate consecutive timestamps 85 | if #history == 1 or not time_equal(history[history_position], history[#history - 1]) then 86 | history[#history + 1] = {} 87 | history_position = #history 88 | end 89 | for i = 1, 9 do 90 | history[#history][i] = 0 91 | end 92 | end 93 | 94 | function backspace() 95 | if cursor_position ~= 9 or current_time[9] == 0 then 96 | shift_cursor(true) 97 | end 98 | if history[history_position][cursor_position] ~= 0 then 99 | copy_history_to_last() 100 | history[#history][cursor_position] = 0 101 | end 102 | end 103 | 104 | function history_move(up) 105 | if up then 106 | history_position = math.max(1, history_position - 1) 107 | else 108 | history_position = math.min(history_position + 1, #history) 109 | end 110 | end 111 | 112 | local key_mappings = { 113 | LEFT = function() shift_cursor(true) show_seeker() end, 114 | RIGHT = function() shift_cursor(false) show_seeker() end, 115 | UP = function() history_move(true) show_seeker() end, 116 | DOWN = function() history_move(false) show_seeker() end, 117 | BS = function() backspace() show_seeker() end, 118 | ESC = function() set_inactive() end, 119 | ENTER = function() seek_to() set_inactive() end 120 | } 121 | for i = 0, 9 do 122 | local func = function() change_number(i) show_seeker() end 123 | key_mappings[string.format("KP%d", i)] = func 124 | key_mappings[string.format("%d", i)] = func 125 | end 126 | 127 | function set_active() 128 | if not mp.get_property("seekable") then return end 129 | -- find duration of the video and set cursor position accordingly 130 | local duration = mp.get_property_number("duration") 131 | if duration ~= nil then 132 | for i = 1, 9 do 133 | if duration > time_scale[i] then 134 | cursor_position = i 135 | break 136 | end 137 | end 138 | end 139 | for key, func in pairs(key_mappings) do 140 | mp.add_forced_key_binding(key, "seek-to-"..key, func) 141 | end 142 | show_seeker() 143 | timer = mp.add_periodic_timer(timer_duration, show_seeker) 144 | active = true 145 | end 146 | 147 | function set_inactive() 148 | mp.osd_message("") 149 | for key, _ in pairs(key_mappings) do 150 | mp.remove_key_binding("seek-to-"..key) 151 | end 152 | timer:kill() 153 | active = false 154 | end 155 | 156 | mp.add_key_binding(g, "toggle-seeker", function() if active then set_inactive() else set_active() end end) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ----------------------------------- 2 | # mpv.snad for [Windows](https://github.com/thisisshihan/mpv.snad) / Linux / Mac 3 | _[mpv](https://mpv.io/) a free, open source, and cross-platform media player._ 4 | _(This repository contain only stable version of windows)_ 5 | 6 | ![https://mpv.io/](https://github.com/thisisshihan/screenshots/blob/master/mpv.icon256.png) 7 | 8 | ## About mpv.snad: 9 | _[mpv.snad](https://github.com/thisisshihan/mpv.snad)_ is a player which configured _[mpv](https://mpv.io/) player_ 10 | which is based on most known as _[mplayer](http://www.mplayerhq.hu)_ to optimize your video experience with most useful featuers. (see complete _[key gide](https://github.com/thisisshihan/mpv-player-config-snad/blob/mpv-config-snad-windows-ubuntu-linux-macos/KEY.md)_) 11 | 12 | #### Download Latest Windows Version: 13 | * Download the latest version from sourceforge.net [mpv.snad](https://sourceforge.net/projects/mpv-snad/files/) (this file contain all the config files) 14 | * _(AMD FSR and NVIDIA Image Scaling added (CTRL+A/N/Z) added to v35.1 +)_ 15 | 16 | #### How to install: 17 | * Extract the files. 18 | * Move the folder to required destination. 19 | * Go to **_`.../installer`_** folder 20 | * Run **_`mpv-install.bat`_** as admin 21 | 22 | #### Other Downloads 23 | * Windows / ubuntu / linux / macos / Android stable cahnnel official: [mpv.io](http://mpv.io/installation) 24 | * Windows beta channel official: [sourceforge.net](https://sourceforge.net/projects/mpv-player-windows/files) 25 | * Android stable official: [play.google.com](https://play.google.com/store/apps/details?id=is.xyz.mpv&hl=en) 26 | * Android test builds official: [github.com](https://github.com/mpv-android/mpv-android/releases) 27 | * Config files by snad for Windows / ubuntu / linux / macos: [mpv.snad](https://goo.gl/7Mphpk) 28 | 29 | #### Config For Windows (not required if you download the player from this repository): 30 | * Download [_All Settings From Here_](https://goo.gl/7Mphpk) and extract them to a folder. 31 | * copy / overwrite extracted files to **_`...AppData\Roaming\mpv`_**
_or_ 32 | * create a folder as **_`portable_config`_** in the folder where mpv.exe exist and, 33 | * copy extracted files to **_`...portable_config`_** 34 | 35 | #### Config For Linux: 36 | * Download [_All Settings From Here_](https://goo.gl/7Mphpk) and extract them to a folder. 37 | * copy / overwrite extracted files to **_`...etc/mpv`_** _(you need root access to this folder)_ 38 | 39 | #### **Basic key guide -->** [key-guide](https://github.com/thisisshihan/mpv-player-config-snad/blob/mpv-config-snad-windows-ubuntu-linux-macos/KEY_basic.md) 40 | #### **A Complete key guide -->** [key-guide](https://github.com/thisisshihan/mpv-player-config-snad/blob/mpv-config-snad-windows-ubuntu-linux-macos/KEY.md) 41 | ------------------------------------- 42 | **Simple Interface**
43 | ![s2](https://github.com/thisisshihan/screenshots/blob/master/mpv.interface.png) 44 | ## 45 | **Touchpad Gesture**
46 | ![s2](https://github.com/thisisshihan/screenshots/blob/master/touchpadGesture2.png) 47 | ## 48 | **Advanced Playlist Manager**
49 | _Show Playlist_ P / TAB
50 | _Navigate_ UP / DOWN / SPACE / < / >
_A Complete key guide -->_ [key-guide](https://github.com/thisisshihan/mpv-player-config-snad/blob/mpv-config-snad-windows-ubuntu-linux-macos/KEY.md)
51 | ![s1](https://github.com/thisisshihan/screenshots/blob/master/mpv.adv.playlist.png) 52 | ## 53 | **Visualizer**
54 | A perfect visualizer for audios with no album-art or for Internet Radios 55 | ![s2](https://github.com/thisisshihan/screenshots/blob/master/mpv_visualizer.PNG) 56 | ## 57 | **Improved Video Filter for Best Video Experience**
58 | _Apply Video Filter_ V , CTRL + 1 -> 9
_A Complete key guide -->_ [key-guide](https://github.com/thisisshihan/mpv-player-config-snad/blob/mpv-config-snad-windows-ubuntu-linux-macos/KEY.md)
_(Pic1-without filter, Pic2-with filter)_
59 | ![s1](https://github.com/thisisshihan/screenshots/blob/master/mpv.adv.color.png) 60 | 61 | ------------------------------------- 62 | ## About MPV Player: 63 | **Overview:** 64 | > mpv is a fork of [mplayer2](http://www.mplayerhq.hu/design7/info.html) and [MPlayer](http://www.mplayerhq.hu/design7/info.html). It shares some features with the former projects while introducing many more. 65 | 66 | **Streamlined CLI options:** 67 | > MPlayer's options parser was improved to behave more like other CLI programs, and many option names and semantics were reworked to make them more intuitive and memorable. 68 | 69 | **On Screen Controller:** 70 | > While mpv has no official GUI, it has a small controller that is triggered by mouse movement. 71 | 72 | **High quality video output:** 73 | > mpv has an OpenGL based video output that is capable of many features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more. 74 | 75 | **GPU video decoding:** 76 | > mpv leverages the FFmpeg hwaccel APIs to support VDPAU, VAAPI, DXVA2, VDA and VideoToolbox video decoding acceleration. 77 | 78 | **Embeddable:** 79 | > A straightforward C API was designed from the ground up to make mpv usable as a library and facilitate easy integration into other applications. 80 | 81 | **Active development:** 82 | > mpv is under active development, focusing on code refactoring and cleanups as well as adding features. Want a feature? 83 | 84 | ------------------------------------------- 85 | -------------------------------------------------------------------------------- /removed_conf/scripts/autoload.lua.bac: -------------------------------------------------------------------------------- 1 | -- This script automatically loads playlist entries before and after the 2 | -- the currently played file. It does so by scanning the directory a file is 3 | -- located in when starting playback. It sorts the directory entries 4 | -- alphabetically, and adds entries before and after the current file to 5 | -- the internal playlist. (It stops if the it would add an already existing 6 | -- playlist entry at the same position - this makes it "stable".) 7 | -- Add at most 5000 * 2 files when starting a file (before + after). 8 | MAXENTRIES = 5000 9 | 10 | local msg = require 'mp.msg' 11 | local options = require 'mp.options' 12 | local utils = require 'mp.utils' 13 | 14 | o = { 15 | disabled = false 16 | } 17 | options.read_options(o) 18 | 19 | function Set (t) 20 | local set = {} 21 | for _, v in pairs(t) do set[v] = true end 22 | return set 23 | end 24 | 25 | EXTENSIONS = Set { 26 | 'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp', 'mov', 'f4v', 27 | 'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus', 28 | } 29 | 30 | function add_files_at(index, files) 31 | index = index - 1 32 | local oldcount = mp.get_property_number("playlist-count", 1) 33 | for i = 1, #files do 34 | mp.commandv("loadfile", files[i], "append") 35 | mp.commandv("playlist-move", oldcount + i - 1, index + i - 1) 36 | end 37 | end 38 | 39 | function get_extension(path) 40 | match = string.match(path, "%.([^%.]+)$" ) 41 | if match == nil then 42 | return "nomatch" 43 | else 44 | return match 45 | end 46 | end 47 | 48 | table.filter = function(t, iter) 49 | for i = #t, 1, -1 do 50 | if not iter(t[i]) then 51 | table.remove(t, i) 52 | end 53 | end 54 | end 55 | 56 | -- splitbynum and alnumcomp from alphanum.lua (C) Andre Bogus 57 | -- Released under the MIT License 58 | -- http://www.davekoelle.com/files/alphanum.lua 59 | 60 | -- split a string into a table of number and string values 61 | function splitbynum(s) 62 | local result = {} 63 | for x, y in (s or ""):gmatch("(%d*)(%D*)") do 64 | if x ~= "" then table.insert(result, tonumber(x)) end 65 | if y ~= "" then table.insert(result, y) end 66 | end 67 | return result 68 | end 69 | 70 | function clean_key(k) 71 | k = (' '..k..' '):gsub("%s+", " "):sub(2, -2):lower() 72 | return splitbynum(k) 73 | end 74 | 75 | -- compare two strings 76 | function alnumcomp(x, y) 77 | local xt, yt = clean_key(x), clean_key(y) 78 | for i = 1, math.min(#xt, #yt) do 79 | local xe, ye = xt[i], yt[i] 80 | if type(xe) == "string" then ye = tostring(ye) 81 | elseif type(ye) == "string" then xe = tostring(xe) end 82 | if xe ~= ye then return xe < ye end 83 | end 84 | return #xt < #yt 85 | end 86 | 87 | local autoloaded = nil 88 | 89 | function find_and_add_entries() 90 | local path = mp.get_property("path", "") 91 | local dir, filename = utils.split_path(path) 92 | msg.trace(("dir: %s, filename: %s"):format(dir, filename)) 93 | if o.disabled then 94 | msg.verbose("stopping: autoload disabled") 95 | elseif #dir == 0 then 96 | msg.verbose("stopping: not a local path") 97 | return 98 | end 99 | 100 | local pl_count = mp.get_property_number("playlist-count", 1) 101 | -- check if this is a manually made playlist 102 | if (pl_count > 1 and autoloaded == nil) or 103 | (pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil) then 104 | return 105 | else 106 | autoloaded = true 107 | end 108 | 109 | local pl = mp.get_property_native("playlist", {}) 110 | local pl_current = mp.get_property_number("playlist-pos-1", 1) 111 | msg.trace(("playlist-pos-1: %s, playlist: %s"):format(pl_current, 112 | utils.to_string(pl))) 113 | 114 | local files = utils.readdir(dir, "files") 115 | if files == nil then 116 | return 117 | end 118 | table.filter(files, function (v, k) 119 | if string.match(v, "^%.") then 120 | return false 121 | end 122 | local ext = get_extension(v) 123 | if ext == nil then 124 | return false 125 | end 126 | return EXTENSIONS[string.lower(ext)] 127 | end) 128 | table.sort(files, alnumcomp) 129 | 130 | if dir == "." then 131 | dir = "" 132 | end 133 | 134 | -- Find the current pl entry (dir+"/"+filename) in the sorted dir list 135 | local current 136 | for i = 1, #files do 137 | if files[i] == filename then 138 | current = i 139 | break 140 | end 141 | end 142 | if current == nil then 143 | return 144 | end 145 | msg.trace("current file position in files: "..current) 146 | 147 | local append = {[-1] = {}, [1] = {}} 148 | for direction = -1, 1, 2 do -- 2 iterations, with direction = -1 and +1 149 | for i = 1, MAXENTRIES do 150 | local file = files[current + i * direction] 151 | local pl_e = pl[pl_current + i * direction] 152 | if file == nil or file[1] == "." then 153 | break 154 | end 155 | 156 | local filepath = dir .. file 157 | if pl_e then 158 | -- If there's a playlist entry, and it's the same file, stop. 159 | msg.trace(pl_e.filename.." == "..filepath.." ?") 160 | if pl_e.filename == filepath then 161 | break 162 | end 163 | end 164 | 165 | if direction == -1 then 166 | if pl_current == 1 then -- never add additional entries in the middle 167 | msg.info("Prepending " .. file) 168 | table.insert(append[-1], 1, filepath) 169 | end 170 | else 171 | msg.info("Adding " .. file) 172 | table.insert(append[1], filepath) 173 | end 174 | end 175 | end 176 | 177 | add_files_at(pl_current + 1, append[1]) 178 | add_files_at(pl_current, append[-1]) 179 | end 180 | 181 | mp.register_event("start-file", find_and_add_entries) 182 | -------------------------------------------------------------------------------- /removed_conf/scripts/autoload2.lua.bac: -------------------------------------------------------------------------------- 1 | -- This script automatically loads playlist entries before and after the 2 | -- the currently played file. It does so by scanning the directory a file is 3 | -- located in when starting playback. It sorts the directory entries 4 | -- alphabetically, and adds entries before and after the current file to 5 | -- the internal playlist. (It stops if the it would add an already existing 6 | -- playlist entry at the same position - this makes it "stable".) 7 | -- Add at most 5000 * 2 files when starting a file (before + after). 8 | MAXENTRIES = 5000 9 | 10 | local msg = require 'mp.msg' 11 | local options = require 'mp.options' 12 | local utils = require 'mp.utils' 13 | 14 | o = { 15 | disabled = false 16 | } 17 | options.read_options(o) 18 | 19 | function Set (t) 20 | local set = {} 21 | for _, v in pairs(t) do set[v] = true end 22 | return set 23 | end 24 | 25 | EXTENSIONS = Set { 26 | 'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp', 'mov', 'f4v', 27 | 'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus', 28 | } 29 | 30 | function add_files_at(index, files) 31 | index = index - 1 32 | local oldcount = mp.get_property_number("playlist-count", 1) 33 | for i = 1, #files do 34 | mp.commandv("loadfile", files[i], "append") 35 | mp.commandv("playlist-move", oldcount + i - 1, index + i - 1) 36 | end 37 | end 38 | 39 | function get_extension(path) 40 | match = string.match(path, "%.([^%.]+)$" ) 41 | if match == nil then 42 | return "nomatch" 43 | else 44 | return match 45 | end 46 | end 47 | 48 | table.filter = function(t, iter) 49 | for i = #t, 1, -1 do 50 | if not iter(t[i]) then 51 | table.remove(t, i) 52 | end 53 | end 54 | end 55 | 56 | -- splitbynum and alnumcomp from alphanum.lua (C) Andre Bogus 57 | -- Released under the MIT License 58 | -- http://www.davekoelle.com/files/alphanum.lua 59 | 60 | -- split a string into a table of number and string values 61 | function splitbynum(s) 62 | local result = {} 63 | for x, y in (s or ""):gmatch("(%d*)(%D*)") do 64 | if x ~= "" then table.insert(result, tonumber(x)) end 65 | if y ~= "" then table.insert(result, y) end 66 | end 67 | return result 68 | end 69 | 70 | function clean_key(k) 71 | k = (' '..k..' '):gsub("%s+", " "):sub(2, -2):lower() 72 | return splitbynum(k) 73 | end 74 | 75 | -- compare two strings 76 | function alnumcomp(x, y) 77 | local xt, yt = clean_key(x), clean_key(y) 78 | for i = 1, math.min(#xt, #yt) do 79 | local xe, ye = xt[i], yt[i] 80 | if type(xe) == "string" then ye = tostring(ye) 81 | elseif type(ye) == "string" then xe = tostring(xe) end 82 | if xe ~= ye then return xe < ye end 83 | end 84 | return #xt < #yt 85 | end 86 | 87 | local autoloaded = nil 88 | 89 | function find_and_add_entries() 90 | local path = mp.get_property("path", "") 91 | local dir, filename = utils.split_path(path) 92 | msg.trace(("dir: %s, filename: %s"):format(dir, filename)) 93 | if o.disabled then 94 | msg.verbose("stopping: autoload disabled") 95 | elseif #dir == 0 then 96 | msg.verbose("stopping: not a local path") 97 | return 98 | end 99 | 100 | local pl_count = mp.get_property_number("playlist-count", 1) 101 | -- check if this is a manually made playlist 102 | if (pl_count > 1 and autoloaded == nil) or 103 | (pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil) then 104 | return 105 | else 106 | autoloaded = true 107 | end 108 | 109 | local pl = mp.get_property_native("playlist", {}) 110 | local pl_current = mp.get_property_number("playlist-pos-1", 1) 111 | msg.trace(("playlist-pos-1: %s, playlist: %s"):format(pl_current, 112 | utils.to_string(pl))) 113 | 114 | local files = utils.readdir(dir, "files") 115 | if files == nil then 116 | return 117 | end 118 | table.filter(files, function (v, k) 119 | if string.match(v, "^%.") then 120 | return false 121 | end 122 | local ext = get_extension(v) 123 | if ext == nil then 124 | return false 125 | end 126 | return EXTENSIONS[string.lower(ext)] 127 | end) 128 | table.sort(files, alnumcomp) 129 | 130 | if dir == "." then 131 | dir = "" 132 | end 133 | 134 | -- Find the current pl entry (dir+"/"+filename) in the sorted dir list 135 | local current 136 | for i = 1, #files do 137 | if files[i] == filename then 138 | current = i 139 | break 140 | end 141 | end 142 | if current == nil then 143 | return 144 | end 145 | msg.trace("current file position in files: "..current) 146 | 147 | local append = {[-1] = {}, [1] = {}} 148 | for direction = -1, 1, 2 do -- 2 iterations, with direction = -1 and +1 149 | for i = 1, MAXENTRIES do 150 | local file = files[current + i * direction] 151 | local pl_e = pl[pl_current + i * direction] 152 | if file == nil or file[1] == "." then 153 | break 154 | end 155 | 156 | local filepath = dir .. file 157 | if pl_e then 158 | -- If there's a playlist entry, and it's the same file, stop. 159 | msg.trace(pl_e.filename.." == "..filepath.." ?") 160 | if pl_e.filename == filepath then 161 | break 162 | end 163 | end 164 | 165 | if direction == -1 then 166 | if pl_current == 1 then -- never add additional entries in the middle 167 | msg.info("Prepending " .. file) 168 | table.insert(append[-1], 1, filepath) 169 | end 170 | else 171 | msg.info("Adding " .. file) 172 | table.insert(append[1], filepath) 173 | end 174 | end 175 | end 176 | 177 | add_files_at(pl_current + 1, append[1]) 178 | add_files_at(pl_current, append[-1]) 179 | end 180 | 181 | mp.register_event("start-file", find_and_add_entries) 182 | -------------------------------------------------------------------------------- /removed_conf/scripts/audio-balance.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | hacky port of mpv balance property to lavfi pan 3 | unlike mpv it should also change the volume to 4 | the surround and back lateral channels 5 | might be broken with "6.1" channel layout, since it can use 6 | either back or surround laterals 7 | input.conf default bindings: 8 | ) script-binding balance-to-left 9 | = script-binding balance-to-right 10 | ? script-binding reset-balance 11 | script-message 12 | # 'balance-to-left' is equivalent to "script-message -0.1" 13 | # 'balance-to-right' is equivalent to "script-message 0.1" 14 | --]] 15 | 16 | options = require 'mp.options' 17 | 18 | local opts = { 19 | forcelayout = "", 20 | -- if empty, will use the same layout as the original audio 21 | left = 0.5, 22 | right = 0.5 23 | } 24 | 25 | options.read_options(opts) 26 | 27 | local left = opts.left 28 | local right = opts.right 29 | 30 | local function add_left_channel(left_ch_name, right_ch_name) 31 | return string.format("%s=%.1f*%s+%.1f*%s", 32 | left_ch_name, 33 | math.max(0,math.min(1,left*2)), left_ch_name, 34 | math.max(0,math.min(1,(right-0.5)*2)), right_ch_name) 35 | end 36 | 37 | local function add_right_channel(left_ch_name, right_ch_name) 38 | return string.format("%s=%.1f*%s+%.1f*%s", 39 | right_ch_name, 40 | math.max(0,math.min(1,(left-0.5)*2)), left_ch_name, 41 | math.max(0,math.min(1,right*2)), right_ch_name) 42 | end 43 | 44 | local function update_filter() 45 | local graph = {} 46 | local channels = 47 | opts.forcelayout ~= "" and opts.forcelayout or 48 | mp.get_property('audio-params/hr-channels', 'stereo') 49 | if channels == "mono" then 50 | return 51 | end 52 | 53 | graph[1] = add_left_channel('FL', 'FR') 54 | graph[2] = add_right_channel('FL', 'FR') 55 | 56 | if channels == "3.0" or 57 | channels == "3.0(back)" or 58 | channels == "3.1" or 59 | channels == "5.0" or 60 | channels == "5.0(side)" or 61 | channels == "4.1" or 62 | channels == "5.1" or 63 | channels == "5.1(side)" or 64 | channels == "6.0" or 65 | channels == "6.0(front)" or 66 | channels == "hexagonal" or 67 | channels == "6.1" or 68 | channels == "7.0" or 69 | channels == "7.0(front)" or 70 | channels == "7.1" or 71 | channels == "7.1(wide)" or 72 | channels == "7.1(side-side)" or 73 | channels == "octagonal" then 74 | graph[#graph+1] = 'FC=FC' 75 | end 76 | 77 | if channels == "2.1" or 78 | channels == "3.1" or 79 | channels == "4.1" or 80 | channels == "5.1" or 81 | channels == "5.1(side)" or 82 | channels == "6.1" or 83 | channels == "6.1(front)" or 84 | channels == "7.1" or 85 | channels == "7.1(wide)" or 86 | channels == "7.1(side-side)" then 87 | graph[#graph+1] = 'LFE=LFE' 88 | end 89 | 90 | if channels == "3.0(back)" or 91 | channels == "4.0" or 92 | channels == "4.1" or 93 | channels == "6.0" or 94 | channels == "hexagonal" or 95 | channels == "6.1" or 96 | channels == "6.1(back)" or 97 | channels == "octagonal" then 98 | graph[#graph+1] = 'BC=BC' 99 | end 100 | 101 | if channels == "quad" or 102 | channels == "5.0" or 103 | channels == "5.1" or 104 | channels == "hexagonal" or 105 | channels == "6.1(back)" or 106 | channels == "7.0" or 107 | channels == "7.1" or 108 | channels == "7.1(wide)" or 109 | channels == "octagonal" then 110 | graph[#graph+1] = add_left_channel('BL', 'BR') 111 | graph[#graph+1] = add_right_channel('BL', 'BR') 112 | end 113 | 114 | if channels == "quad(side)" or 115 | channels == "5.0(side)" or 116 | channels == "5.1(side)" or 117 | channels == "hexagonal" or 118 | channels == "6.0" or 119 | channels == "6.0(front)" or 120 | channels == "6.1" or 121 | channels == "6.1(front)" or 122 | channels == "7.0" or 123 | channels == "7.0(front)" or 124 | channels == "7.1" or 125 | channels == "7.1(wide-side)" or 126 | channels == "octagonal" then 127 | graph[#graph+1] = add_left_channel('SL', 'SR') 128 | graph[#graph+1] = add_right_channel('SL', 'SR') 129 | end 130 | 131 | if channels == "6.0(front)" or 132 | channels == "6.1(front)" or 133 | channels == "7.0(front)" or 134 | channels == "7.1(wide)" or 135 | channels == "7.1(wide-side)" then 136 | graph[#graph+1] = add_left_channel('FLC', 'FRC') 137 | graph[#graph+1] = add_right_channel('FLC', 'FRC') 138 | end 139 | 140 | mp.command(string.format('no-osd af add @balance:lavfi=[pan=%s|%s]', 141 | channels, table.concat(graph, "|"))) 142 | 143 | mp.commandv('show-text', 144 | string.format('Audio Balance (pan): Left: %.0f%% Right: %.0f%%', 145 | left*100, right*100)) 146 | end 147 | 148 | local function change_balance(val) 149 | val = tonumber(val) 150 | if not val or (val > 1 or val < -1) then 151 | mp.msg.warn("Parameter should be a number between -1.0 and 1.0 (was "..val..")") 152 | return 153 | end 154 | left = math.max(0,math.min(1,left + val * -1)) 155 | right = math.max(0,math.min(1,right + val)) 156 | update_filter() 157 | end 158 | 159 | mp.register_script_message(mp.get_script_name(), change_balance) 160 | 161 | -- shift+9 and shift+0 in Portuguese layout 162 | mp.add_key_binding(")", 'balance-to-left', function() change_balance(-0.05); end, { repeatable = true }) 163 | mp.add_key_binding("=", 'balance-to-right', function() change_balance(0.05); end, { repeatable = true }) 164 | 165 | mp.add_key_binding("?", 'balance-reset', function() 166 | mp.command('no-osd af del @balance') 167 | left = 0.5 168 | right = 0.5 169 | end) -------------------------------------------------------------------------------- /removed_conf/scripts/lin.autoload2.lua: -------------------------------------------------------------------------------- 1 | -- This script automatically loads playlist entries before and after the 2 | -- the currently played file. It does so by scanning the directory a file is 3 | -- located in when starting playback. It sorts the directory entries 4 | -- alphabetically, and adds entries before and after the current file to 5 | -- the internal playlist. (It stops if the it would add an already existing 6 | -- playlist entry at the same position - this makes it "stable".) 7 | -- Add at most 5000 * 2 files when starting a file (before + after). 8 | MAXENTRIES = 5000 9 | 10 | local msg = require 'mp.msg' 11 | local options = require 'mp.options' 12 | local utils = require 'mp.utils' 13 | 14 | o = { 15 | disabled = false 16 | } 17 | options.read_options(o) 18 | 19 | function Set (t) 20 | local set = {} 21 | for _, v in pairs(t) do set[v] = true end 22 | return set 23 | end 24 | 25 | EXTENSIONS = Set { 26 | 'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp', 27 | 'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus', 28 | } 29 | 30 | function add_files_at(index, files) 31 | index = index - 1 32 | local oldcount = mp.get_property_number("playlist-count", 1) 33 | for i = 1, #files do 34 | mp.commandv("loadfile", files[i], "append") 35 | mp.commandv("playlist-move", oldcount + i - 1, index + i - 1) 36 | end 37 | end 38 | 39 | function get_extension(path) 40 | match = string.match(path, "%.([^%.]+)$" ) 41 | if match == nil then 42 | return "nomatch" 43 | else 44 | return match 45 | end 46 | end 47 | 48 | table.filter = function(t, iter) 49 | for i = #t, 1, -1 do 50 | if not iter(t[i]) then 51 | table.remove(t, i) 52 | end 53 | end 54 | end 55 | 56 | -- splitbynum and alnumcomp from alphanum.lua (C) Andre Bogus 57 | -- Released under the MIT License 58 | -- http://www.davekoelle.com/files/alphanum.lua 59 | 60 | -- split a string into a table of number and string values 61 | function splitbynum(s) 62 | local result = {} 63 | for x, y in (s or ""):gmatch("(%d*)(%D*)") do 64 | if x ~= "" then table.insert(result, tonumber(x)) end 65 | if y ~= "" then table.insert(result, y) end 66 | end 67 | return result 68 | end 69 | 70 | function clean_key(k) 71 | k = (' '..k..' '):gsub("%s+", " "):sub(2, -2):lower() 72 | return splitbynum(k) 73 | end 74 | 75 | -- compare two strings 76 | function alnumcomp(x, y) 77 | local xt, yt = clean_key(x), clean_key(y) 78 | for i = 1, math.min(#xt, #yt) do 79 | local xe, ye = xt[i], yt[i] 80 | if type(xe) == "string" then ye = tostring(ye) 81 | elseif type(ye) == "string" then xe = tostring(xe) end 82 | if xe ~= ye then return xe < ye end 83 | end 84 | return #xt < #yt 85 | end 86 | 87 | function find_and_add_entries() 88 | local path = mp.get_property("path", "") 89 | msg.debug("path: "..path) 90 | local dir, filename = utils.split_path(path) 91 | msg.debug(("dir: %s, filename: %s"):format(dir, filename)) 92 | if o.disabled then 93 | msg.verbose("stopping: autoload disabled") 94 | elseif #dir == 0 then 95 | msg.verbose("stopping: not a local path") 96 | return 97 | end 98 | local pl_count = mp.get_property_number("playlist-count", 1) 99 | if (pl_count > 1 and autoload_running == nil) or 100 | (pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil) then 101 | return 102 | elseif autoload_running then 103 | msg.verbose("stopping: previous autoload script still running") 104 | return 105 | else 106 | autoload_running = true 107 | end 108 | 109 | local pl = mp.get_property_native("playlist", {}) 110 | local pl_current = mp.get_property_number("playlist-pos", 0) + 1 111 | msg.debug(("playlist-pos-1: %s, playlist: %s"):format(pl_current, 112 | utils.to_string(pl))) 113 | 114 | local files = utils.readdir(dir, "files") 115 | if files == nil then 116 | autoload_running = false 117 | return 118 | end 119 | table.filter(files, function (v, k) 120 | if string.match(v, "^%.") then 121 | return false 122 | end 123 | local ext = get_extension(v) 124 | if ext == nil then 125 | return false 126 | end 127 | return EXTENSIONS[string.lower(ext)] 128 | end) 129 | table.sort(files, alnumcomp) 130 | 131 | if dir == "." then 132 | dir = "" 133 | end 134 | 135 | -- Find the current pl entry (dir+"/"+filename) in the sorted dir list 136 | local current 137 | for i = 1, #files do 138 | if files[i] == filename then 139 | current = i 140 | break 141 | end 142 | end 143 | if current == nil then 144 | autoload_running = false 145 | return 146 | end 147 | msg.debug("current file position in files: "..current) 148 | 149 | local append = {[-1] = {}, [1] = {}} 150 | for direction = -1, 1, 2 do -- 2 iterations, with direction = -1 and +1 151 | for i = 1, MAXENTRIES do 152 | local file = files[current + i * direction] 153 | local pl_e = pl[pl_current + i * direction] 154 | if file == nil or file[1] == "." then 155 | break 156 | end 157 | 158 | local filepath = dir .. file 159 | if pl_e then 160 | msg.debug(pl_e.filename.."=="..filepath.."?") 161 | -- If there's a playlist entry, and it's the same file, stop. 162 | if pl_e.filename == filepath then 163 | break 164 | end 165 | end 166 | 167 | if direction == -1 then 168 | if pl_current == 1 then -- never add additional entries in the middle 169 | msg.info("Prepending " .. file) 170 | table.insert(append[-1], 1, filepath) 171 | end 172 | else 173 | msg.info("Adding " .. file) 174 | table.insert(append[1], filepath) 175 | end 176 | end 177 | end 178 | 179 | add_files_at(pl_current + 1, append[1]) 180 | add_files_at(pl_current, append[-1]) 181 | autoload_running = false 182 | end 183 | 184 | mp.register_event("start-file", find_and_add_entries) 185 | -------------------------------------------------------------------------------- /removed_conf/scripts/lin.autoload1.lua: -------------------------------------------------------------------------------- 1 | -- This script automatically loads playlist entries before and after the 2 | -- the currently played file. It does so by scanning the directory a file is 3 | -- located in when starting playback. It sorts the directory entries 4 | -- alphabetically, and adds entries before and after the current file to 5 | -- the internal playlist. (It stops if the it would add an already existing 6 | -- playlist entry at the same position - this makes it "stable".) 7 | -- Add at most 5000 * 2 files when starting a file (before + after). 8 | MAXENTRIES = 5000 9 | 10 | local msg = require 'mp.msg' 11 | local options = require 'mp.options' 12 | local utils = require 'mp.utils' 13 | 14 | o = { 15 | disabled = false 16 | } 17 | options.read_options(o) 18 | 19 | function Set (t) 20 | local set = {} 21 | for _, v in pairs(t) do set[v] = true end 22 | return set 23 | end 24 | 25 | EXTENSIONS = Set { 26 | 'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp', 27 | 'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus', 28 | } 29 | 30 | function add_files_at(index, files) 31 | index = index - 1 32 | local oldcount = mp.get_property_number("playlist-count", 1) 33 | for i = 1, #files do 34 | mp.commandv("loadfile", files[i], "append") 35 | mp.commandv("playlist-move", oldcount + i - 1, index + i - 1) 36 | end 37 | end 38 | 39 | function get_extension(path) 40 | match = string.match(path, "%.([^%.]+)$" ) 41 | if match == nil then 42 | return "nomatch" 43 | else 44 | return match 45 | end 46 | end 47 | 48 | table.filter = function(t, iter) 49 | for i = #t, 1, -1 do 50 | if not iter(t[i]) then 51 | table.remove(t, i) 52 | end 53 | end 54 | end 55 | 56 | -- splitbynum and alnumcomp from alphanum.lua (C) Andre Bogus 57 | -- Released under the MIT License 58 | -- http://www.davekoelle.com/files/alphanum.lua 59 | 60 | -- split a string into a table of number and string values 61 | function splitbynum(s) 62 | local result = {} 63 | for x, y in (s or ""):gmatch("(%d*)(%D*)") do 64 | if x ~= "" then table.insert(result, tonumber(x)) end 65 | if y ~= "" then table.insert(result, y) end 66 | end 67 | return result 68 | end 69 | 70 | function clean_key(k) 71 | k = (' '..k..' '):gsub("%s+", " "):sub(2, -2):lower() 72 | return splitbynum(k) 73 | end 74 | 75 | -- compare two strings 76 | function alnumcomp(x, y) 77 | local xt, yt = clean_key(x), clean_key(y) 78 | for i = 1, math.min(#xt, #yt) do 79 | local xe, ye = xt[i], yt[i] 80 | if type(xe) == "string" then ye = tostring(ye) 81 | elseif type(ye) == "string" then xe = tostring(xe) end 82 | if xe ~= ye then return xe < ye end 83 | end 84 | return #xt < #yt 85 | end 86 | 87 | function find_and_add_entries() 88 | local path = mp.get_property("path", "") 89 | msg.debug("path: "..path) 90 | local dir, filename = utils.split_path(path) 91 | msg.debug(("dir: %s, filename: %s"):format(dir, filename)) 92 | if o.disabled then 93 | msg.verbose("stopping: autoload disabled") 94 | elseif #dir == 0 then 95 | msg.verbose("stopping: not a local path") 96 | return 97 | end 98 | local pl_count = mp.get_property_number("playlist-count", 1) 99 | if (pl_count > 1 and autoload_running == nil) or 100 | (pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil) then 101 | return 102 | -- elseif autoload_running then 103 | -- msg.verbose("stopping: previous autoload script still running") 104 | -- return 105 | else 106 | autoload_running = true 107 | end 108 | 109 | local pl = mp.get_property_native("playlist", {}) 110 | local pl_current = mp.get_property_number("playlist-pos", 0) + 1 111 | msg.debug(("playlist-pos-1: %s, playlist: %s"):format(pl_current, 112 | utils.to_string(pl))) 113 | 114 | local files = utils.readdir(dir, "files") 115 | if files == nil then 116 | -- autoload_running = false 117 | return 118 | end 119 | table.filter(files, function (v, k) 120 | if string.match(v, "^%.") then 121 | return false 122 | end 123 | local ext = get_extension(v) 124 | if ext == nil then 125 | return false 126 | end 127 | return EXTENSIONS[string.lower(ext)] 128 | end) 129 | table.sort(files, alnumcomp) 130 | 131 | if dir == "." then 132 | dir = "" 133 | end 134 | 135 | -- Find the current pl entry (dir+"/"+filename) in the sorted dir list 136 | local current 137 | for i = 1, #files do 138 | if files[i] == filename then 139 | current = i 140 | break 141 | end 142 | end 143 | if current == nil then 144 | -- autoload_running = false 145 | return 146 | end 147 | msg.debug("current file position in files: "..current) 148 | 149 | local append = {[-1] = {}, [1] = {}} 150 | for direction = -1, 1, 2 do -- 2 iterations, with direction = -1 and +1 151 | for i = 1, MAXENTRIES do 152 | local file = files[current + i * direction] 153 | local pl_e = pl[pl_current + i * direction] 154 | if file == nil or file[1] == "." then 155 | break 156 | end 157 | 158 | local filepath = dir .. file 159 | if pl_e then 160 | msg.debug(pl_e.filename.."=="..filepath.."?") 161 | -- If there's a playlist entry, and it's the same file, stop. 162 | if pl_e.filename == filepath then 163 | break 164 | end 165 | end 166 | 167 | if direction == -1 then 168 | if pl_current == 1 then -- never add additional entries in the middle 169 | msg.info("Prepending " .. file) 170 | table.insert(append[-1], 1, filepath) 171 | end 172 | else 173 | msg.info("Adding " .. file) 174 | table.insert(append[1], filepath) 175 | end 176 | end 177 | end 178 | 179 | add_files_at(pl_current + 1, append[1]) 180 | add_files_at(pl_current, append[-1]) 181 | -- autoload_running = false 182 | end 183 | 184 | mp.register_event("start-file", find_and_add_entries) 185 | -------------------------------------------------------------------------------- /removed_conf/shaders/SSimDownscaler.glsl: -------------------------------------------------------------------------------- 1 | // This library is free software; you can redistribute it and/or 2 | // modify it under the terms of the GNU Lesser General Public 3 | // License as published by the Free Software Foundation; either 4 | // version 3.0 of the License, or (at your option) any later version. 5 | // 6 | // This library is distributed in the hope that it will be useful, 7 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9 | // Lesser General Public License for more details. 10 | // 11 | // You should have received a copy of the GNU Lesser General Public 12 | // License along with this library. 13 | 14 | //!HOOK POSTKERNEL 15 | //!BIND HOOKED 16 | //!BIND PREKERNEL 17 | //!SAVE L2 18 | //!WIDTH NATIVE_CROPPED.w 19 | //!WHEN NATIVE_CROPPED.h POSTKERNEL.h > 20 | //!COMPONENTS 3 21 | //!DESC SSimDownscaler L2 pass 1 22 | 23 | #define axis 1 24 | 25 | #define offset vec2(0,0) 26 | 27 | #define MN(B,C,x) (x < 1.0 ? ((2.-1.5*B-(C))*x + (-3.+2.*B+C))*x*x + (1.-(B)/3.) : (((-(B)/6.-(C))*x + (B+5.*C))*x + (-2.*B-8.*C))*x+((4./3.)*B+4.*C)) 28 | #define Kernel(x) MN(.0, .5, abs(x)) 29 | #define taps 2.0 30 | 31 | vec4 hook() { 32 | vec2 base = PREKERNEL_pt * (PREKERNEL_pos * input_size + tex_offset); 33 | 34 | float low = ceil((PREKERNEL_pos - taps*POSTKERNEL_pt) * input_size - offset + tex_offset - 0.5)[axis]; 35 | float high = floor((PREKERNEL_pos + taps*POSTKERNEL_pt) * input_size - offset + tex_offset - 0.5)[axis]; 36 | 37 | float W = 0.0; 38 | vec4 avg = vec4(0); 39 | vec2 pos = base; 40 | 41 | for (float k = low; k <= high; k++) { 42 | pos[axis] = PREKERNEL_pt[axis] * (k - offset[axis] + 0.5); 43 | float rel = (pos[axis] - base[axis])*POSTKERNEL_size[axis]; 44 | float w = Kernel(rel); 45 | 46 | vec4 tex = textureLod(PREKERNEL_raw, pos, 0.0) * PREKERNEL_mul; 47 | avg += w * tex * tex; 48 | W += w; 49 | } 50 | avg /= W; 51 | 52 | return avg; 53 | } 54 | 55 | //!HOOK POSTKERNEL 56 | //!BIND HOOKED 57 | //!BIND L2 58 | //!SAVE L2 59 | //!WHEN NATIVE_CROPPED.w POSTKERNEL.w > 60 | //!COMPONENTS 3 61 | //!DESC SSimDownscaler L2 pass 2 62 | 63 | #define axis 0 64 | 65 | #define offset vec2(0,0) 66 | 67 | #define MN(B,C,x) (x < 1.0 ? ((2.-1.5*B-(C))*x + (-3.+2.*B+C))*x*x + (1.-(B)/3.) : (((-(B)/6.-(C))*x + (B+5.*C))*x + (-2.*B-8.*C))*x+((4./3.)*B+4.*C)) 68 | #define Kernel(x) MN(.0, .5, abs(x)) 69 | #define taps 2.0 70 | 71 | vec4 hook() { 72 | float low = ceil((L2_pos - taps*POSTKERNEL_pt) * L2_size - offset - 0.5)[axis]; 73 | float high = floor((L2_pos + taps*POSTKERNEL_pt) * L2_size - offset - 0.5)[axis]; 74 | 75 | float W = 0.0; 76 | vec4 avg = vec4(0); 77 | vec2 pos = L2_pos; 78 | 79 | for (float k = low; k <= high; k++) { 80 | pos[axis] = L2_pt[axis] * (k - offset[axis] + 0.5); 81 | float rel = (pos[axis] - L2_pos[axis])*POSTKERNEL_size[axis]; 82 | float w = Kernel(rel); 83 | 84 | avg += w * textureLod(L2_raw, pos, 0.0) * L2_mul; 85 | W += w; 86 | } 87 | avg /= W; 88 | 89 | return avg; 90 | } 91 | 92 | //!HOOK POSTKERNEL 93 | //!BIND HOOKED 94 | //!BIND L2 95 | //!SAVE MR 96 | //!WHEN NATIVE_CROPPED.h POSTKERNEL.h > 97 | //!COMPONENTS 4 98 | //!DESC SSimDownscaler mean & R 99 | 100 | #define oversharp 0.0 101 | 102 | #define sigma_nsq 10. / (255.*255.) 103 | #define locality 2.0 104 | 105 | #define offset vec2(0,0) 106 | 107 | #define Kernel(x) pow(1.0 / locality, abs(x)) 108 | #define taps 3.0 109 | 110 | #define Luma(rgb) ( dot(rgb, vec3(0.2126, 0.7152, 0.0722)) ) 111 | 112 | mat3x3 ScaleH(vec2 pos) { 113 | float low = ceil(-0.5*taps - offset)[0]; 114 | float high = floor(0.5*taps - offset)[0]; 115 | 116 | float W = 0.0; 117 | mat3x3 avg = mat3x3(0); 118 | 119 | for (float k = low; k <= high; k++) { 120 | pos[0] = HOOKED_pos[0] + HOOKED_pt[0] * k; 121 | float rel = k + offset[0]; 122 | float w = Kernel(rel); 123 | 124 | vec3 L = POSTKERNEL_tex(pos).rgb; 125 | avg += w * mat3x3(L, L*L, L2_tex(pos).rgb); 126 | W += w; 127 | } 128 | avg /= W; 129 | 130 | return avg; 131 | } 132 | 133 | vec4 hook() { 134 | vec2 pos = HOOKED_pos; 135 | 136 | float low = ceil(-0.5*taps - offset)[1]; 137 | float high = floor(0.5*taps - offset)[1]; 138 | 139 | float W = 0.0; 140 | mat3x3 avg = mat3x3(0); 141 | 142 | for (float k = low; k <= high; k++) { 143 | pos[1] = HOOKED_pos[1] + HOOKED_pt[1] * k; 144 | float rel = k + offset[1]; 145 | float w = Kernel(rel); 146 | 147 | avg += w * ScaleH(pos); 148 | W += w; 149 | } 150 | avg /= W; 151 | 152 | float Sl = Luma(max(avg[1] - avg[0] * avg[0], 0.)); 153 | float Sh = Luma(max(avg[2] - avg[0] * avg[0], 0.)); 154 | return vec4(avg[0], mix(sqrt((Sh + sigma_nsq) / (Sl + sigma_nsq)) * (1. + oversharp), clamp(Sh / Sl, 0., 1.), int(Sl > Sh))); 155 | } 156 | 157 | //!HOOK POSTKERNEL 158 | //!BIND HOOKED 159 | //!BIND MR 160 | //!WHEN NATIVE_CROPPED.h POSTKERNEL.h > 161 | //!DESC SSimDownscaler final pass 162 | 163 | #define locality 2.0 164 | 165 | #define offset vec2(0,0) 166 | 167 | #define Kernel(x) pow(1.0 / locality, abs(x)) 168 | #define taps 3.0 169 | 170 | #define Gamma(x) ( pow(x, vec3(1.0/2.0)) ) 171 | #define GammaInv(x) ( pow(clamp(x, 0.0, 1.0), vec3(2.0)) ) 172 | 173 | mat3x3 ScaleH(vec2 pos) { 174 | float low = ceil(-0.5*taps - offset)[0]; 175 | float high = floor(0.5*taps - offset)[0]; 176 | 177 | float W = 0.0; 178 | mat3x3 avg = mat3x3(0); 179 | 180 | for (float k = low; k <= high; k++) { 181 | pos[0] = HOOKED_pos[0] + HOOKED_pt[0] * k; 182 | float rel = k + offset[0]; 183 | float w = Kernel(rel); 184 | 185 | vec4 MR = MR_tex(pos); 186 | avg += w * mat3x3(MR.a*MR.rgb, MR.rgb, MR.aaa); 187 | W += w; 188 | } 189 | avg /= W; 190 | 191 | return avg; 192 | } 193 | 194 | vec4 hook() { 195 | vec2 pos = HOOKED_pos; 196 | 197 | float low = ceil(-0.5*taps - offset)[1]; 198 | float high = floor(0.5*taps - offset)[1]; 199 | 200 | float W = 0.0; 201 | mat3x3 avg = mat3x3(0); 202 | 203 | for (float k = low; k <= high; k++) { 204 | pos[1] = HOOKED_pos[1] + HOOKED_pt[1] * k; 205 | float rel = k + offset[1]; 206 | float w = Kernel(rel); 207 | 208 | avg += w * ScaleH(pos); 209 | W += w; 210 | } 211 | avg /= W; 212 | vec4 L = POSTKERNEL_texOff(0); 213 | return vec4(avg[1] + avg[2] * L.rgb - avg[0], L.a); 214 | } 215 | -------------------------------------------------------------------------------- /removed_conf/shaders/SSimSuperRes.glsl: -------------------------------------------------------------------------------- 1 | // SSimSuperRes by Shiandow 2 | // 3 | // This library is free software; you can redistribute it and/or 4 | // modify it under the terms of the GNU Lesser General Public 5 | // License as published by the Free Software Foundation; either 6 | // version 3.0 of the License, or (at your option) any later version. 7 | // 8 | // This library is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | // Lesser General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU Lesser General Public 14 | // License along with this library. 15 | 16 | //!HOOK POSTKERNEL 17 | //!BIND HOOKED 18 | //!SAVE LOWRES 19 | //!HEIGHT NATIVE_CROPPED.h 20 | //!WHEN NATIVE_CROPPED.h OUTPUT.h < 21 | //!COMPONENTS 4 22 | //!DESC SSSR Downscaling I 23 | 24 | #define axis 1 25 | 26 | #define offset vec2(0,0) 27 | 28 | #define MN(B,C,x) (x < 1.0 ? ((2.-1.5*B-(C))*x + (-3.+2.*B+C))*x*x + (1.-(B)/3.) : (((-(B)/6.-(C))*x + (B+5.*C))*x + (-2.*B-8.*C))*x+((4./3.)*B+4.*C)) 29 | #define Kernel(x) MN(0.334, 0.333, abs(x)) 30 | #define taps 2.0 31 | 32 | #define Luma(rgb) dot(rgb*rgb, vec3(0.2126, 0.7152, 0.0722)) 33 | 34 | vec4 hook() { 35 | float low = ceil((HOOKED_pos - taps/input_size) * HOOKED_size - offset - 0.5)[axis]; 36 | float high = floor((HOOKED_pos + taps/input_size) * HOOKED_size - offset - 0.5)[axis]; 37 | 38 | float W = 0.0; 39 | vec4 avg = vec4(0); 40 | vec2 pos = HOOKED_pos; 41 | vec4 tex; 42 | 43 | for (float k = low; k <= high; k++) { 44 | pos[axis] = HOOKED_pt[axis] * (k - offset[axis] + 0.5); 45 | float rel = (pos[axis] - HOOKED_pos[axis])*input_size[axis]; 46 | float w = Kernel(rel); 47 | 48 | tex.rgb = textureLod(HOOKED_raw, pos, 0.0).rgb * HOOKED_mul; 49 | tex.a = Luma(tex.rgb); 50 | avg += w * tex; 51 | W += w; 52 | } 53 | avg /= W; 54 | 55 | return vec4(avg.rgb, max(abs(avg.a - Luma(avg.rgb)), 5e-7)); 56 | } 57 | 58 | //!HOOK POSTKERNEL 59 | //!BIND LOWRES 60 | //!SAVE LOWRES 61 | //!WIDTH NATIVE_CROPPED.w 62 | //!HEIGHT NATIVE_CROPPED.h 63 | //!WHEN NATIVE_CROPPED.w OUTPUT.w < 64 | //!COMPONENTS 4 65 | //!DESC SSSR Downscaling II 66 | 67 | #define axis 0 68 | 69 | #define offset vec2(0,0) 70 | 71 | #define MN(B,C,x) (x < 1.0 ? ((2.-1.5*B-(C))*x + (-3.+2.*B+C))*x*x + (1.-(B)/3.) : (((-(B)/6.-(C))*x + (B+5.*C))*x + (-2.*B-8.*C))*x+((4./3.)*B+4.*C)) 72 | #define Kernel(x) MN(0.334, 0.333, abs(x)) 73 | #define taps 2.0 74 | 75 | #define Luma(rgb) dot(rgb*rgb, vec3(0.2126, 0.7152, 0.0722)) 76 | 77 | vec4 hook() { 78 | float low = ceil((LOWRES_pos - taps/input_size) * LOWRES_size - offset - 0.5)[axis]; 79 | float high = floor((LOWRES_pos + taps/input_size) * LOWRES_size - offset - 0.5)[axis]; 80 | 81 | float W = 0.0; 82 | vec4 avg = vec4(0); 83 | vec2 pos = LOWRES_pos; 84 | vec4 tex; 85 | 86 | for (float k = low; k <= high; k++) { 87 | pos[axis] = LOWRES_pt[axis] * (k - offset[axis] + 0.5); 88 | float rel = (pos[axis] - LOWRES_pos[axis])*input_size[axis]; 89 | float w = Kernel(rel); 90 | 91 | tex.rgb = textureLod(LOWRES_raw, pos, 0.0).rgb * LOWRES_mul; 92 | tex.a = Luma(tex.rgb); 93 | avg += w * tex; 94 | W += w; 95 | } 96 | avg /= W; 97 | 98 | return vec4(avg.rgb, max(abs(avg.a - Luma(avg.rgb)), 5e-7) + LOWRES_texOff(0).a); 99 | } 100 | 101 | //!HOOK POSTKERNEL 102 | //!BIND PREKERNEL 103 | //!BIND LOWRES 104 | //!SAVE var 105 | //!WIDTH NATIVE_CROPPED.w 106 | //!HEIGHT NATIVE_CROPPED.h 107 | //!WHEN NATIVE_CROPPED.h OUTPUT.h < 108 | //!COMPONENTS 2 109 | //!DESC SSSR var 110 | 111 | #define spread 1.0 / 4.0 112 | 113 | #define GetL(x,y) PREKERNEL_tex(PREKERNEL_pt * (PREKERNEL_pos * input_size + tex_offset + vec2(x,y))).rgb 114 | #define GetH(x,y) LOWRES_texOff(vec2(x,y)).rgb 115 | 116 | #define Luma(rgb) dot(rgb*rgb, vec3(0.2126, 0.7152, 0.0722)) 117 | #define diff(x,y) vec2(Luma((GetL(x,y) - meanL)), Luma((GetH(x,y) - meanH))) 118 | 119 | vec4 hook() { 120 | vec3 meanL = GetL(0,0); 121 | vec3 meanH = GetH(0,0); 122 | for (int X=-1; X<=1; X+=2) { 123 | meanL += GetL(X,0) * spread; 124 | meanH += GetH(X,0) * spread; 125 | } 126 | for (int Y=-1; Y<=1; Y+=2) { 127 | meanL += GetL(0,Y) * spread; 128 | meanH += GetH(0,Y) * spread; 129 | } 130 | meanL /= (1.0 + 4.0*spread); 131 | meanH /= (1.0 + 4.0*spread); 132 | 133 | vec2 var = diff(0,0); 134 | for (int X=-1; X<=1; X+=2) 135 | var += diff(X,0) * spread; 136 | 137 | for (int Y=-1; Y<=1; Y+=2) 138 | var += diff(0,Y) * spread; 139 | 140 | return vec4(max(var / (1.0 + 4.0*spread), vec2(1e-6)), 0, 0); 141 | } 142 | 143 | //!HOOK POSTKERNEL 144 | //!BIND HOOKED 145 | //!BIND PREKERNEL 146 | //!BIND LOWRES 147 | //!BIND var 148 | //!WHEN NATIVE_CROPPED.h OUTPUT.h < 149 | //!DESC SSSR final pass 150 | 151 | #define oversharp 0.5 152 | 153 | // -- Window Size -- 154 | #define taps 3.0 155 | #define even (taps - 2.0 * floor(taps / 2.0) == 0.0) 156 | #define minX int(1.0-ceil(taps/2.0)) 157 | #define maxX int(floor(taps/2.0)) 158 | 159 | #define Kernel(x) cos(acos(-1.0)*(x)/taps) // Hann kernel 160 | 161 | // -- Input processing -- 162 | #define var(x,y) var_tex(var_pt * (pos + vec2(x,y) + 0.5)).rg 163 | #define GetL(x,y) PREKERNEL_tex(PREKERNEL_pt * (pos + tex_offset + vec2(x,y) + 0.5)).rgb 164 | #define GetH(x,y) LOWRES_tex(LOWRES_pt * (pos + vec2(x,y) + 0.5)) 165 | 166 | #define Luma(rgb) dot(rgb*rgb, vec3(0.2126, 0.7152, 0.0722)) 167 | 168 | vec4 hook() { 169 | vec4 c0 = HOOKED_texOff(0); 170 | 171 | vec2 pos = HOOKED_pos * LOWRES_size - vec2(0.5); 172 | vec2 offset = pos - (even ? floor(pos) : round(pos)); 173 | pos -= offset; 174 | 175 | vec2 mVar = vec2(0.0); 176 | for (int X=-1; X<=1; X++) 177 | for (int Y=-1; Y<=1; Y++) { 178 | vec2 w = clamp(1.5 - abs(vec2(X,Y)), 0.0, 1.0); 179 | mVar += w.r * w.g * vec2(GetH(X,Y).a, 1.0); 180 | } 181 | mVar.r /= mVar.g; 182 | 183 | // Calculate faithfulness force 184 | float weightSum = 0.0; 185 | vec3 diff = vec3(0); 186 | 187 | for (int X = minX; X <= maxX; X++) 188 | for (int Y = minX; Y <= maxX; Y++) 189 | { 190 | float R = (-1.0 - oversharp) * sqrt(var(X,Y).r / (var(X,Y).g + mVar.r)); 191 | 192 | vec2 krnl = Kernel(vec2(X,Y) - offset); 193 | float weight = krnl.r * krnl.g / (Luma((c0.rgb - GetH(X,Y).rgb)) + GetH(X,Y).a); 194 | 195 | diff += weight * (GetL(X,Y) + GetH(X,Y).rgb * R + (-1.0 - R) * (c0.rgb)); 196 | weightSum += weight; 197 | } 198 | diff /= weightSum; 199 | 200 | c0.rgb = ((c0.rgb) + diff); 201 | 202 | return c0; 203 | } 204 | -------------------------------------------------------------------------------- /removed_conf/scripts/firequalizer15.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Linear Phase 15-Bands Equalizer 3 | Key: 4 | - toggle equalizer control: ctrl+e 5 | - prev/next gain control: UP / DOWN 6 | - decrease/increase gain: LEFT / RIGHT 7 | - copy gain value from prev gain control: [ 8 | - copy gain value from next gain control: ] 9 | Note that ~~/lua-settings directory should exist to save gain values. 10 | --]] 11 | 12 | local options = require "mp.options" 13 | local msg = require "mp.msg" 14 | 15 | local key_toggle_control = "ctrl+e" 16 | local key_prev_entry = "UP" 17 | local key_next_entry = "DOWN" 18 | local key_decrease = "LEFT" 19 | local key_increase = "RIGHT" 20 | local key_copy_prev = "[" 21 | local key_copy_next = "]" 22 | 23 | local control_enabled = false 24 | local num_entry = 15 25 | local selected_entry = 0 26 | local min_val = -360 27 | local max_val = 120 28 | local stale_gain_entry = "" 29 | 30 | local function eq(x) 31 | return "eq" .. x 32 | end 33 | 34 | local gain_table = { 35 | eq0 = 0, 36 | eq1 = 0, 37 | eq2 = 0, 38 | eq3 = 0, 39 | eq4 = 0, 40 | eq5 = 0, 41 | eq6 = 0, 42 | eq7 = 0, 43 | eq8 = 0, 44 | eq9 = 0, 45 | eq10 = 0, 46 | eq11 = 0, 47 | eq12 = 0, 48 | eq13 = 0, 49 | eq14 = 0 50 | } 51 | 52 | local freq_label = { 53 | eq0 = "# 0 Hz:", 54 | eq1 = "# 65 Hz:", 55 | eq2 = "# 157 Hz:", 56 | eq3 = "# 288 Hz:", 57 | eq4 = "# 472 Hz:", 58 | eq5 = "# 733 Hz:", 59 | eq6 = "# 1k1 Hz:", 60 | eq7 = "# 1k6 Hz:", 61 | eq8 = "# 2k4 Hz:", 62 | eq9 = "# 3k4 Hz:", 63 | eq10 = "# 4k9 Hz:", 64 | eq11 = "# 7k0 Hz:", 65 | eq12 = "# 10k Hz:", 66 | eq13 = "# 14k Hz:", 67 | eq14 = "# 20k Hz:" 68 | } 69 | 70 | options.read_options(gain_table) 71 | 72 | for x = 0, num_entry-1 do 73 | gain_table[eq(x)] = math.min(math.max(gain_table[eq(x)], min_val), max_val) 74 | end 75 | 76 | local function save_gain_table() 77 | local settingdir = mp.find_config_file("lua-settings") 78 | local fp = settingdir and io.open(settingdir .. "/" .. mp.get_script_name() .. ".conf", "w") 79 | if fp == nil then 80 | msg.warn("Cannot save gain table.") 81 | else 82 | for x = 0, num_entry-1 do 83 | fp:write(eq(x) .. "=" .. gain_table[eq(x)] .. "\n") 84 | end 85 | fp:close() 86 | end 87 | end 88 | 89 | local normalcolor = "ffffff" 90 | local selectedcolor = "00ffff" 91 | local fontsize = 70 92 | local fontfamily = "mono" 93 | local pdefault = "{\\fn" .. fontfamily .. "\\fscx" .. fontsize .. "\\fscy" .. fontsize .. "\\1c&" .. normalcolor .. "&}" 94 | local pselected = "{\\fn" .. fontfamily .. "\\fscx" .. fontsize .. "\\fscy" .. fontsize .. "\\1c&" .. selectedcolor .. "&}" 95 | 96 | local function gain_line(x) 97 | local val = gain_table[eq(x)] - min_val; 98 | local str = "" 99 | local x = 10 100 | while x <= val do 101 | str = str .. "=" 102 | x = x + 20 103 | end 104 | return str 105 | end 106 | 107 | local function show_osd_ass() 108 | local str = pdefault .. "Linear Phase 15-Bands Equalizer\n" 109 | for x = 0, num_entry-1 do 110 | local pval = pdefault 111 | if x == selected_entry then 112 | pval = pselected 113 | end 114 | str = str .. pval .. freq_label[eq(x)] .. string.format("%7.1f", gain_table[eq(x)]*0.1) .. " dB |" .. gain_line(x) .. "\n" 115 | end 116 | mp.set_osd_ass(0, 0, str) 117 | end 118 | 119 | local function hide_osd_ass() 120 | mp.set_osd_ass(0, 0, "{}") 121 | end 122 | 123 | local function gen_gain_entry() 124 | local str = string.format("entry(0,%.1f)", gain_table[eq(0)]*0.1) 125 | for x = 1, num_entry-1 do 126 | str = str .. string.format(";entry(%d,%.1f)", x, gain_table[eq(x)]*0.1) 127 | end 128 | return str 129 | end 130 | 131 | local function insert_filter(gain_entry) 132 | local graph = "firequalizer = " .. 133 | "wfunc = tukey:" .. 134 | "delay = 0.028:" .. 135 | "scale = linlog:" .. 136 | "zero_phase = on:" .. 137 | "gain_entry = '" .. gain_entry .. "':" .. 138 | "gain = 'cubic_interpolate(2.8853900817779269*log(f/157.48+1))'" 139 | mp.commandv("af", "add", "@" .. mp.get_script_name() .. ":lavfi=graph=[" .. graph .. "]") 140 | end 141 | 142 | local function audio_reconfig() 143 | local gain_entry = gen_gain_entry() 144 | if not (stale_gain_entry == gain_entry) then 145 | insert_filter(gain_entry) 146 | stale_gain_entry = gain_entry 147 | end 148 | end 149 | 150 | audio_reconfig() 151 | mp.register_event("playback-restart", audio_reconfig) 152 | 153 | local function send_command() 154 | mp.commandv("af-command", mp.get_script_name(), "gain_entry", gen_gain_entry()) 155 | end 156 | 157 | local function prev_entry() 158 | selected_entry = math.max(selected_entry-1, 0) 159 | show_osd_ass() 160 | end 161 | 162 | local function next_entry() 163 | selected_entry = math.min(selected_entry+1, num_entry-1) 164 | show_osd_ass() 165 | end 166 | 167 | local function decrease_gain() 168 | gain_table[eq(selected_entry)] = math.max(gain_table[eq(selected_entry)]-1, min_val) 169 | send_command() 170 | show_osd_ass() 171 | save_gain_table() 172 | end 173 | 174 | local function increase_gain() 175 | gain_table[eq(selected_entry)] = math.min(gain_table[eq(selected_entry)]+1, max_val) 176 | send_command() 177 | show_osd_ass() 178 | save_gain_table() 179 | end 180 | 181 | local function copy_prev() 182 | gain_table[eq(selected_entry)] = gain_table[eq(math.max(selected_entry-1, 0))] 183 | send_command() 184 | show_osd_ass() 185 | save_gain_table() 186 | end 187 | 188 | local function copy_next() 189 | gain_table[eq(selected_entry)] = gain_table[eq(math.min(selected_entry+1, num_entry-1))] 190 | send_command() 191 | show_osd_ass() 192 | save_gain_table() 193 | end 194 | 195 | local function binding_name(name) 196 | return mp.get_script_name() .. "-" .. name 197 | end 198 | 199 | local function toggle_control() 200 | control_enabled = not control_enabled 201 | if control_enabled then 202 | show_osd_ass() 203 | mp.add_forced_key_binding(key_prev_entry, binding_name("prev"), prev_entry, {repeatable=true}) 204 | mp.add_forced_key_binding(key_next_entry, binding_name("next"), next_entry, {repeatable=true}) 205 | mp.add_forced_key_binding(key_decrease, binding_name("decrease"), decrease_gain, {repeatable=true}) 206 | mp.add_forced_key_binding(key_increase, binding_name("increase"), increase_gain, {repeatable=true}) 207 | mp.add_forced_key_binding(key_copy_prev, binding_name("copy_prev"), copy_prev) 208 | mp.add_forced_key_binding(key_copy_next, binding_name("copy_next"), copy_next) 209 | else 210 | hide_osd_ass() 211 | mp.remove_key_binding(binding_name("prev")) 212 | mp.remove_key_binding(binding_name("next")) 213 | mp.remove_key_binding(binding_name("decrease")) 214 | mp.remove_key_binding(binding_name("increase")) 215 | mp.remove_key_binding(binding_name("copy_prev")) 216 | mp.remove_key_binding(binding_name("copy_next")) 217 | end 218 | end 219 | 220 | mp.add_forced_key_binding(key_toggle_control, binding_name("toggle_control"), toggle_control) -------------------------------------------------------------------------------- /scripts/easycrop.lua: -------------------------------------------------------------------------------- 1 | local msg = require('mp.msg') 2 | local assdraw = require('mp.assdraw') 3 | 4 | local script_name = "easycrop" 5 | 6 | -- Number of crop points currently chosen (0 to 2) 7 | local points = {} 8 | -- True if in cropping selection mode 9 | local cropping = false 10 | -- Original value of osc property 11 | local osc_prop = false 12 | 13 | -- Helper that converts two points to top-left and bottom-right 14 | local swizzle_points = function (p1, p2) 15 | if p1.x > p2.x then p1.x, p2.x = p2.x, p1.x end 16 | if p1.y > p2.y then p1.y, p2.y = p2.y, p1.y end 17 | end 18 | 19 | local clamp = function (val, min, max) 20 | assert(min <= max) 21 | if val < min then return min end 22 | if val > max then return max end 23 | return val 24 | end 25 | 26 | local video_space_from_screen_space = function (ssp) 27 | -- Video native dimensions and screen size 28 | local vid_w = mp.get_property("width") 29 | local vid_h = mp.get_property("height") 30 | local osd_w = mp.get_property("osd-width") 31 | local osd_h = mp.get_property("osd-height") 32 | 33 | -- Factor by which the video is scaled to fit the screen 34 | local scale = math.min(osd_w/vid_w, osd_h/vid_h) 35 | 36 | -- Size video takes up in screen 37 | local vid_sw, vid_sh = scale*vid_w, scale*vid_h 38 | 39 | -- Video offset within screen 40 | local off_x = math.floor((osd_w - vid_sw)/2) 41 | local off_y = math.floor((osd_h - vid_sh)/2) 42 | 43 | local vsp = {} 44 | 45 | -- Move the point to within the video 46 | vsp.x = clamp(ssp.x, off_x, off_x + vid_sw) 47 | vsp.y = clamp(ssp.y, off_y, off_y + vid_sh) 48 | 49 | -- Convert screen-space to video-space 50 | vsp.x = math.floor((vsp.x - off_x) / scale) 51 | vsp.y = math.floor((vsp.y - off_y) / scale) 52 | 53 | return vsp 54 | end 55 | 56 | local screen_space_from_video_space = function (vsp) 57 | -- Video native dimensions and screen size 58 | local vid_w = mp.get_property("width") 59 | local vid_h = mp.get_property("height") 60 | local osd_w = mp.get_property("osd-width") 61 | local osd_h = mp.get_property("osd-height") 62 | 63 | -- Factor by which the video is scaled to fit the screen 64 | local scale = math.min(osd_w/vid_w, osd_h/vid_h) 65 | 66 | -- Size video takes up in screen 67 | local vid_sw, vid_sh = scale*vid_w, scale*vid_h 68 | 69 | -- Video offset within screen 70 | local off_x = math.floor((osd_w - vid_sw)/2) 71 | local off_y = math.floor((osd_h - vid_sh)/2) 72 | 73 | local ssp = {} 74 | ssp.x = vsp.x * scale + off_x 75 | ssp.y = vsp.y * scale + off_y 76 | return ssp 77 | end 78 | 79 | -- Wrapper that converts RRGGBB / RRGGBBAA to ASS format 80 | local ass_set_color = function (idx, color) 81 | assert(color:len() == 8 or color:len() == 6) 82 | local ass = "" 83 | 84 | -- Set alpha value (if present) 85 | if color:len() == 8 then 86 | local alpha = 0xff - tonumber(color:sub(7, 8), 16) 87 | ass = ass .. string.format("\\%da&H%X&", idx, alpha) 88 | end 89 | 90 | -- Swizzle RGB to BGR and build ASS string 91 | color = color:sub(5, 6) .. color:sub(3, 4) .. color:sub(1, 2) 92 | return "{" .. ass .. string.format("\\%dc&H%s&", idx, color) .. "}" 93 | end 94 | 95 | local draw_rect = function (p1, p2) 96 | local osd_w, osd_h = mp.get_property("osd-width"), mp.get_property("osd-height") 97 | 98 | ass = assdraw.ass_new() 99 | 100 | -- Draw overlay over surrounding unselected region 101 | 102 | ass:draw_start() 103 | ass:pos(0, 0) 104 | 105 | ass:append(ass_set_color(1, "000000aa")) 106 | ass:append(ass_set_color(3, "00000000")) 107 | 108 | local l = math.min(p1.x, p2.x) 109 | local r = math.max(p1.x, p2.x) 110 | local u = math.min(p1.y, p2.y) 111 | local d = math.max(p1.y, p2.y) 112 | 113 | ass:rect_cw(0, 0, l, osd_h) 114 | ass:rect_cw(r, 0, osd_w, osd_h) 115 | ass:rect_cw(l, 0, r, u) 116 | ass:rect_cw(l, d, r, osd_h) 117 | 118 | ass:draw_stop() 119 | 120 | -- Draw border around selected region 121 | 122 | ass:new_event() 123 | ass:draw_start() 124 | ass:pos(0, 0) 125 | 126 | ass:append(ass_set_color(1, "00000000")) 127 | ass:append(ass_set_color(3, "000000ff")) 128 | ass:append("{\\bord2}") 129 | 130 | ass:rect_cw(p1.x, p1.y, p2.x, p2.y) 131 | 132 | ass:draw_stop() 133 | 134 | mp.set_osd_ass(osd_w, osd_h, ass.text) 135 | end 136 | 137 | local draw_fill = function () 138 | local osd_w, osd_h = mp.get_property("osd-width"), mp.get_property("osd-height") 139 | 140 | ass = assdraw.ass_new() 141 | ass:draw_start() 142 | ass:pos(0, 0) 143 | 144 | ass:append(ass_set_color(1, "000000aa")) 145 | ass:append(ass_set_color(3, "00000000")) 146 | ass:rect_cw(0, 0, osd_w, osd_h) 147 | 148 | ass:draw_stop() 149 | mp.set_osd_ass(osd_w, osd_h, ass.text) 150 | end 151 | 152 | local draw_clear = function () 153 | local osd_w, osd_h = mp.get_property("osd-width"), mp.get_property("osd-height") 154 | mp.set_osd_ass(osd_w, osd_h, "") 155 | end 156 | 157 | local draw_cropper = function () 158 | if #points == 1 then 159 | local p1 = screen_space_from_video_space(points[1]) 160 | local p2 = {} 161 | p2.x, p2.y = mp.get_mouse_pos() 162 | draw_rect(p1, p2) 163 | end 164 | end 165 | 166 | local uncrop = function () 167 | mp.command("no-osd vf del @" .. script_name .. ":crop") 168 | end 169 | 170 | local crop = function(p1, p2) 171 | swizzle_points(p1, p2) 172 | 173 | local w = p2.x - p1.x 174 | local h = p2.y - p1.y 175 | local ok, err = mp.command(string.format( 176 | "no-osd vf add @%s:crop=%s:%s:%s:%s", script_name, w, h, p1.x, p1.y)) 177 | 178 | if not ok then 179 | mp.osd_message("Cropping failed") 180 | points = {} 181 | end 182 | end 183 | 184 | local easycrop_stop = function () 185 | mp.set_property("osc", osc_prop) 186 | cropping = false 187 | mp.remove_key_binding("easycrop_mouse_btn0") 188 | draw_clear() 189 | end 190 | 191 | local mouse_btn0_cb = function () 192 | if not cropping then 193 | return 194 | end 195 | 196 | local mx, my = mp.get_mouse_pos() 197 | table.insert(points, video_space_from_screen_space({ x = mx, y = my })) 198 | 199 | if #points == 2 then 200 | crop(points[1], points[2]) 201 | easycrop_stop() 202 | end 203 | end 204 | 205 | local easycrop_start = function () 206 | -- Cropping requires swdec or hwdec with copy-back 207 | local hwdec = mp.get_property("hwdec-current") 208 | if hwdec == nil then 209 | return mp.msg.error("Cannot determine current hardware decoder mode") 210 | end 211 | -- Check whitelist of ok values 212 | local valid_hwdec = { 213 | ["no"] = true, -- software decoding 214 | -- Taken from mpv manual 215 | ["videotoolbox-co"] = true, 216 | ["vaapi-copy"] = true, 217 | ["dxva2-copy"] = true, 218 | ["d3d11va-copy"] = true, 219 | ["mediacodec"] = true 220 | } 221 | if not valid_hwdec[hwdec] then 222 | return mp.osd_message("Cropping requires swdec or hwdec with copy-back (see mpv manual)") 223 | end 224 | 225 | -- Just clear the current crop and return, if there is one 226 | if #points ~= 0 then 227 | uncrop() 228 | points = {} 229 | return 230 | end 231 | 232 | -- Hide OSC 233 | osc_prop = mp.get_property("osc") 234 | mp.set_property("osc", "no") 235 | 236 | cropping = true 237 | mp.add_forced_key_binding("mouse_btn0", "easycrop_mouse_btn0", mouse_btn0_cb) 238 | draw_fill() 239 | end 240 | 241 | local easycrop_activate = function () 242 | if cropping then 243 | easycrop_stop() 244 | else 245 | easycrop_start() 246 | end 247 | end 248 | 249 | mp.add_key_binding("mouse_move", draw_cropper) 250 | mp.observe_property("osd-width", "native", draw_cropper) 251 | mp.observe_property("osd-height", "native", draw_cropper) 252 | 253 | mp.add_key_binding("k", "easycrop", easycrop_activate) 254 | mp.add_key_binding("K", "easycrop", easycrop_activate) -------------------------------------------------------------------------------- /removed_conf/input.options: -------------------------------------------------------------------------------- 1 | # mpv keybindings 2 | # 3 | # Location of user-defined bindings: ~/.config/mpv/input.conf 4 | # 5 | # Lines starting with # are comments. Use SHARP to assign the # key. 6 | # Copy this file and uncomment and edit the bindings you want to change. 7 | # 8 | # List of commands and further details: DOCS/man/input.rst 9 | # List of special keys: --input-keylist 10 | # Keybindings testing mode: mpv --input-test --force-window --idle 11 | # 12 | # Use 'ignore to unbind a key fully 13 | # 14 | # Strings need to be quoted and escaped: 15 | # KEY show-text "This is a single backslash: \\ and a quote: \" !" 16 | # 17 | # You can use modifier-key combinations like Shift+Left or Ctrl+Alt+x with 18 | # the modifiers Shift, Ctrl, Alt and Meta (may not work on the terminal). 19 | # 20 | # The default keybindings are hardcoded into the mpv binary. 21 | # You can disable them completely with: --no-input-default-bindings 22 | 23 | # Developer note: 24 | # On compilation, this file is baked into the mpv binary, and all lines are 25 | # uncommented (unless '#' is followed by a space) - thus this file defines the 26 | # default key bindings. 27 | 28 | # If this is enabled, treat all the following bindings as default. 29 | # default-bindings start 30 | 31 | # MOUSE_BTN0 ignore # don't do anything 32 | # MOUSE_BTN0_DBL cycle fullscreen # toggle fullscreen on/off 33 | # MOUSE_BTN2 cycle pause # toggle pause on/off 34 | # MOUSE_BTN3 seek 10 35 | # MOUSE_BTN4 seek -10 36 | # MOUSE_BTN5 add volume -2 37 | # MOUSE_BTN6 add volume 2 38 | 39 | # Mouse wheels, touchpad or other input devices that have axes 40 | # if the input devices supports precise scrolling it will also scale the 41 | # numeric value accordingly 42 | # AXIS_UP seek 10 43 | # AXIS_DOWN seek -10 44 | # AXIS_LEFT seek 5 45 | # AXIS_RIGHT seek -5 46 | 47 | # Seek units are in seconds, but note that these are limited by keyframes 48 | # RIGHT seek 5 49 | # LEFT seek -5 50 | # UP seek 60 51 | # DOWN seek -60 52 | # Do smaller, always exact (non-keyframe-limited), seeks with shift. 53 | # Don't show them on the OSD (no-osd). 54 | # Shift+RIGHT no-osd seek 1 exact 55 | # Shift+LEFT no-osd seek -1 exact 56 | # Shift+UP no-osd seek 5 exact 57 | # Shift+DOWN no-osd seek -5 exact 58 | # Skip to previous/next subtitle (subject to some restrictions; see manpage) 59 | # Ctrl+LEFT no-osd sub-seek -1 60 | # Ctrl+RIGHT no-osd sub-seek 1 61 | # PGUP add chapter 1 # skip to next chapter 62 | # PGDWN add chapter -1 # skip to previous chapter 63 | # Shift+PGUP seek 600 64 | # Shift+PGDWN seek -600 65 | #[ multiply speed 0.9091 # scale playback speed 66 | #] multiply speed 1.1 67 | #{ multiply speed 0.5 68 | #} multiply speed 2.0 69 | #BS set speed 1.0 # reset speed to normal 70 | #q quit 71 | #Q quit-watch-later 72 | #q {encode} quit 4 73 | #ESC set fullscreen no 74 | #ESC {encode} quit 4 75 | #p cycle pause # toggle pause/playback mode 76 | #. frame-step # advance one frame and pause 77 | #, frame-back-step # go back by one frame and pause 78 | #SPACE cycle pause 79 | #> playlist-next # skip to next file 80 | #ENTER playlist-next # skip to next file 81 | #< playlist-prev # skip to previous file 82 | #O no-osd cycle_values osd-level 3 1 # cycle through OSD mode 83 | #o show-progress 84 | #P show-progress 85 | #I show-text "${filename}" # display filename in osd 86 | #z add sub-delay -0.1 # subtract 100 ms delay from subs 87 | #x add sub-delay +0.1 # add 88 | #ctrl++ add audio-delay 0.100 # this changes audio/video sync 89 | #ctrl+- add audio-delay -0.100 90 | #9 add volume -2 91 | #/ add volume -2 92 | #0 add volume 2 93 | #* add volume 2 94 | #m cycle mute 95 | #1 add contrast -1 96 | #2 add contrast 1 97 | #3 add brightness -1 98 | #4 add brightness 1 99 | #5 add gamma -1 100 | #6 add gamma 1 101 | #7 add saturation -1 102 | #8 add saturation 1 103 | #d cycle framedrop # cycle through framedrop modes 104 | # toggle deinterlacer (automatically inserts or removes required filter) 105 | #D cycle deinterlace 106 | #r add sub-pos -1 # move subtitles up 107 | #t add sub-pos +1 # down 108 | #v cycle sub-visibility 109 | # stretch SSA/ASS subtitles with anamorphic videos to match historical 110 | #V cycle ass-vsfilter-aspect-compat 111 | # switch between applying no style overrides to SSA/ASS subtitles, and 112 | # overriding them almost completely with the normal subtitle style 113 | #u cycle-values ass-style-override "force" "no" 114 | #j cycle sub # cycle through subtitles 115 | #J cycle sub down # ...backwards 116 | #SHARP cycle audio # switch audio streams 117 | #_ cycle video 118 | #T cycle ontop # toggle video window ontop of other windows 119 | #f cycle fullscreen # toggle fullscreen 120 | #s screenshot # take a screenshot 121 | #S screenshot video # ...without subtitles 122 | #Ctrl+s screenshot window # ...with subtitles and OSD, and scaled 123 | #Alt+s screenshot each-frame # automatically screenshot every frame 124 | #w add panscan -0.1 # zoom out with -panscan 0 -fs 125 | #e add panscan +0.1 # in 126 | # cycle video Video aspects; "-1" is the container aspect 127 | #A cycle-values video-aspect "16:9" "4:3" "2.35:1" "-1" 128 | #POWER quit 129 | #PLAY cycle pause 130 | #PAUSE cycle pause 131 | #PLAYPAUSE cycle pause 132 | #STOP quit 133 | #FORWARD seek 60 134 | #REWIND seek -60 135 | #NEXT playlist-next 136 | #PREV playlist-prev 137 | #VOLUME_UP add volume 2 138 | #VOLUME_DOWN add volume -2 139 | #MUTE cycle mute 140 | #CLOSE_WIN quit 141 | #CLOSE_WIN {encode} quit 4 142 | #E cycle edition # next edition 143 | #l ab_loop # Set/clear A-B loop points 144 | #L cycle-values loop "inf" "no" # toggle infinite looping 145 | #ctrl+c quit 4 146 | 147 | # Apple Remote section 148 | #AR_PLAY cycle pause 149 | #AR_PLAY_HOLD quit 150 | #AR_CENTER cycle pause 151 | #AR_CENTER_HOLD quit 152 | #AR_NEXT seek 10 153 | #AR_NEXT_HOLD seek 120 154 | #AR_PREV seek -10 155 | #AR_PREV_HOLD seek -120 156 | #AR_MENU show-progress 157 | #AR_MENU_HOLD cycle mute 158 | #AR_VUP add volume 2 159 | #AR_VUP_HOLD add chapter 1 160 | #AR_VDOWN add volume -2 161 | #AR_VDOWN_HOLD add chapter -1 162 | 163 | # For dvdnav:// and bdnav:// 164 | 165 | # navigation controls during playback 166 | #ENTER {discnav} discnav menu # DISCNAV MENU 167 | # BS {discnav} discnav prev # DISCNAV PREVIOUS menu (in the order chapter->title->root) 168 | # navigation controls when showing menu (additionally to the controls above) 169 | #UP {discnav-menu} discnav up # DISCNAV UP 170 | #DOWN {discnav-menu} discnav down # DISCNAV DOWN 171 | #LEFT {discnav-menu} discnav left # DISCNAV LEFT 172 | #RIGHT {discnav-menu} discnav right # DISCNAV RIGHT 173 | #ENTER {discnav-menu} discnav select # DISCNAV SELECT (ok) 174 | #MOUSE_BTN0 {discnav-menu} discnav mouse 175 | #MOUSE_MOVE {discnav-menu} discnav mouse_move 176 | 177 | # For tv:// 178 | #h cycle tv-channel -1 # previous channel 179 | #k cycle tv-channel +1 # next channel 180 | 181 | # 182 | # Legacy bindings (may or may not be removed in the future) 183 | 184 | # 185 | # Not assigned by default 186 | # (not an exhaustive list of unbound commands) 187 | # 188 | 189 | # ? add sub-scale +0.1 # increase subtitle font size 190 | # ? add sub-scale -0.1 # decrease subtitle font size 191 | # ? sub-step -1 # immediately display next subtitle 192 | # ? sub-step +1 # previous 193 | # ? cycle-values window-scale 0.5 2 1 # switch between 1/2, 2x, unresized window size 194 | # ? cycle colormatrix 195 | # ? add audio-delay 0.100 # this changes audio/video sync 196 | # ? add audio-delay -0.100 197 | # ? cycle angle # switch DVD/Bluray angle 198 | # ? cycle sub-forced-only # toggle DVD forced subs 199 | # ? cycle program # cycle transport stream programs 200 | # ? stop # stop playback (quit or enter idle mode) -------------------------------------------------------------------------------- /mpv.conf: -------------------------------------------------------------------------------- 1 | # mpv configuration file by snad 2 | # https://github.com/thisisshihan/mpv-player-config-snad 3 | 4 | 5 | # player / window configuration 6 | # ----------------------------- 7 | border=yes # Border at startup (default:yes) 8 | autofit-larger=90%x82% # resize window in case it's larger than W%xH% of the screen 100%x95% 9 | autofit-smaller=65%x65% # resize window in case it's smaller 10 | geometry=50%:50% # Window geometry (default:50%:50%) 11 | cursor-autohide-fs-only # don't autohide the cursor in window mode, only fullscreen 12 | input-media-keys=no # enable/disable OSX media keys 13 | cursor-autohide=5000 # autohide the curser after 1s 14 | ontop=no # always on top enable when open 15 | snap-window=yes 16 | prefetch-playlist=yes 17 | force-seekable=yes # Flag (default: no) 18 | framedrop=no 19 | # no-window-dragging # use for gestures.lua 20 | # fit-border=yes 21 | 22 | 23 | # autoload configuration 24 | # ---------------------- 25 | autoload-files=yes # Flag (default: no) 26 | directory-mode=ignore # Flag , igonre will prevent from loading directories 27 | autocreate-playlist=filter # Flag 28 | directory-filter-types=video,audio # Flag 29 | # video-exts=3g2,3gp,avi,flv,m2ts,m4v,mj2,mkv,mov,mp4,mpeg,mpg,ogv,rmvb,webm,wmv,y4m 30 | # audio-exts=aiff,ape,au,flac,m4a,mka,mp3,oga,ogg,ogm,opus,wav,wma 31 | # image-exts=avif,bmp,gif,j2k,jp2,jpeg,jpg,jxl,png,svg,tga,tif,tiff,webp 32 | 33 | 34 | # screensot configuration 35 | # ----------------------- 36 | screenshot-format=jpeg # screenshot format (default: jpeg) 37 | screenshot-template=mpv%n-%f # screenshot file name 38 | screenshot-jpeg-quality=90 # Set the JPEG quality level. Higher means better quality. The default is 90 <1-100> 39 | screenshot-png-compression=7 # Set the PNG quality level. Higher means better quality. The default is 7 <1-9> 40 | 41 | 42 | # cache 43 | # ----- 44 | # cache=no 45 | cache-default=8000000 # size in KB 46 | cache-backbuffer=25000 # size in KB 47 | cache-initial=0 # start playback when your cache is filled up with x kB 48 | cache-secs=7200 # how many seconds of audio/video to prefetch if the cache is active 49 | 50 | 51 | # osd configuration 52 | # ----------------- 53 | osd-level=1 # enable osd and display --osd-status-msg on interaction 54 | osd-duration=2000 # hide the osd after x ms 55 | osd-font="SamsungOne-400" # fonts directo (../mpv/fonts) 56 | osd-font-size=36 57 | osd-spacing=0.5 58 | osd-color="#FFFFFFFF" 59 | osd-border-color="#80262626" 60 | osd-border-size=2.5 # Float (0 to 10) (default: 3.000000) 61 | osd-shadow-offset=1.5 62 | osd-shadow-color="#33000000" # Transparent ARGB (33:20%) hex value 63 | osd-border-color="#80262626" # Transparent ARGB (80:50%) hex value 64 | osd-blur=0 # Float (0 to 20) (default: 0.000000) Gaussian blur factor applied to the OSD font border 65 | osd-margin-x=25 66 | osd-margin-y=22 67 | osd-align-x=left #left|center|right 68 | osd-align-y=top #top|center|bottom 69 | osd-status-msg=${?playlist-pos:[${playlist-pos-1}/${playlist-count}] ${time-pos} / ${duration} ${?percent-pos:(${percent-pos}%)} #${filename} #${?frame-drop-count:${!frame-drop-count==0: Dropped: ${frame-drop-count}}}${?chapter: \n Chapter: ${chapter}} 70 | # osd-playing-msg =${?playlist-pos: [${playlist-pos-1}/${playlist-count}] ▶ ${filename} ~ [${width}x${height}] \n\n${?chapter:Chapter: ${chapter}} 71 | 72 | 73 | # osd bar configuration 74 | # --------------------- 75 | osd-bar-h=0.8 # Float (0.1 to 50) (default: 3.125000) 76 | osd-bar-w=99 # Float (1 to 100) (default: 75.000000) 77 | osd-bar-align-x=0 # Float (-1 to 1) (default: 0.000000) 78 | osd-bar-align-y=-0.988 # Float (-1 to 1) (default: 0.500000) 79 | osd-bar-border-size=0.5 # Float (0 to 10) (default: 3.000000) 80 | osd-scale-by-window=no # Flag (default: yes) 81 | 82 | 83 | # osc configuration 84 | # ----------------- 85 | osc=yes 86 | 87 | 88 | # sub configuration 89 | # ----------------- 90 | slang=eng,spn # automatically select these subtitles (decreasing priority) 91 | sub=yes # enable subtitle when open 92 | sub-font="SamsungOne-400" # fonts directo (../mpv/fonts) 93 | sub-font-size=36 94 | sub-color="#FFFFFFFF" 95 | sub-border-color="#80262626" 96 | sub-border-size=2 97 | sub-shadow-offset=1.5 98 | sub-shadow-color="#33000000" 99 | sub-spacing=1 100 | sub-scale-by-window=No # Flag (default: yes) 101 | sub-scale-with-window=No # Flag (default: yes) 102 | sub-auto=Fuzzy # all - external subs don't have to match the file name exactly to autoload #Fuzzy 103 | sub-file-paths-append=ass # search for external subs in these relative subdirectories 104 | sub-file-paths-append=srt 105 | sub-file-paths-append=sub 106 | sub-file-paths-append=subs 107 | sub-file-paths-append=subtitles 108 | sub-file-paths-append=english subtitles 109 | # sub-ass-style-override=force # Override ASS sub font styles 110 | # ass-force-style='Default.Bold=1,Default.FontSize=22,Shadow=1.5,BackColour=White' 111 | 112 | 113 | title=mpv.snad ~ ${?filename:[${playlist-pos-1}/${playlist-count}] ${time-pos} / ${duration} (${percent-pos}%) ~ ${filename} ~ [${width}x${height}] ~ ${file-size}}${!filename:No file.} #String (default: mpv - ${?media-title:${media-title}}${!media-title:No file.}) 114 | 115 | 116 | # audio 117 | # ----- 118 | alang=eng,spn # automatically select these audio tracks (decreasing priority) 119 | audio-file-auto=fuzzy # external audio doesn't has to match the file name exactly to autoload 120 | audio-pitch-correction=yes # automatically insert scaletempo when playing with higher speed 121 | volume-max=120 # maximum volume in %, everything above 100 results in amplification 122 | volume=50 # default volume, 100 = unchanged 123 | # af=acompressor # fix amplification noise (utilize dynamic range compression) 124 | 125 | 126 | # video Output 127 | # ------------ 128 | # Active VOs (and some other options) are set conditionally 129 | # See here for more information: https://github.com/wm4/mpv-scripts/blob/master/auto-profiles.lua 130 | # The script was slightly modified, functions from scripts/auto-profiles-functions.lua are imported 131 | 132 | # Defaults for all profiles 133 | # High quality video rendering for fast computer. 134 | # profile=gpu-hq 135 | # deband=no 136 | # vo=gl:force-pbo 137 | 138 | [high-quality] 139 | profile-desc=cond:is_desktop() and get('width', math.huge) < 3840 140 | scale=ewa_lanczossharp 141 | cscale=ewa_lanczossoft 142 | dscale=mitchell 143 | scale-antiring=0.7 144 | cscale-antiring=0.7 145 | dither-depth=auto 146 | correct-downscaling=yes 147 | sigmoid-upscaling=yes 148 | deband=yes 149 | 150 | [mid-quality] 151 | profile-desc=cond:(is_laptop() and not on_battery() and get('width', math.huge) < 1920) or (is_desktop() and get('width', math.huge) >= 3840) 152 | scale=spline36 153 | cscale=bilinear 154 | dscale=mitchell 155 | scale-antiring=1.0 156 | cscale-antiring=1.0 157 | dither-depth=auto 158 | correct-downscaling=yes 159 | sigmoid-upscaling=yes 160 | deband=yes 161 | 162 | [low-quality] 163 | profile-desc=cond:is_laptop() and (on_battery() or get('width', math.huge) >= 1920) 164 | scale=bilinear 165 | cscale=bilinear 166 | dscale=bilinear 167 | scale-antiring=0.0 168 | cscale-antiring=0.0 169 | dither-depth=no 170 | correct-downscaling=no 171 | sigmoid-upscaling=no 172 | deband=no 173 | 174 | [60FPS] 175 | profile-desc=cond:is_laptop() and get('container-fps', 0) >= 59 176 | scale=bilinear 177 | cscale=bilinear 178 | 179 | [4K] 180 | profile-desc=cond:get('width', -math.huge) >= 3840 181 | vd-lavc-threads=32 182 | 183 | [4K-inverted] 184 | profile-desc=cond:get('width', -math.huge) < 3840 185 | vd-lavc-threads=0 186 | 187 | # AMD FidelityFX FSR/CAS and NVIDIA Image Scaling 188 | # ----------------------------------------------- 189 | # profile=gpu-hq 190 | # glsl-shader="~~/shaders/FSR.glsl" 191 | # glsl-shader="~~/shaders/NVScaler.glsl" 192 | # glsl-shader="~~/shaders/NVSharpen.glsl" 193 | # glsl-shader="~~/shaders/CAS.glsl" 194 | # glsl-shader="~~/shaders/CAS-scaled.glsl" 195 | -------------------------------------------------------------------------------- /KEY.md: -------------------------------------------------------------------------------- 1 | ----------------------------------- 2 | # A Complete Guide for Keybindings of [snad.mpv](https://github.com/thisisshihan/mpv-player-config-snad/blob/mpv-config-snad-windows-ubuntu-linux-macos/README.md) 3 | 4 | ## 5 | **Touchpad Gesture**
6 | ![s2](https://github.com/thisisshihan/screenshots/blob/master/touchpadGesture2.png) 7 | 8 | ## 9 | **Keyboard Control** 10 | 11 | | | | 12 | | ---: | --- | 13 | | ESC TAB BACKSPACE
ENTER SPACE | **Keys** | 14 | | TAB | Show Playlist | 15 | | TAB | Show Playlist | 16 | | ENTER | Exit | 17 | | SHIFT + ENTER | Change Video Aspect Raion | 18 | | CTRL + ENTER | Rotate Video | 19 | | BACKSPACE ← | Reset All Settings | 20 | | ESC | Exit | 21 | | SPACE | Pause | 22 | | | | 23 | | INS HOME PAGE UP
DEL END PAGE DOWN | **Keys** | 24 | | INS | -- | 25 | | DEL | -- | 26 | | PAGE UP | -- | 27 | | PAGE DOWN | Save Video Position and Quit to Watch Later | 28 | | HOME | Jump to 0s | 29 | | END | -- | 30 | | | | 31 | |
| **Arrow Keys** | 32 | | | Foward 3s | 33 | | | Backward 3s | 34 | | | Foward 6s | 35 | | | Backward 6s | 36 | | CTRL + | Foward 30s | 37 | | CTRL + | Backward 30s | 38 | | CTRL + | Foward 60s | 39 | | CTRL + | Backward 60s | 40 | | SHIFT + | Foward 300s | 41 | | SHIFT + | Backward 300s | 42 | | SHIFT + | Foward 600s | 43 | | SHIFT + | Backward 600s | 44 | | ALT + | Sub Position Up | 45 | | ALT + | Sub Position Down | 46 | | | | 47 | | / * - +
7 8 9
4 5 6
1 2 3
0 DEC ENTER | **Keypad** | 48 | | / | Volume Down | 49 | | * | Volume Up | 50 | | - | Decrease A-V Delay | 51 | | + | Increase A-V Delay | 52 | | KP0 | Control Video Size / Position | 53 | | KP1 | Control Video Size / Position | 54 | | KP2 | Control Video Size / Position | 55 | | KP3 | Control Video Size / Position | 56 | | KP4 | Control Video Size / Position | 57 | | KP5 | Reset Video Size / Position | 58 | | KP6 | Control Video Size / Position | 59 | | KP7 | Control Video Size / Position | 60 | | KP8 | Control Video Size / Position | 61 | | KP9 | Control Video Size / Position | 62 | | DEL | Control Video Size / Position | 63 | | ENTER | Quit | 64 | | | | 65 | | CTRL + + | Increase Sub Delay | 66 | | CTRL + - | Decrease Sub Delay | 67 | | ALT + / | Sub Position Up | 68 | | ALT + * | Sub Position Down | 69 | | ALT + + | Increase Sub Size | 70 | | ALT + - | Decrease Sub Size | 71 | | ALT + ENTER | Reset A-V, Sub Delay | 72 | | | | 73 | | CTRL + KP0 | Reaet All Color (Brightness, Contr...) | 74 | | CTRL + KP1 | Decrease Brightness | 75 | | CTRL + KP2 | Increase Brightness | 76 | | CTRL + KP3 | Decrease Contrast | 77 | | CTRL + KP4 | Increase Contrast | 78 | | CTRL + KP5 | Decrease Gamma | 79 | | CTRL + KP6 | Increase Gamma | 80 | | CTRL + KP7 | Decrease Saturation | 81 | | CTRL + KP8 | Increase Saturation | 82 | | CTRL + KP9 | Decrease Hue | 83 | | CTRL + DEL | Increase Hue | 84 | | CTRL + ENTER | Rotate Video | 85 | | | | 86 | | SHIFT + KP0 | Reaet All Color (Brightness, Contr...) | 87 | | SHIFT + KP1 | Decrease Brightness | 88 | | SHIFT + KP2 | Increase Brightness | 89 | | SHIFT + KP3 | Decrease Contrast | 90 | | SHIFT + KP4 | Increase Contrast | 91 | | SHIFT + KP5 | Decrease Gamma | 92 | | SHIFT + KP6 | Increase Gamma | 93 | | SHIFT + KP7 | Decrease Saturation | 94 | | SHIFT + KP8 | Increase Saturation | 95 | | SHIFT + KP9 | Decrease Hue | 96 | | SHIFT + DEL | Increase Hue | 97 | | SHIFT + ENTER | Change Video Aspect Raion | 98 | | | | 99 | | F1 F2 F3 F4
F5 F6 F7 F8
F9 F10 F11 F12 | **Keyboard Row F1 to F12** | 100 | | F1 | Decrease Brightness | 101 | | F2 | Increase Brightness | 102 | | F3 | Decrease Contrast | 103 | | F4 | Increase Contrast | 104 | | F5 | Decrease Gamma | 105 | | F6 | Increase Gamma | 106 | | F7 | Decrease Saturation | 107 | | F8 | Increase Saturation | 108 | | F9 | Decrease Hue | 109 | | F10 | Increase Hue | 110 | | F11 | Reaet All Color (Brightness, Contr...) | 111 | | F12 | Reset All Settings | 112 | | | | 113 | | ~ 1 2 3 4 5 6 7 8 9 0 - = | **Keyboard Row** | 114 | | 1 | Reset Brightness _to change F1 , F2_ | 115 | | 2 | Reset Contrast _to change F3 , F4_ | 116 | | 3 | Reset Gamma _to change F5 , F6_ | 117 | | 4 | Reset Saturation _to change F7 , F8_ | 118 | | 5 | Reset Hue _to change F9 , F10_ | 119 | | 6 | Reaet All Color _Brightness, Contr..._ | 120 | | 7 | -- | 121 | | 8 | -- | 122 | | 9 | -- | 123 | | 0 | Reset A-V Delay | 124 | | _ | Decrease A-V Delay | 125 | | = | Increase A-V Delay | 126 | | ~ | Show Chapter List | 127 | | | | 128 | | CTRL + 1 | Apply Video Filter (1) | 129 | | CTRL + 2 | Apply Video Filter (2) | 130 | | CTRL + 3 | Apply Video Filter (3) | 131 | | CTRL + 4 | Apply Video Filter (4) | 132 | | CTRL + 5 | Apply Video Filter (5) | 133 | | CTRL + 6 | Apply Video Filter (6) | 134 | | CTRL + 7 | Apply Video Filter (7) | 135 | | CTRL + 8 | Apply Video Filter (8) | 136 | | CTRL + 9 | Remove Video Filter | 137 | | | | 138 | | Q W E R T Y U I O P { } | **Keyboard Row** | 139 | | Q | Save Video Position and Quit to Watch Later | 140 | | W | Show System Clock | 141 | | E | -- | 142 | | R | Rotate Video | 143 | | T | Enable / Disable Ontop | 144 | | Y | -- | 145 | | U | -- | 146 | | I | Show the Progress | 147 | | O | Change OSD Visible to Always / Auto | 148 | | CTRL + O | Open File | 149 | | P | Show Playlist | 150 | | CTRL + P | Save Playlist | 151 | | [ | Increase Play Speed | 152 | | ] | Decrease Play Speed | 153 | | \| | Reset Play Speed | 154 | | | | 155 | | A S D F G H J K L : " | **Keyboard Row** | 156 | | A | Change Video Aspect Raion | 157 | | CTRL + A | AMD FidelityFX FSR 1.0 | 158 | | S | Save Screenshot to Desktop | 159 | | D | Enable / Disable DeInterlace | 160 | | F | Change Full Screen / Windowed Mode | 161 | | G | Decrease Sharpness of Video | 162 | | H | Increase Sharpness of Video | 163 | | J | Change Subtitle Track | 164 | | K | Change Audio Track | 165 | | L | Enable / Disable Repeat Playlist | 166 | | : | Enable / Disable Repeat Current File | 167 | | " | Volume Up | 168 | | | | 169 | | Z X C V B N M < > ? | **Keyboard Row** | 170 | | Z | Enable / Disable Keep Aspect Ratio | 171 | | CTRL + Z | FSR/NIS Cleared | 172 | | X | Enable / Disable Auto Crop | 173 | | C | Crop | 174 | | V | Enable / Disable Color Filters | 175 | | B | Enable / Disable Border of Player in Windowed mode | 176 | | N | Enable / Disable "ASS" Sub Style | 177 | | CTRL + N | NVIDIA Image Scaling | 178 | | M | Enable / Disable Mute | 179 | | < | Jump Previous item in Playlist | 180 | | > | Jump Next item in Playlist | 181 | | / | Volume Down | 182 | 183 | # 184 | -------------------------------------------------------------------------------- /removed_conf/scripts/encode.lua: -------------------------------------------------------------------------------- 1 | local utils = require "mp.utils" 2 | local options = require "mp.options" 3 | 4 | local start_timestamp = nil 5 | local profile_start = "" 6 | 7 | -- implementation detail of the osd message 8 | local timer = nil 9 | local timer_duration = 2 10 | 11 | function append_table(lhs, rhs) 12 | for i = 1,#rhs do 13 | lhs[#lhs+1] = rhs[i] 14 | end 15 | return lhs 16 | end 17 | 18 | function file_exists(name) 19 | local f = io.open(name, "r") 20 | if f ~= nil then 21 | io.close(f) 22 | return true 23 | else 24 | return false 25 | end 26 | end 27 | 28 | function get_output_string(dir, format, input, title, from, to, profile) 29 | local res = utils.readdir(dir) 30 | if not res then 31 | return nil 32 | end 33 | local files = {} 34 | for _, f in ipairs(res) do 35 | files[f] = true 36 | end 37 | local output = format 38 | output = string.gsub(output, "$f", input) 39 | output = string.gsub(output, "$t", title) 40 | output = string.gsub(output, "$s", seconds_to_time_string(from, true)) 41 | output = string.gsub(output, "$e", seconds_to_time_string(to, true)) 42 | output = string.gsub(output, "$d", seconds_to_time_string(to-from, true)) 43 | output = string.gsub(output, "$p", profile) 44 | if not string.find(output, "$n") then 45 | if not files[output] then 46 | return output 47 | else 48 | return nil 49 | end 50 | end 51 | local i = 1 52 | while true do 53 | local potential_name = string.gsub(output, "$n", tostring(i)) 54 | if not files[potential_name] then 55 | return potential_name 56 | end 57 | i = i + 1 58 | end 59 | end 60 | 61 | function get_video_filters() 62 | local filters = {} 63 | local vf_table = mp.get_property_native("vf") 64 | for _, vf in ipairs(vf_table) do 65 | local name = vf["name"] 66 | local filter 67 | if name == "crop" then 68 | local p = vf["params"] 69 | filter = string.format("crop=%d:%d:%d:%d", p.w, p.h, p.x, p.y) 70 | elseif name == "mirror" then 71 | filter = "hflip" 72 | elseif name == "flip" then 73 | filter = "vflip" 74 | elseif name == "rotate" then 75 | local rotation = vf["params"]["angle"] 76 | -- rotate is NOT the filter we want here 77 | if rotation == "90" then 78 | filter = "transpose=clock" 79 | elseif rotation == "180" then 80 | filter = "transpose=clock,transpose=clock" 81 | elseif rotation == "270" then 82 | filter = "transpose=cclock" 83 | end 84 | end 85 | filters[#filters + 1] = filter 86 | end 87 | return filters 88 | end 89 | 90 | function get_active_tracks() 91 | local accepted = { 92 | video = true, 93 | audio = not mp.get_property_bool("mute"), 94 | sub = mp.get_property_bool("sub-visibility") 95 | } 96 | local active_tracks = {} 97 | for _, track in ipairs(mp.get_property_native("track-list")) do 98 | if track["selected"] and accepted[track["type"]] then 99 | active_tracks[#active_tracks + 1] = string.format("0:%d", track["ff-index"]) 100 | end 101 | end 102 | return active_tracks 103 | end 104 | 105 | function seconds_to_time_string(seconds, full) 106 | local ret = string.format("%02d:%02d.%03d" 107 | , math.floor(seconds / 60) % 60 108 | , math.floor(seconds) % 60 109 | , seconds * 1000 % 1000 110 | ) 111 | if full or seconds > 3600 then 112 | ret = string.format("%d:%s", math.floor(seconds / 3600), ret) 113 | end 114 | return ret 115 | end 116 | 117 | function start_encoding(input_path, from, to, settings) 118 | local args = { 119 | "ffmpeg", 120 | "-loglevel", "panic", "-hide_banner", --stfu ffmpeg 121 | "-ss", seconds_to_time_string(from, false), 122 | "-i", input_path, 123 | "-to", tostring(to-from) 124 | } 125 | 126 | -- map currently playing channels 127 | if settings.only_active_tracks then 128 | for _, t in ipairs(get_active_tracks()) do 129 | args = append_table(args, { "-map", t }) 130 | end 131 | else 132 | args = append_table(args, { "-map", "0" }) 133 | end 134 | 135 | -- apply some of the video filters currently in the chain 136 | local filters = {} 137 | if settings.preserve_filters then 138 | filters = append_table(filters, get_video_filters()) 139 | end 140 | if settings.append_filter ~= "" then 141 | filters[#filters + 1] = settings.append_filter 142 | end 143 | if #filters > 0 then 144 | args = append_table(args, { 145 | "-filter:v", table.concat(filters, ",") 146 | }) 147 | end 148 | 149 | -- split the user-passed settings on whitespace 150 | for token in string.gmatch(settings.codec, "[^%s]+") do 151 | args[#args + 1] = token 152 | end 153 | 154 | -- path of the output 155 | local output_directory = settings.output_directory 156 | if output_directory == "" then 157 | output_directory, _ = utils.split_path(input_path) 158 | else 159 | output_directory = string.gsub(output_directory, "^~", os.getenv("HOME") or "~") 160 | end 161 | local output_name = string.format("%s.%s", settings.output_format, settings.container) 162 | local input_name = mp.get_property("filename/no-ext") or "encode" 163 | local title = mp.get_property("media-title") 164 | output_name = get_output_string(output_directory, output_name, input_name, title, from, to, settings.profile) 165 | if not output_name then 166 | mp.osd_message("Invalid path " .. output_directory) 167 | return 168 | end 169 | args[#args + 1] = utils.join_path(output_directory, output_name) 170 | 171 | if settings.print then 172 | local o = "" 173 | -- fuck this is ugly 174 | for i = 1, #args do 175 | local fmt = "" 176 | if i == 1 then 177 | fmt = "%s%s" 178 | elseif i >= 2 and i <= 4 then 179 | fmt = "%s" 180 | elseif args[i-1] == "-i" or i == #args or args[i-1] == "-filter:v" then 181 | fmt = "%s \"%s\"" 182 | else 183 | fmt = "%s %s" 184 | end 185 | o = string.format(fmt, o, args[i]) 186 | end 187 | print(o) 188 | end 189 | if settings.detached then 190 | utils.subprocess_detached({ args = args }) 191 | else 192 | local res = utils.subprocess({ args = args, max_size = 0, cancellable = false }) 193 | if res.status == 0 then 194 | mp.osd_message("Finished encoding succesfully") 195 | else 196 | mp.osd_message("Failed to encode, check the log") 197 | end 198 | end 199 | end 200 | 201 | function clear_timestamp() 202 | timer:kill() 203 | start_timestamp = nil 204 | profile_start = "" 205 | mp.remove_key_binding("encode-ESC") 206 | mp.remove_key_binding("encode-ENTER") 207 | mp.osd_message("", 0) 208 | end 209 | 210 | function set_timestamp(profile) 211 | local path = mp.get_property("path") 212 | if not path then 213 | mp.osd_message("No file currently playing") 214 | return 215 | end 216 | if not mp.get_property_bool("seekable") then 217 | mp.osd_message("Cannot encode non-seekable media") 218 | return 219 | end 220 | 221 | if not start_timestamp or profile ~= profile_start then 222 | profile_start = profile 223 | start_timestamp = mp.get_property_number("time-pos") 224 | local msg = function() 225 | mp.osd_message( 226 | string.format("encode [%s]: waiting for end timestamp", profile or "default"), 227 | timer_duration 228 | ) 229 | end 230 | msg() 231 | timer = mp.add_periodic_timer(timer_duration, msg) 232 | mp.add_forced_key_binding("ESC", "encode-ESC", clear_timestamp) 233 | mp.add_forced_key_binding("ENTER", "encode-ENTER", function() set_timestamp(profile) end) 234 | else 235 | local from = start_timestamp 236 | local to = mp.get_property_number("time-pos") 237 | if to <= from then 238 | mp.osd_message("Second timestamp cannot be before the first", timer_duration) 239 | timer:kill() 240 | timer:resume() 241 | return 242 | end 243 | clear_timestamp() 244 | mp.osd_message(string.format("Encoding from %s to %s" 245 | , seconds_to_time_string(from, false) 246 | , seconds_to_time_string(to, false) 247 | ), timer_duration) 248 | -- include the current frame into the extract 249 | local fps = mp.get_property_number("container-fps") or 30 250 | to = to + 1 / fps / 2 251 | local settings = { 252 | detached = true, 253 | container = "webm", 254 | only_active_tracks = false, 255 | preserve_filters = true, 256 | append_filter = "", 257 | codec = "-an -sn -c:v libvpx -crf 10 -b:v 1000k", 258 | output_format = "$f_$n", 259 | output_directory = "", 260 | print = true, 261 | } 262 | if profile then 263 | options.read_options(settings, profile) 264 | settings.profile = profile 265 | else 266 | settings.profile = "default" 267 | end 268 | if not file_exists(path) then 269 | path = mp.get_property("stream-path") 270 | end 271 | start_encoding(path, from, to, settings) 272 | end 273 | end 274 | 275 | mp.add_key_binding(g, "set-timestamp", set_timestamp) -------------------------------------------------------------------------------- /scripts/youtube-quality.lua: -------------------------------------------------------------------------------- 1 | -- youtube-quality.lua 2 | -- 3 | -- Change youtube video quality on the fly. 4 | -- 5 | -- Diplays a menu that lets you switch to different ytdl-format settings while 6 | -- you're in the middle of a video (just like you were using the web player). 7 | -- 8 | -- Bound to ctrl-f by default. 9 | 10 | local mp = require 'mp' 11 | local utils = require 'mp.utils' 12 | local msg = require 'mp.msg' 13 | local assdraw = require 'mp.assdraw' 14 | 15 | local opts = { 16 | --key bindings 17 | toggle_menu_binding = "ctrl+v", 18 | up_binding = "UP", 19 | down_binding = "DOWN", 20 | select_binding = "ENTER", 21 | 22 | --formatting / cursors 23 | selected_and_active = "▶ - ", 24 | selected_and_inactive = "● - ", 25 | unselected_and_active = "▷ - ", 26 | unselected_and_inactive = "○ - ", 27 | 28 | --font size scales by window, if false requires larger font and padding sizes 29 | scale_playlist_by_window=false, 30 | 31 | --playlist ass style overrides inside curly brackets, \keyvalue is one field, extra \ for escape in lua 32 | --example {\\fnUbuntu\\fs10\\b0\\bord1} equals: font=Ubuntu, size=10, bold=no, border=1 33 | --read http://docs.aegisub.org/3.2/ASS_Tags/ for reference of tags 34 | --undeclared tags will use default osd settings 35 | --these styles will be used for the whole playlist. More specific styling will need to be hacked in 36 | -- 37 | --(a monospaced font is recommended but not required) 38 | style_ass_tags = "{\\fscx80\\fscy80}", 39 | 40 | --paddings for top left corner 41 | text_padding_x = 25, 42 | text_padding_y = 25, 43 | 44 | --other 45 | menu_timeout = 10, 46 | 47 | --use youtube-dl to fetch a list of available formats (overrides quality_strings) 48 | fetch_formats = true, 49 | 50 | --default menu entries 51 | quality_strings=[[ 52 | [ 53 | {"4320p" : "bestvideo[height<=?4320p]+bestaudio/best"}, 54 | {"2160p" : "bestvideo[height<=?2160]+bestaudio/best"}, 55 | {"1440p" : "bestvideo[height<=?1440]+bestaudio/best"}, 56 | {"1080p" : "bestvideo[height<=?1080]+bestaudio/best"}, 57 | {"720p" : "bestvideo[height<=?720]+bestaudio/best"}, 58 | {"480p" : "bestvideo[height<=?480]+bestaudio/best"}, 59 | {"360p" : "bestvideo[height<=?360]+bestaudio/best"}, 60 | {"240p" : "bestvideo[height<=?240]+bestaudio/best"}, 61 | {"144p" : "bestvideo[height<=?144]+bestaudio/best"} 62 | ] 63 | ]], 64 | } 65 | (require 'mp.options').read_options(opts, "youtube-quality") 66 | opts.quality_strings = utils.parse_json(opts.quality_strings) 67 | 68 | local destroyer = nil 69 | 70 | 71 | function show_menu() 72 | local selected = 1 73 | local active = 0 74 | local current_ytdl_format = mp.get_property("ytdl-format") 75 | msg.verbose("current ytdl-format: "..current_ytdl_format) 76 | local num_options = 0 77 | local options = {} 78 | 79 | 80 | if opts.fetch_formats then 81 | options, num_options = download_formats() 82 | end 83 | 84 | if next(options) == nil then 85 | for i,v in ipairs(opts.quality_strings) do 86 | num_options = num_options + 1 87 | for k,v2 in pairs(v) do 88 | options[i] = {label = k, format=v2} 89 | if v2 == current_ytdl_format then 90 | active = i 91 | selected = active 92 | end 93 | end 94 | end 95 | end 96 | 97 | --set the cursor to the currently format 98 | for i,v in ipairs(options) do 99 | if v.format == current_ytdl_format then 100 | active = i 101 | selected = active 102 | break 103 | end 104 | end 105 | 106 | function selected_move(amt) 107 | selected = selected + amt 108 | if selected < 1 then selected = num_options 109 | elseif selected > num_options then selected = 1 end 110 | timeout:kill() 111 | timeout:resume() 112 | draw_menu() 113 | end 114 | function choose_prefix(i) 115 | if i == selected and i == active then return opts.selected_and_active 116 | elseif i == selected then return opts.selected_and_inactive end 117 | 118 | if i ~= selected and i == active then return opts.unselected_and_active 119 | elseif i ~= selected then return opts.unselected_and_inactive end 120 | return "> " --shouldn't get here. 121 | end 122 | 123 | function draw_menu() 124 | local ass = assdraw.ass_new() 125 | 126 | ass:pos(opts.text_padding_x, opts.text_padding_y) 127 | ass:append(opts.style_ass_tags) 128 | 129 | for i,v in ipairs(options) do 130 | ass:append(choose_prefix(i)..v.label.."\\N") 131 | end 132 | 133 | local w, h = mp.get_osd_size() 134 | if opts.scale_playlist_by_window then w,h = 0, 0 end 135 | mp.set_osd_ass(w, h, ass.text) 136 | end 137 | 138 | function destroy() 139 | timeout:kill() 140 | mp.set_osd_ass(0,0,"") 141 | mp.remove_key_binding("move_up") 142 | mp.remove_key_binding("move_down") 143 | mp.remove_key_binding("select") 144 | mp.remove_key_binding("escape") 145 | destroyer = nil 146 | end 147 | timeout = mp.add_periodic_timer(opts.menu_timeout, destroy) 148 | destroyer = destroy 149 | 150 | mp.add_forced_key_binding(opts.up_binding, "move_up", function() selected_move(-1) end, {repeatable=true}) 151 | mp.add_forced_key_binding(opts.down_binding, "move_down", function() selected_move(1) end, {repeatable=true}) 152 | mp.add_forced_key_binding(opts.select_binding, "select", function() 153 | destroy() 154 | mp.set_property("ytdl-format", options[selected].format) 155 | reload_resume() 156 | end) 157 | mp.add_forced_key_binding(opts.toggle_menu_binding, "escape", destroy) 158 | 159 | draw_menu() 160 | return 161 | end 162 | 163 | local ytdl = { 164 | path = "youtube-dl", 165 | searched = false, 166 | blacklisted = {} 167 | } 168 | 169 | format_cache={} 170 | function download_formats() 171 | local function exec(args) 172 | local ret = utils.subprocess({args = args}) 173 | return ret.status, ret.stdout, ret 174 | end 175 | 176 | local function table_size(t) 177 | s = 0 178 | for i,v in ipairs(t) do 179 | s = s+1 180 | end 181 | return s 182 | end 183 | 184 | local url = mp.get_property("path") 185 | 186 | url = string.gsub(url, "ytdl://", "") -- Strip possible ytdl:// prefix. 187 | 188 | -- don't fetch the format list if we already have it 189 | if format_cache[url] ~= nil then 190 | local res = format_cache[url] 191 | return res, table_size(res) 192 | end 193 | mp.osd_message("fetching available formats with youtube-dl...", 60) 194 | 195 | if not (ytdl.searched) then 196 | local ytdl_mcd = mp.find_config_file("youtube-dl") 197 | if not (ytdl_mcd == nil) then 198 | msg.verbose("found youtube-dl at: " .. ytdl_mcd) 199 | ytdl.path = ytdl_mcd 200 | end 201 | ytdl.searched = true 202 | end 203 | 204 | local command = {ytdl.path, "--no-warnings", "--no-playlist", "-J"} 205 | table.insert(command, url) 206 | local es, json, result = exec(command) 207 | 208 | if (es < 0) or (json == nil) or (json == "") then 209 | mp.osd_message("fetching formats failed...", 1) 210 | msg.error("failed to get format list: " .. err) 211 | return {}, 0 212 | end 213 | 214 | local json, err = utils.parse_json(json) 215 | 216 | if (json == nil) then 217 | mp.osd_message("fetching formats failed...", 1) 218 | msg.error("failed to parse JSON data: " .. err) 219 | return {}, 0 220 | end 221 | 222 | res = {} 223 | msg.verbose("youtube-dl succeeded!") 224 | for i,v in ipairs(json.formats) do 225 | if v.vcodec ~= "none" then 226 | local fps = v.fps and v.fps.."fps" or "" 227 | local resolution = string.format("%sx%s", v.width, v.height) 228 | local l = string.format("%-9s %-5s (%-4s / %s)", resolution, fps, v.ext, v.vcodec) 229 | local f = string.format("%s+bestaudio/best", v.format_id) 230 | table.insert(res, {label=l, format=f, width=v.width }) 231 | end 232 | end 233 | 234 | table.sort(res, function(a, b) return a.width > b.width end) 235 | 236 | mp.osd_message("", 0) 237 | format_cache[url] = res 238 | return res, table_size(res) 239 | end 240 | 241 | 242 | -- register script message to show menu 243 | mp.register_script_message("toggle-quality-menu", 244 | function() 245 | if destroyer ~= nil then 246 | destroyer() 247 | else 248 | show_menu() 249 | end 250 | end) 251 | 252 | -- keybind to launch menu 253 | mp.add_key_binding(opts.toggle_menu_binding, "quality-menu", show_menu) 254 | 255 | -- special thanks to reload.lua (https://github.com/4e6/mpv-reload/) 256 | function reload_resume() 257 | local playlist_pos = mp.get_property_number("playlist-pos") 258 | local reload_duration = mp.get_property_native("duration") 259 | local time_pos = mp.get_property("time-pos") 260 | 261 | mp.set_property_number("playlist-pos", playlist_pos) 262 | 263 | -- Tries to determine live stream vs. pre-recordered VOD. VOD has non-zero 264 | -- duration property. When reloading VOD, to keep the current time position 265 | -- we should provide offset from the start. Stream doesn't have fixed start. 266 | -- Decent choice would be to reload stream from it's current 'live' positon. 267 | -- That's the reason we don't pass the offset when reloading streams. 268 | if reload_duration and reload_duration > 0 then 269 | local function seeker() 270 | mp.commandv("seek", time_pos, "absolute") 271 | mp.unregister_event(seeker) 272 | end 273 | mp.register_event("file-loaded", seeker) 274 | end 275 | end -------------------------------------------------------------------------------- /removed_conf/shaders/CAS.glsl: -------------------------------------------------------------------------------- 1 | // LICENSE 2 | // ======= 3 | // Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved. 4 | // ------- 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 6 | // files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 7 | // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 8 | // Software is furnished to do so, subject to the following conditions: 9 | // ------- 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 11 | // Software. 12 | // ------- 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 14 | // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 16 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | 18 | // FidelityFX CAS by AMD 19 | // ported to mpv by agyild 20 | 21 | // Changelog 22 | // Optimized texture lookups for OpenGL 4.0+, DirectX 10+, and OpenGL ES 3.1+ (9 -> 4). 23 | // Changed rcp + mul operations to div for better clarity when CAS_GO_SLOWER is set to 1, since the compiler should automatically 24 | // optimize those instructions anyway. 25 | // Made it directly operate on LUMA plane, since the original shader was operating on LUMA by deriving it from RGB. This should 26 | // cause a major increase in performance, especially on OpenGL 4.0+ renderers (4 texture lookups vs. 9) 27 | // Removed transparency preservation mechanism since the alpha channel is a separate source plan than LUMA 28 | // Added custom gamma curve support for relinearization 29 | // Removed final blending between the original and the sharpened pixels since it was redundant 30 | // 31 | // Notes 32 | // The filter is designed to run in linear light, and does have an optional relinerization and delinearization pass which 33 | // assumes BT.1886 content by default. Do not forget to change SOURCE_TRC and TARGET_TRC variables depending 34 | // on what kind of content the filter is running on. You might want to create seperate versions of the file with different 35 | // colorspace values, and apply them via autoprofiles. Note that running in non-linear light will result in oversharpening. 36 | // 37 | // By default the shader only runs on non-scaled content since it is designed for use without scaling, if the content is 38 | // scaled you should probably use CAS-scaled.glsl instead. However this behavior can be overriden by changing the WHEN 39 | // directives with "OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 < !" which allows it to be used as a pre-upscale sharpener. 40 | 41 | //!HOOK LUMA 42 | //!BIND HOOKED 43 | //!DESC FidelityFX Sharpening (Relinearization) 44 | //!WHEN OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 > ! OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 < ! * 45 | 46 | // User variables - Relinearization 47 | // Compatibility 48 | #define SOURCE_TRC 4 // Is needed to convert from source colorspace to linear light. 0 = None (Skip conversion), 1 = Rec709, 2 = PQ, 3 = sRGB, 4 = BT.1886, 5 = HLG, 6 = Custom 49 | #define CUSTOM_GAMMA 2.2 // Custom power gamma curve to use if and when SOURCE_TRC is 6. 50 | 51 | // Shader code 52 | 53 | float From709(float rec709) { 54 | return max(min(rec709 / float(4.5), float(0.081)), pow((rec709 + float(0.099)) / float(1.099), float(1.0 / 0.45))); 55 | } 56 | 57 | float FromPq(float pq) { 58 | float p = pow(pq, float(0.0126833)); 59 | return (pow(clamp(p - float(0.835938), 0.0, 1.0) / (float(18.8516) - float(18.6875) * p), float(6.27739))); 60 | } 61 | 62 | float FromSrgb(float srgb) { 63 | return max(min(srgb / 12.92, float(0.04045)), pow((srgb + float(0.055)) / float(1.055), float(2.4))); 64 | } 65 | 66 | float FromHlg(float hlg) { 67 | const float a = 0.17883277; 68 | const float b = 0.28466892; 69 | const float c = 0.55991073; 70 | 71 | float linear; 72 | if (hlg >= 0.0 && hlg <= 0.5) { 73 | linear = pow(hlg, 2.0) / 3.0; 74 | } else { 75 | linear = (exp((hlg - c) / a) + b) / 12.0; 76 | } 77 | 78 | return linear; 79 | } 80 | 81 | vec4 hook() { 82 | vec4 col = HOOKED_tex(HOOKED_pos); 83 | col.r = clamp(col.r, 0.0, 1.0); 84 | #if (SOURCE_TRC == 1) 85 | col.r = From709(col.r); 86 | #elif (SOURCE_TRC == 2) 87 | col.r = FromPq(col.r); 88 | #elif (SOURCE_TRC == 3) 89 | col.r = FromSrgb(col.r); 90 | #elif (SOURCE_TRC == 4) 91 | col.r = pow(col.r, float(2.4)); 92 | #elif (SOURCE_TRC == 5) 93 | col.r = FromHlg(col.r); 94 | #elif (SOURCE_TRC == 6) 95 | col.r = pow(col.r, float(CUSTOM_GAMMA)); 96 | #endif 97 | return col; 98 | } 99 | 100 | //!HOOK LUMA 101 | //!BIND HOOKED 102 | //!DESC FidelityFX Sharpening 103 | //!WHEN OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 > ! OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 < ! * 104 | 105 | // User variables 106 | // Intensity 107 | #define SHARPENING 0.0 // Adjusts the range the shader adapts to high contrast (0 is not all the way off). Higher values = more high contrast sharpening. 0.0 to 1.0. 108 | 109 | // Performance 110 | #define CAS_BETTER_DIAGONALS 1 // If set to 0, drops certain math and texture lookup operations for better performance. 0 or 1. 111 | #define CAS_GO_SLOWER 0 // If set to 1, disables the use of optimized approximate transcendental functions which might slightly increase accuracy in exchange of performance. 0 or 1. 112 | 113 | // Compatibility 114 | #define TARGET_TRC 4 // Is needed to convert from source colorspace to target colorspace. 0 = None (Skip conversion), 1 = Rec709, 2 = PQ, 3 = sRGB, 4 = BT.1886, 5 = HLG, 6 = Custom 115 | #define CUSTOM_GAMMA 2.2 // Custom power gamma curve to use if and when TARGET_TRC is 6. 116 | 117 | // Shader code 118 | 119 | float To709(float linear) { 120 | return max(min(linear * float(4.5), float(0.018)), float(1.099) * pow(linear, float(0.45)) - float(0.099)); 121 | } 122 | 123 | float ToPq(float linear) { 124 | float p = pow(linear, float(0.159302)); 125 | return pow((float(0.835938) + float(18.8516) * p) / (float(1.0) + float(18.6875) * p), float(78.8438)); 126 | } 127 | 128 | float ToSrgb(float linear) { 129 | return max(min(linear * float(12.92), float(0.0031308)), float(1.055) * pow(linear, float(0.41666)) - float(0.055)); 130 | } 131 | 132 | float ToHlg(float linear) { 133 | const float a = 0.17883277; 134 | const float b = 0.28466892; 135 | const float c = 0.55991073; 136 | 137 | float hlg; 138 | if (linear <= 1.0 / 12.0) { 139 | hlg = sqrt(3.0 * linear); 140 | } else { 141 | hlg = a * log(12.0 * linear - b) + c; 142 | } 143 | 144 | return hlg; 145 | } 146 | 147 | #if (CAS_GO_SLOWER == 0) 148 | 149 | float APrxLoSqrtF1(float a) { 150 | return uintBitsToFloat((floatBitsToUint(a) >> uint(1)) + uint(0x1fbc4639)); 151 | } 152 | 153 | float APrxLoRcpF1(float a) { 154 | return uintBitsToFloat(uint(0x7ef07ebb) - floatBitsToUint(a)); 155 | } 156 | 157 | float APrxMedRcpF1(float a) { 158 | float b = uintBitsToFloat(uint(0x7ef19fff) - floatBitsToUint(a)); 159 | return b * (-b * a + float(2.0)); 160 | } 161 | 162 | #endif 163 | 164 | vec4 hook() 165 | { 166 | // fetch a 3x3 neighborhood around the pixel 'e', 167 | // a b c 168 | // d(e)f 169 | // g h i 170 | 171 | #if (defined(HOOKED_gather) && (__VERSION__ >= 400 || (GL_ES && __VERSION__ >= 310))) 172 | vec4 efhi = HOOKED_gather(vec2(HOOKED_pos + vec2(0.5) * HOOKED_pt), 0); 173 | 174 | float e = efhi.w; 175 | float f = efhi.z; 176 | float h = efhi.x; 177 | 178 | vec3 abd = HOOKED_gather(vec2(HOOKED_pos - vec2(0.5) * HOOKED_pt), 0).wzx; 179 | float b = abd.y; 180 | float d = abd.z; 181 | 182 | #if (CAS_BETTER_DIAGONALS == 1) 183 | float a = abd.x; 184 | float i = efhi.y; 185 | #endif 186 | #else 187 | float e = HOOKED_tex(HOOKED_pos).r; 188 | float f = HOOKED_texOff(vec2(1.0, 0.0)).r; 189 | float h = HOOKED_texOff(vec2(0.0, 1.0)).r; 190 | 191 | #if (CAS_BETTER_DIAGONALS == 1) 192 | float a = HOOKED_texOff(vec2(-1.0, -1.0)).r; 193 | float i = HOOKED_texOff(vec2(1.0, 1.0)).r; 194 | #endif 195 | 196 | float b = HOOKED_texOff(vec2( 0.0, -1.0)).r; 197 | float d = HOOKED_texOff(vec2(-1.0, 0.0)).r; 198 | #endif 199 | #if (CAS_BETTER_DIAGONALS == 1) 200 | float c = HOOKED_texOff(vec2( 1.0, -1.0)).r; 201 | float g = HOOKED_texOff(vec2(-1.0, 1.0)).r; 202 | #endif 203 | 204 | // Soft min and max. 205 | // a b c b 206 | // d e f * 0.5 + d e f * 0.5 207 | // g h i h 208 | // These are 2.0x bigger (factored out the extra multiply). 209 | 210 | float mnL = min(min(min(d, e), min(f, b)), h); 211 | float mxL = max(max(max(d, e), max(f, b)), h); 212 | #if (CAS_BETTER_DIAGONALS == 1) 213 | float mnL2 = min(mnL, min(min(a, c), min(g, i))); 214 | mnL += mnL2; 215 | 216 | float mxL2 = max(mxL, max(max(a, c), max(g, i))); 217 | mxL += mxL2; 218 | #endif 219 | 220 | // Smooth minimum distance to signal limit divided by smooth max. 221 | const float bdval = bool(CAS_BETTER_DIAGONALS) ? 2.0 : 1.0; 222 | #if (CAS_GO_SLOWER == 1) 223 | float ampL = clamp(min(mnL, bdval - mxL) / mxL, 0.0, 1.0); 224 | #else 225 | float ampL = clamp(min(mnL, bdval - mxL) * APrxLoRcpF1(mxL), 0.0, 1.0); 226 | #endif 227 | 228 | // Shaping amount of sharpening. 229 | #if (CAS_GO_SLOWER == 1) 230 | ampL = sqrt(ampL); 231 | #else 232 | ampL = APrxLoSqrtF1(ampL); 233 | #endif 234 | 235 | // Filter shape. 236 | // 0 w 0 237 | // w 1 w 238 | // 0 w 0 239 | 240 | const float peak = -(mix(8.0, 5.0, clamp(SHARPENING, 0.0, 1.0))); 241 | float wL = ampL / peak; 242 | 243 | // Filter. 244 | // Using green coef only 245 | float Weight = 1.0 + 4.0 * wL; 246 | vec4 pix = vec4(0.0, 0.0, 0.0, 1.0); 247 | pix.r = ((b + d + f + h) * wL) + e; 248 | #if (CAS_GO_SLOWER == 1) 249 | pix.r /= Weight; 250 | #else 251 | pix.r *= APrxMedRcpF1(Weight); 252 | #endif 253 | pix.r = clamp(pix.r, 0.0, 1.0); 254 | 255 | #if (TARGET_TRC == 1) 256 | pix.r = To709(pix.r); 257 | #elif (TARGET_TRC == 2) 258 | pix.r = ToPq(pix.r); 259 | #elif (TARGET_TRC == 3) 260 | pix.r = ToSrgb(pix.r); 261 | #elif (TARGET_TRC == 4) 262 | pix.r = pow(pix.r, float(1.0 / 2.4)); 263 | #elif (TARGET_TRC == 5) 264 | pix.r = ToHlg(pix.r); 265 | #elif (TARGET_TRC == 6) 266 | pix.r = pow(pix.r, float(1.0 / CUSTOM_GAMMA)); 267 | #endif 268 | 269 | return pix; 270 | } -------------------------------------------------------------------------------- /removed_conf/scripts/gestures.lua: -------------------------------------------------------------------------------- 1 | -- touchscreen and mouse gestures for mpv. 2 | -- in order to use this, you have to set 3 | 4 | -- to configure create a configuration under script-opts, following keys are respected 5 | 6 | local OPTS = { 7 | -- general 8 | autostart = 0, 9 | deadzone = 50, 10 | sample_rate_ms = 48, 11 | input_delay = mp.get_property_native("input-doubleclick-time"), 12 | -- seeking / volume controller 13 | seek_volume_button = "MOUSE_BTN0", 14 | -- seeking 15 | pixels_per_second = 10, 16 | inertia_tick_ms = 16, -- lower values achieve smoother inertia at the cost of performance 17 | inertia_lower_bound_pixels = 10, 18 | -- volume 19 | volume_modifier = 50, 20 | -- speed 21 | speed_enabled = 1, 22 | speed_button = "MBTN_MID", 23 | pps = 1000, 24 | } 25 | (require 'mp.options').read_options(OPTS) 26 | 27 | local mp = require 'mp' 28 | local msg = require 'mp.msg' 29 | math.randomseed(mp.get_time()); math.random(); math.random(); math.random() 30 | 31 | local function noop() 32 | end 33 | 34 | local function if_enabled(enable) return function(wrappee) if enable then 35 | local wrap = wrappee(); 36 | return { start = function() wrap.start() end, stop = function() wrap.stop() end } 37 | else 38 | return { start = noop, stop = noop } 39 | end end end 40 | 41 | local function drag_handler(onDrag, onStart, onEnd, options) 42 | if onStart == nil then onStart = noop end 43 | if onEnd == nil then onEnd = noop end 44 | if options == nil then options = {} end 45 | if options.deadzone == nil then options.deadzone = false end 46 | if options.deadzone_reset == nil then options.deadzone_reset = "auto" end 47 | if options.tick_ms == nil then options.tick_ms = 48 end 48 | if options.button == nil then options.button = "MOUSE_BTN0" end 49 | if options.input_delay == nil then options.input_delay = mp.get_property_native("input-doubleclick-time") end 50 | 51 | local mouse = "up" 52 | local state = 0 -- 0: off, 1: drag 53 | local startx, starty = -1 54 | local startw, starth = -1; 55 | local x, y = -1 56 | 57 | local haste = false; -- whether there is a latency (for eg doubleclick) before acting on input, can be controlled externally via set_haste 58 | local active_deadzone = false; 59 | 60 | local ticker -- hoist timer 61 | local drag_start_deferrer -- hoist timer 62 | 63 | local function reset() 64 | drag_start_deferrer:kill(); 65 | ticker:kill(); 66 | if options.deadzone_reset ~= "manual" then active_deadzone = false end 67 | state = 0 68 | startx, starty = -1 69 | x, y = -1 70 | end 71 | 72 | ticker = mp.add_periodic_timer(options.tick_ms / 1000, function() 73 | if mouse == "down" and state == 1 then -- in drag 74 | local w, h = mp.get_osd_size(); 75 | if (w ~= startw or h ~= starth) then -- window size invalidated (ex fullscreen), bail 76 | reset() 77 | msg.trace("bailed") 78 | return 79 | end 80 | 81 | x, y = mp.get_mouse_pos() 82 | msg.trace("dragging") 83 | local diffx, diffy = x - startx, y - starty 84 | 85 | if not options.deadzone then 86 | onDrag(diffx, diffy) 87 | else 88 | if not active_deadzone then 89 | local abdiffx, abdiffy = math.abs(diffx), math.abs(diffy) 90 | if options.deadzone > abdiffx and options.deadzone > abdiffy then -- both inside deadzone, no active 91 | active_deadzone = false; 92 | else 93 | if abdiffy >= abdiffx then 94 | active_deadzone = "y" 95 | else 96 | active_deadzone = "x" 97 | end 98 | end 99 | end 100 | 101 | if active_deadzone then -- a deadzone has been breached, act 102 | if active_deadzone == "y" then 103 | onDrag(false, diffy) 104 | elseif active_deadzone == "x" then 105 | onDrag(diffx, false) 106 | else 107 | msg.warn("unspecified active deadzone value") 108 | end 109 | end 110 | end 111 | end 112 | end); ticker:kill() -- don't run unless initiated 113 | 114 | local function drag_start() 115 | onStart() 116 | state = 1 117 | ticker:resume() 118 | msg.trace("start drag") 119 | end 120 | drag_start_deferrer = mp.add_timeout(options.input_delay / 1000, function() 121 | drag_start() 122 | end); drag_start_deferrer:kill(); 123 | 124 | local bindingname = "a-" .. math.random(1, 1000000) .. "-b"; 125 | local binding = function(t) 126 | mouse = t.event 127 | 128 | if mouse == "down" and state == 0 then -- start dragging 129 | startx, starty = mp.get_mouse_pos() 130 | startw, starth = mp.get_osd_size() 131 | x, y = startx, starty 132 | if haste then drag_start() else drag_start_deferrer:resume() end 133 | elseif mouse == "up" then -- drag stopped 134 | local ostate = state 135 | reset() 136 | if ostate == 1 then 137 | msg.trace("end drag") 138 | onEnd() 139 | end 140 | end 141 | end 142 | 143 | return { start = function() 144 | mp.remove_key_binding(bindingname) 145 | mp.add_forced_key_binding(options.button, bindingname, binding, {complex = true, repeatable = true}) 146 | end, stop = function() 147 | mp.remove_key_binding(bindingname) 148 | reset(); 149 | end, set_haste = function(h) 150 | haste = h 151 | end, reset_deadzone = function() 152 | active_deadzone = false 153 | end} 154 | end 155 | 156 | local function seek_n_volume() 157 | local time 158 | local inertia_start; 159 | local x 160 | local dx 161 | local init_pos 162 | local init_vol 163 | local max_vol 164 | local osd_height 165 | local control_pos 166 | local control_vol 167 | 168 | local drag 169 | 170 | local function speedup(x) 171 | -- in dire need of refactoring, do not expose those as opts yet as it's too finnicky 172 | local elapsed = (time - inertia_start)/10 + 1 173 | local speedup = math.max(math.abs(x), 250) * (elapsed) 174 | if x > 0 then return -speedup else return speedup end 175 | end 176 | 177 | local function set_pos() 178 | local setpos = init_pos + x/OPTS.pixels_per_second 179 | if setpos < 0 then setpos = 0 end 180 | mp.command("seek " .. setpos .. " absolute exact") 181 | end 182 | 183 | local function digestX(newx) 184 | if not control_pos then return end 185 | local delta = mp.get_time() - time; 186 | time = delta + time; 187 | dx = (newx - x) / delta 188 | x = newx 189 | 190 | set_pos() 191 | end 192 | 193 | local function digestY(y) 194 | if not control_vol then return end 195 | y = -y 196 | local vol = OPTS.volume_modifier*(y / (osd_height / 2)) 197 | 198 | mp.command("set volume " .. math.min(max_vol, math.max(0, init_vol + vol))) 199 | end 200 | 201 | local function calculX() 202 | if not control_pos then return end 203 | local delta = mp.get_time() - time; 204 | time = delta + time; 205 | dx = dx + speedup(dx)*delta 206 | x = x + dx*delta 207 | 208 | set_pos() 209 | end 210 | 211 | local inertia; inertia = mp.add_periodic_timer(OPTS.inertia_tick_ms / 1000, function() 212 | msg.trace("on inertia", dx, x) 213 | calculX() 214 | if math.abs(dx) < OPTS.inertia_lower_bound_pixels then 215 | msg.trace("end inertia") 216 | inertia:kill() 217 | drag.set_haste(false) 218 | drag.reset_deadzone() 219 | end 220 | end); inertia:kill(); 221 | 222 | 223 | drag = drag_handler(function(newx, y) 224 | msg.trace("on drag") 225 | inertia:kill() 226 | if newx ~= false then 227 | control_pos = true 228 | else 229 | control_pos = false 230 | end 231 | if y ~= false then 232 | control_vol = true 233 | else 234 | control_vol = false 235 | end 236 | 237 | digestX(newx) 238 | digestY(y) 239 | end, function() 240 | msg.trace("start drag") 241 | drag.set_haste(true) 242 | inertia:kill() 243 | 244 | init_pos = mp.get_property_native("time-pos") 245 | init_vol = mp.get_property_native("volume") 246 | max_vol = mp.get_property_native("volume-max") 247 | local _w; w, osd_height = mp.get_osd_size() 248 | time = mp.get_time() 249 | x = 0 250 | dx = 0 251 | end, function() 252 | msg.trace("end drag / start inertia") 253 | inertia_start = mp.get_time() 254 | inertia:resume() 255 | end, { deadzone = OPTS.deadzone, deadzone_reset = "manual", 256 | button = OPTS.seek_volume_button, tick_ms = OPTS.sample_rate_ms, input_delay = OPTS.input_delay }) 257 | 258 | return { 259 | start = function() drag.start() end, 260 | stop = function() drag.stop() end 261 | } 262 | end 263 | 264 | local function speed() 265 | local init_speed 266 | 267 | local drag = drag_handler(function(x, y) 268 | if y ~= false then 269 | mp.command("set speed 1.0") 270 | return 271 | end 272 | if x ~= false then 273 | mp.command("set speed " .. math.max(0.01, init_speed + x/OPTS.pps)) 274 | return 275 | end 276 | end, function() 277 | init_speed = mp.get_property_native("speed") 278 | end, nil, { button = OPTS.speed_button, deadzone = OPTS.deadzone }) 279 | 280 | return { 281 | start = function() drag.start() end, 282 | stop = function() drag.stop() end 283 | } 284 | end 285 | 286 | local ctl1 = seek_n_volume(); 287 | local ctl2 = if_enabled(OPTS.speed_enabled)(speed); 288 | 289 | local state = OPTS.autostart; 290 | if state then 291 | ctl1.start() 292 | ctl2.start() 293 | end 294 | 295 | function toggle_gestures() 296 | if state == 1 then 297 | state = 0 298 | ctl1.stop() 299 | ctl2.stop() 300 | else 301 | state = 1 302 | ctl1.start() 303 | ctl2.start() 304 | end 305 | end 306 | 307 | mp.add_key_binding(nil, "toggle", toggle_gestures) 308 | -------------------------------------------------------------------------------- /scripts/autocrop.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | This script uses the lavfi cropdetect filter and the video-crop property to 3 | automatically crop the currently playing video with appropriate parameters. 4 | 5 | It automatically crops the video when playback starts. 6 | 7 | You can also manually crop the video by pressing the "C" (shift+c) key. 8 | Pressing it again undoes the crop. 9 | 10 | The workflow is as follows: First, it inserts the cropdetect filter. After 11 | (default is 1) seconds, it then sets video-crop based on the 12 | vf-metadata values gathered by cropdetect. The cropdetect filter is removed 13 | after video-crop is set as it is no longer needed. 14 | 15 | Since the crop parameters are determined from the 1 second of video between 16 | inserting the cropdetect filter and setting video-crop, the "C" key should be 17 | pressed at a position in the video where the crop region is unambiguous (i.e., 18 | not a black frame, black background title card, or dark scene). 19 | 20 | If non-copy-back hardware decoding is in use, hwdec is temporarily disabled for 21 | the duration of cropdetect as the filter would fail otherwise. 22 | 23 | These are the default options. They can be overridden by adding 24 | script-opts-append=autocrop-= to mpv.conf. 25 | --]] 26 | local options = { 27 | -- Whether to automatically apply crop at the start of playback. If you 28 | -- don't want to crop automatically, add 29 | -- script-opts-append=autocrop-auto=no to mpv.conf. 30 | auto = false, 31 | -- Delay before starting crop in auto mode. You can try to increase this 32 | -- value to avoid dark scenes or fade ins at beginning. Automatic cropping 33 | -- will not occur if the value is larger than the remaining playback time. 34 | auto_delay = 4, 35 | -- Black threshold for cropdetect. Smaller values will generally result in 36 | -- less cropping. See limit of 37 | -- https://ffmpeg.org/ffmpeg-filters.html#cropdetect 38 | detect_limit = "24/255", 39 | -- The value which the width/height should be divisible by. Smaller 40 | -- values have better detection accuracy. If you have problems with 41 | -- other filters, you can try to set it to 4 or 16. See round of 42 | -- https://ffmpeg.org/ffmpeg-filters.html#cropdetect 43 | detect_round = 2, 44 | -- The ratio of the minimum clip size to the original. A number from 0 to 45 | -- 1. If the picture is over cropped, try adjusting this value. 46 | detect_min_ratio = 0.5, 47 | -- How long to gather cropdetect data. Increasing this may be desirable to 48 | -- allow cropdetect more time to collect data. 49 | detect_seconds = 1, 50 | -- Whether the OSD shouldn't be used when cropdetect and video-crop are 51 | -- applied and removed. 52 | suppress_osd = false, 53 | } 54 | 55 | require "mp.options".read_options(options) 56 | 57 | local cropdetect_label = mp.get_script_name() .. "-cropdetect" 58 | 59 | timers = { 60 | auto_delay = nil, 61 | detect_crop = nil 62 | } 63 | 64 | local hwdec_backup 65 | 66 | local command_prefix = options.suppress_osd and 'no-osd' or '' 67 | 68 | function is_enough_time(seconds) 69 | 70 | -- Plus 1 second for deviation. 71 | local time_needed = seconds + 1 72 | local playtime_remaining = mp.get_property_native("playtime-remaining") 73 | 74 | return playtime_remaining and time_needed < playtime_remaining 75 | end 76 | 77 | function is_cropable(time_needed) 78 | if mp.get_property_native('current-tracks/video/image') ~= false then 79 | mp.msg.warn("autocrop only works for videos.") 80 | return false 81 | end 82 | 83 | if not is_enough_time(time_needed) then 84 | mp.msg.warn("Not enough time to detect crop.") 85 | return false 86 | end 87 | 88 | return true 89 | end 90 | 91 | function remove_cropdetect() 92 | for _, filter in pairs(mp.get_property_native("vf")) do 93 | if filter.label == cropdetect_label then 94 | mp.command( 95 | string.format("%s vf remove @%s", command_prefix, filter.label)) 96 | 97 | return 98 | end 99 | end 100 | end 101 | 102 | function restore_hwdec() 103 | if hwdec_backup then 104 | mp.set_property("hwdec", hwdec_backup) 105 | hwdec_backup = nil 106 | end 107 | end 108 | 109 | function cleanup() 110 | remove_cropdetect() 111 | 112 | -- Kill all timers. 113 | for index, timer in pairs(timers) do 114 | if timer then 115 | timer:kill() 116 | timers[index] = nil 117 | end 118 | end 119 | 120 | restore_hwdec() 121 | end 122 | 123 | function detect_crop() 124 | local time_needed = options.detect_seconds 125 | 126 | if not is_cropable(time_needed) then 127 | return 128 | end 129 | 130 | local hwdec_current = mp.get_property("hwdec-current") 131 | if hwdec_current:find("-copy$") == nil and hwdec_current ~= "no" and 132 | hwdec_current ~= "crystalhd" and hwdec_current ~= "rkmpp" then 133 | hwdec_backup = mp.get_property("hwdec") 134 | mp.set_property("hwdec", "no") 135 | end 136 | 137 | -- Insert the cropdetect filter. 138 | local limit = options.detect_limit 139 | local round = options.detect_round 140 | 141 | mp.command( 142 | string.format( 143 | '%s vf pre @%s:cropdetect=limit=%s:round=%d:reset=0', 144 | command_prefix, cropdetect_label, limit, round 145 | ) 146 | ) 147 | 148 | -- Wait to gather data. 149 | timers.detect_crop = mp.add_timeout(time_needed, detect_end) 150 | end 151 | 152 | function detect_end() 153 | 154 | -- Get the metadata and remove the cropdetect filter. 155 | local cropdetect_metadata = mp.get_property_native( 156 | "vf-metadata/" .. cropdetect_label) 157 | remove_cropdetect() 158 | 159 | -- Remove the timer of detect crop. 160 | if timers.detect_crop then 161 | timers.detect_crop:kill() 162 | timers.detect_crop = nil 163 | end 164 | 165 | restore_hwdec() 166 | 167 | local meta = {} 168 | 169 | -- Verify the existence of metadata. 170 | if cropdetect_metadata then 171 | meta = { 172 | w = cropdetect_metadata["lavfi.cropdetect.w"], 173 | h = cropdetect_metadata["lavfi.cropdetect.h"], 174 | x = cropdetect_metadata["lavfi.cropdetect.x"], 175 | y = cropdetect_metadata["lavfi.cropdetect.y"], 176 | } 177 | else 178 | mp.msg.error("No crop data.") 179 | mp.msg.info("Was the cropdetect filter successfully inserted?") 180 | mp.msg.info("Does your version of FFmpeg support AVFrame metadata?") 181 | return 182 | end 183 | 184 | -- Verify that the metadata meets the requirements and convert it. 185 | if meta.w and meta.h and meta.x and meta.y then 186 | local width = mp.get_property_native("width") 187 | local height = mp.get_property_native("height") 188 | 189 | meta = { 190 | w = tonumber(meta.w), 191 | h = tonumber(meta.h), 192 | x = tonumber(meta.x), 193 | y = tonumber(meta.y), 194 | min_w = width * options.detect_min_ratio, 195 | min_h = height * options.detect_min_ratio, 196 | max_w = width, 197 | max_h = height 198 | } 199 | else 200 | mp.msg.error("Got empty crop data.") 201 | mp.msg.info("You might need to increase detect_seconds.") 202 | end 203 | 204 | apply_crop(meta) 205 | end 206 | 207 | function apply_crop(meta) 208 | 209 | -- Verify if it is necessary to crop. 210 | local is_effective = meta.w and meta.h and meta.x and meta.y and 211 | (meta.x > 0 or meta.y > 0 212 | or meta.w < meta.max_w or meta.h < meta.max_h) 213 | 214 | -- Verify it is not over cropped. 215 | local is_excessive = false 216 | if is_effective and (meta.w < meta.min_w or meta.h < meta.min_h) then 217 | mp.msg.info("The area to be cropped is too large.") 218 | mp.msg.info("You might need to decrease detect_min_ratio.") 219 | is_excessive = true 220 | end 221 | 222 | if not is_effective or is_excessive then 223 | -- Clear any existing crop. 224 | mp.command(string.format("%s set file-local-options/video-crop ''", command_prefix)) 225 | return 226 | end 227 | 228 | -- Apply crop. 229 | mp.command(string.format("%s set file-local-options/video-crop %sx%s+%s+%s", 230 | command_prefix, meta.w, meta.h, meta.x, meta.y)) 231 | end 232 | 233 | function on_start() 234 | 235 | -- Clean up at the beginning. 236 | cleanup() 237 | 238 | -- If auto is not true, exit. 239 | if not options.auto then 240 | return 241 | end 242 | 243 | -- If it is the beginning, wait for detect_crop 244 | -- after auto_delay seconds, otherwise immediately. 245 | local playback_time = mp.get_property_native("playback-time") 246 | local is_delay_needed = playback_time 247 | and options.auto_delay > playback_time 248 | 249 | if is_delay_needed then 250 | 251 | -- Verify if there is enough time for autocrop. 252 | local time_needed = options.auto_delay + options.detect_seconds 253 | 254 | if not is_cropable(time_needed) then 255 | return 256 | end 257 | 258 | timers.auto_delay = mp.add_timeout(time_needed, 259 | function() 260 | detect_crop() 261 | 262 | -- Remove the timer of auto delay. 263 | timers.auto_delay:kill() 264 | timers.auto_delay = nil 265 | end 266 | ) 267 | else 268 | detect_crop() 269 | end 270 | end 271 | 272 | function on_toggle() 273 | 274 | -- If it is during auto_delay, kill the timer. 275 | if timers.auto_delay then 276 | timers.auto_delay:kill() 277 | timers.auto_delay = nil 278 | end 279 | 280 | -- Cropped => Remove it. 281 | if mp.get_property("video-crop") ~= "" then 282 | mp.command(string.format("%s set file-local-options/video-crop ''", command_prefix)) 283 | return 284 | end 285 | 286 | -- Detecting => Leave it. 287 | if timers.detect_crop then 288 | mp.msg.warn("Already cropdetecting!") 289 | return 290 | end 291 | 292 | -- Neither => Detect crop. 293 | detect_crop() 294 | end 295 | 296 | mp.add_key_binding("", "auto-crop", on_toggle) 297 | mp.register_event("end-file", cleanup) 298 | mp.register_event("file-loaded", on_start) 299 | -------------------------------------------------------------------------------- /removed_conf/shaders/NVSharpen.glsl: -------------------------------------------------------------------------------- 1 | // The MIT License(MIT) 2 | // 3 | // Copyright(c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files(the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions : 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // NVIDIA Image Scaling v1.0.2 by NVIDIA 23 | // ported to mpv by agyild 24 | 25 | // Changelog 26 | // Made it directly operate on LUMA plane, since the original shader was operating 27 | // on LUMA by deriving it from RGB. 28 | 29 | //!HOOK LUMA 30 | //!BIND HOOKED 31 | //!DESC NVIDIA Image Sharpening v1.0.2 32 | //!COMPUTE 32 32 256 1 33 | //!WHEN OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 > ! OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 < ! * 34 | 35 | // User variables 36 | #define SHARPNESS 0.25 // Amount of sharpening. 0.0 to 1.0. 37 | #define NIS_THREAD_GROUP_SIZE 256 // May be set to 128 for better performance on NVIDIA hardware, otherwise set to 256. Don't forget to modify the COMPUTE directive accordingly as well (e.g., COMPUTE 32 32 128 1). 38 | #define NIS_HDR_MODE 0 // Must be set to 1 for content with PQ colorspace. 0 or 1. 39 | 40 | // Constant variables 41 | #define NIS_BLOCK_WIDTH 32 42 | #define NIS_BLOCK_HEIGHT 32 43 | #define kSupportSize 5 44 | #define kNumPixelsX (NIS_BLOCK_WIDTH + kSupportSize + 1) 45 | #define kNumPixelsY (NIS_BLOCK_HEIGHT + kSupportSize + 1) 46 | const float sharpen_slider = clamp(SHARPNESS, 0.0f, 1.0f) - 0.5f; 47 | const float MaxScale = (sharpen_slider >= 0.0f) ? 1.25f : 1.75f; 48 | const float MinScale = (sharpen_slider >= 0.0f) ? 1.25f : 1.0f; 49 | const float LimitScale = (sharpen_slider >= 0.0f) ? 1.25f : 1.0f; 50 | const float kDetectRatio = 2 * 1127.f / 1024.f; 51 | const float kDetectThres = (bool(NIS_HDR_MODE) ? 32.0f : 64.0f) / 1024.0f; 52 | const float kMinContrastRatio = bool(NIS_HDR_MODE) ? 1.5f : 2.0f; 53 | const float kMaxContrastRatio = bool(NIS_HDR_MODE) ? 5.0f : 10.0f; 54 | const float kSharpStartY = bool(NIS_HDR_MODE) ? 0.35f : 0.45f; 55 | const float kSharpEndY = bool(NIS_HDR_MODE) ? 0.55f : 0.9f; 56 | const float kSharpStrengthMin = max(0.0f, 0.4f + sharpen_slider * MinScale * (bool(NIS_HDR_MODE) ? 1.1f : 1.2)); 57 | const float kSharpStrengthMax = ((bool(NIS_HDR_MODE) ? 2.2f : 1.6f) + sharpen_slider * MaxScale * 1.8f); 58 | const float kSharpLimitMin = max((bool(NIS_HDR_MODE) ? 0.06f :0.1f), (bool(NIS_HDR_MODE) ? 0.1f : 0.14f) + sharpen_slider * LimitScale * (bool(NIS_HDR_MODE) ? 0.28f : 0.32f)); // 59 | const float kSharpLimitMax = ((bool(NIS_HDR_MODE) ? 0.6f : 0.5f) + sharpen_slider * LimitScale * 0.6f); 60 | const float kRatioNorm = 1.0f / (kMaxContrastRatio - kMinContrastRatio); 61 | const float kSharpScaleY = 1.0f / (kSharpEndY - kSharpStartY); 62 | const float kSharpStrengthScale = kSharpStrengthMax - kSharpStrengthMin; 63 | const float kSharpLimitScale = kSharpLimitMax - kSharpLimitMin; 64 | const float kContrastBoost = 1.0f; 65 | const float kEps = 1.0f / 255.0f; 66 | #define kSrcNormX HOOKED_pt.x 67 | #define kSrcNormY HOOKED_pt.y 68 | #define kDstNormX kSrcNormX 69 | #define kDstNormY kSrcNormY 70 | 71 | // HLSL to GLSL macros 72 | #define saturate(x) clamp(x, 0, 1) 73 | #define lerp(a, b, x) mix(a, b, x) 74 | 75 | // CS Shared variables 76 | shared float shPixelsY[kNumPixelsY][kNumPixelsX]; 77 | 78 | // Shader code 79 | 80 | vec4 GetEdgeMap(float p[5][5], int i, int j) { 81 | const float g_0 = abs(p[0 + i][0 + j] + p[0 + i][1 + j] + p[0 + i][2 + j] - p[2 + i][0 + j] - p[2 + i][1 + j] - p[2 + i][2 + j]); 82 | const float g_45 = abs(p[1 + i][0 + j] + p[0 + i][0 + j] + p[0 + i][1 + j] - p[2 + i][1 + j] - p[2 + i][2 + j] - p[1 + i][2 + j]); 83 | const float g_90 = abs(p[0 + i][0 + j] + p[1 + i][0 + j] + p[2 + i][0 + j] - p[0 + i][2 + j] - p[1 + i][2 + j] - p[2 + i][2 + j]); 84 | const float g_135 = abs(p[1 + i][0 + j] + p[2 + i][0 + j] + p[2 + i][1 + j] - p[0 + i][1 + j] - p[0 + i][2 + j] - p[1 + i][2 + j]); 85 | 86 | const float g_0_90_max = max(g_0, g_90); 87 | const float g_0_90_min = min(g_0, g_90); 88 | const float g_45_135_max = max(g_45, g_135); 89 | const float g_45_135_min = min(g_45, g_135); 90 | 91 | float e_0_90 = 0; 92 | float e_45_135 = 0; 93 | 94 | if (g_0_90_max + g_45_135_max == 0) 95 | { 96 | return vec4(0, 0, 0, 0); 97 | } 98 | 99 | e_0_90 = min(g_0_90_max / (g_0_90_max + g_45_135_max), 1.0f); 100 | e_45_135 = 1.0f - e_0_90; 101 | 102 | bool c_0_90 = (g_0_90_max > (g_0_90_min * kDetectRatio)) && (g_0_90_max > kDetectThres) && (g_0_90_max > g_45_135_min); 103 | bool c_45_135 = (g_45_135_max > (g_45_135_min * kDetectRatio)) && (g_45_135_max > kDetectThres) && (g_45_135_max > g_0_90_min); 104 | bool c_g_0_90 = g_0_90_max == g_0; 105 | bool c_g_45_135 = g_45_135_max == g_45; 106 | 107 | float f_e_0_90 = (c_0_90 && c_45_135) ? e_0_90 : 1.0f; 108 | float f_e_45_135 = (c_0_90 && c_45_135) ? e_45_135 : 1.0f; 109 | 110 | float weight_0 = (c_0_90 && c_g_0_90) ? f_e_0_90 : 0.0f; 111 | float weight_90 = (c_0_90 && !c_g_0_90) ? f_e_0_90 : 0.0f; 112 | float weight_45 = (c_45_135 && c_g_45_135) ? f_e_45_135 : 0.0f; 113 | float weight_135 = (c_45_135 && !c_g_45_135) ? f_e_45_135 : 0.0f; 114 | 115 | return vec4(weight_0, weight_90, weight_45, weight_135); 116 | } 117 | 118 | float CalcLTIFast(const float y[5]) { 119 | const float a_min = min(min(y[0], y[1]), y[2]); 120 | const float a_max = max(max(y[0], y[1]), y[2]); 121 | 122 | const float b_min = min(min(y[2], y[3]), y[4]); 123 | const float b_max = max(max(y[2], y[3]), y[4]); 124 | 125 | const float a_cont = a_max - a_min; 126 | const float b_cont = b_max - b_min; 127 | 128 | const float cont_ratio = max(a_cont, b_cont) / (min(a_cont, b_cont) + kEps); 129 | return (1.0f - saturate((cont_ratio - kMinContrastRatio) * kRatioNorm)) * kContrastBoost; 130 | } 131 | 132 | float EvalUSM(const float pxl[5], const float sharpnessStrength, const float sharpnessLimit) { 133 | // USM profile 134 | float y_usm = -0.6001f * pxl[1] + 1.2002f * pxl[2] - 0.6001f * pxl[3]; 135 | // boost USM profile 136 | y_usm *= sharpnessStrength; 137 | // clamp to the limit 138 | y_usm = min(sharpnessLimit, max(-sharpnessLimit, y_usm)); 139 | // reduce ringing 140 | y_usm *= CalcLTIFast(pxl); 141 | 142 | return y_usm; 143 | } 144 | 145 | vec4 GetDirUSM(const float p[5][5]) { 146 | // sharpness boost & limit are the same for all directions 147 | const float scaleY = 1.0f - saturate((p[2][2] - kSharpStartY) * kSharpScaleY); 148 | // scale the ramp to sharpen as a function of luma 149 | const float sharpnessStrength = scaleY * kSharpStrengthScale + kSharpStrengthMin; 150 | // scale the ramp to limit USM as a function of luma 151 | const float sharpnessLimit = (scaleY * kSharpLimitScale + kSharpLimitMin) * p[2][2]; 152 | 153 | vec4 rval; 154 | // 0 deg filter 155 | float interp0Deg[5]; 156 | { 157 | for (int i = 0; i < 5; ++i) 158 | { 159 | interp0Deg[i] = p[i][2]; 160 | } 161 | } 162 | 163 | rval.x = EvalUSM(interp0Deg, sharpnessStrength, sharpnessLimit); 164 | 165 | // 90 deg filter 166 | float interp90Deg[5]; 167 | { 168 | for (int i = 0; i < 5; ++i) 169 | { 170 | interp90Deg[i] = p[2][i]; 171 | } 172 | } 173 | 174 | rval.y = EvalUSM(interp90Deg, sharpnessStrength, sharpnessLimit); 175 | 176 | //45 deg filter 177 | float interp45Deg[5]; 178 | interp45Deg[0] = p[1][1]; 179 | interp45Deg[1] = lerp(p[2][1], p[1][2], 0.5f); 180 | interp45Deg[2] = p[2][2]; 181 | interp45Deg[3] = lerp(p[3][2], p[2][3], 0.5f); 182 | interp45Deg[4] = p[3][3]; 183 | 184 | rval.z = EvalUSM(interp45Deg, sharpnessStrength, sharpnessLimit); 185 | 186 | //135 deg filter 187 | float interp135Deg[5]; 188 | interp135Deg[0] = p[3][1]; 189 | interp135Deg[1] = lerp(p[3][2], p[2][1], 0.5f); 190 | interp135Deg[2] = p[2][2]; 191 | interp135Deg[3] = lerp(p[2][3], p[1][2], 0.5f); 192 | interp135Deg[4] = p[1][3]; 193 | 194 | rval.w = EvalUSM(interp135Deg, sharpnessStrength, sharpnessLimit); 195 | return rval; 196 | } 197 | 198 | void hook() { 199 | uvec2 blockIdx = gl_WorkGroupID.xy; 200 | uint threadIdx = gl_LocalInvocationID.x; 201 | 202 | const int dstBlockX = int(NIS_BLOCK_WIDTH * blockIdx.x); 203 | const int dstBlockY = int(NIS_BLOCK_HEIGHT * blockIdx.y); 204 | 205 | // fill in input luma tile in batches of 2x2 pixels 206 | // we use texture gather to get extra support necessary 207 | // to compute 2x2 edge map outputs too 208 | const float kShift = 0.5f - kSupportSize / 2; 209 | 210 | for (int i = int(threadIdx) * 2; i < kNumPixelsX * kNumPixelsY / 2; i += NIS_THREAD_GROUP_SIZE * 2) { 211 | uvec2 pos = uvec2(uint(i) % uint(kNumPixelsX), uint(i) / uint(kNumPixelsX) * 2); 212 | 213 | for (int dy = 0; dy < 2; dy++) { 214 | for (int dx = 0; dx < 2; dx++) { 215 | const float tx = (dstBlockX + pos.x + dx + kShift) * kSrcNormX; 216 | const float ty = (dstBlockY + pos.y + dy + kShift) * kSrcNormY; 217 | const float px = HOOKED_tex(vec2(tx, ty)).r; 218 | shPixelsY[pos.y + dy][pos.x + dx] = px; 219 | } 220 | } 221 | } 222 | 223 | groupMemoryBarrier(); 224 | barrier(); 225 | 226 | for (int k = int(threadIdx); k < NIS_BLOCK_WIDTH * NIS_BLOCK_HEIGHT; k += NIS_THREAD_GROUP_SIZE) 227 | { 228 | const ivec2 pos = ivec2(uint(k) % uint(NIS_BLOCK_WIDTH), uint(k) / uint(NIS_BLOCK_WIDTH)); 229 | 230 | // load 5x5 support to regs 231 | float p[5][5]; 232 | 233 | for (int i = 0; i < 5; ++i) 234 | { 235 | for (int j = 0; j < 5; ++j) 236 | { 237 | p[i][j] = shPixelsY[pos.y + i][pos.x + j]; 238 | } 239 | } 240 | 241 | // get directional filter bank output 242 | vec4 dirUSM = GetDirUSM(p); 243 | 244 | // generate weights for directional filters 245 | vec4 w = GetEdgeMap(p, kSupportSize / 2 - 1, kSupportSize / 2 - 1); 246 | 247 | // final USM is a weighted sum filter outputs 248 | const float usmY = (dirUSM.x * w.x + dirUSM.y * w.y + dirUSM.z * w.z + dirUSM.w * w.w); 249 | 250 | // do bilinear tap and correct luma texel so it produces new sharpened luma 251 | const int dstX = dstBlockX + pos.x; 252 | const int dstY = dstBlockY + pos.y; 253 | 254 | vec4 op = HOOKED_tex(vec2((dstX + 0.5f) * kDstNormX, (dstY + 0.5f) * kDstNormY)); 255 | op.x += usmY; 256 | 257 | imageStore(out_image, ivec2(dstX, dstY), op); 258 | } 259 | } -------------------------------------------------------------------------------- /removed_conf/shaders/AdaptiveSharp.glsl: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2021, bacondither 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions 6 | // are met: 7 | // 1. Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer 9 | // in this position and unchanged. 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 14 | // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 15 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | // Adaptive sharpen - version 2021-10-17 26 | // Tuned for use post-resize 27 | 28 | //!HOOK OUTPUT 29 | //!BIND HOOKED 30 | //!DESC adaptive-sharpen 31 | 32 | //--------------------------------------- Settings ------------------------------------------------ 33 | 34 | #define curve_height 1.0 // Main control of sharpening strength [>0] 35 | // 0.3 <-> 2.0 is a reasonable range of values 36 | 37 | #define overshoot_ctrl false // Allow for higher overshoot if the current edge pixel 38 | // is surrounded by similar edge pixels 39 | 40 | // Defined values under this row are "optimal" DO NOT CHANGE IF YOU DO NOT KNOW WHAT YOU ARE DOING! 41 | 42 | #define curveslope 0.5 // Sharpening curve slope, high edge values 43 | 44 | #define L_compr_low 0.167 // Light compression, default (0.167=~6x) 45 | #define L_compr_high 0.334 // Light compression, surrounded by edges (0.334=~3x) 46 | 47 | #define D_compr_low 0.250 // Dark compression, default (0.250=4x) 48 | #define D_compr_high 0.500 // Dark compression, surrounded by edges (0.500=2x) 49 | 50 | #define scale_lim 0.1 // Abs max change before compression [>0.01] 51 | #define scale_cs 0.056 // Compression slope above scale_lim 52 | 53 | #define pm_p 1.0 // Power mean p-value [>0-1.0] 54 | //------------------------------------------------------------------------------------------------- 55 | 56 | #define max4(a,b,c,d) ( max(max(a, b), max(c, d)) ) 57 | 58 | // Soft if, fast linear approx 59 | #define soft_if(a,b,c) ( sat((a + b + c + 0.056/2.5)/(maxedge + 0.03/2.5) - 0.85) ) 60 | 61 | // Soft limit, modified tanh approx 62 | #define soft_lim(v,s) ( sat(abs(v/s)*(27.0 + pow(v/s, 2.0))/(27.0 + 9.0*pow(v/s, 2.0)))*s ) 63 | 64 | // Weighted power mean 65 | #define wpmean(a,b,w) ( pow(w*pow(abs(a), pm_p) + abs(1.0-w)*pow(abs(b), pm_p), (1.0/pm_p)) ) 66 | 67 | // Get destination pixel values 68 | #define get(x,y) ( HOOKED_texOff(vec2(x, y)).rgb ) 69 | #define sat(x) ( clamp(x, 0.0, 1.0) ) 70 | #define dxdy(val) ( length(fwidth(val)) ) // =~1/2.5 hq edge without c_comp 71 | 72 | #ifdef LUMA_tex 73 | #define CtL(RGB) RGB.x 74 | #else 75 | #define CtL(RGB) ( sqrt(dot(sat(RGB)*sat(RGB), vec3(0.2126, 0.7152, 0.0722))) ) 76 | #endif 77 | 78 | #define b_diff(pix) ( (blur-luma[pix])*(blur-luma[pix]) ) 79 | 80 | vec4 hook() { 81 | 82 | // [ c22 ] 83 | // [ c24, c9, c23 ] 84 | // [ c21, c1, c2, c3, c18 ] 85 | // [ c19, c10, c4, c0, c5, c11, c16 ] 86 | // [ c20, c6, c7, c8, c17 ] 87 | // [ c15, c12, c14 ] 88 | // [ c13 ] 89 | vec3 c[25] = vec3[](get( 0, 0), get(-1,-1), get( 0,-1), get( 1,-1), get(-1, 0), 90 | get( 1, 0), get(-1, 1), get( 0, 1), get( 1, 1), get( 0,-2), 91 | get(-2, 0), get( 2, 0), get( 0, 2), get( 0, 3), get( 1, 2), 92 | get(-1, 2), get( 3, 0), get( 2, 1), get( 2,-1), get(-3, 0), 93 | get(-2, 1), get(-2,-1), get( 0,-3), get( 1,-2), get(-1,-2)); 94 | 95 | float e[13] = float[](dxdy(c[0]), dxdy(c[1]), dxdy(c[2]), dxdy(c[3]), dxdy(c[4]), 96 | dxdy(c[5]), dxdy(c[6]), dxdy(c[7]), dxdy(c[8]), dxdy(c[9]), 97 | dxdy(c[10]), dxdy(c[11]), dxdy(c[12])); 98 | 99 | // RGB to luma 100 | float luma[25] = float[](CtL(c[0]), CtL(c[1]), CtL(c[2]), CtL(c[3]), CtL(c[4]), CtL(c[5]), CtL(c[6]), 101 | CtL(c[7]), CtL(c[8]), CtL(c[9]), CtL(c[10]), CtL(c[11]), CtL(c[12]), 102 | CtL(c[13]), CtL(c[14]), CtL(c[15]), CtL(c[16]), CtL(c[17]), CtL(c[18]), 103 | CtL(c[19]), CtL(c[20]), CtL(c[21]), CtL(c[22]), CtL(c[23]), CtL(c[24])); 104 | 105 | float c0_Y = luma[0]; 106 | 107 | // Blur, gauss 3x3 108 | float blur = (2.0 * (luma[2]+luma[4]+luma[5]+luma[7]) + (luma[1]+luma[3]+luma[6]+luma[8]) + 4.0 * luma[0]) / 16.0; 109 | 110 | // Contrast compression, center = 0.5 111 | float c_comp = sat(0.266666681f + 0.9*exp2(blur * blur * -7.4)); 112 | 113 | // Edge detection 114 | // Relative matrix weights 115 | // [ 1 ] 116 | // [ 4, 5, 4 ] 117 | // [ 1, 5, 6, 5, 1 ] 118 | // [ 4, 5, 4 ] 119 | // [ 1 ] 120 | float edge = ( 1.38*b_diff(0) 121 | + 1.15*(b_diff(2) + b_diff(4) + b_diff(5) + b_diff(7)) 122 | + 0.92*(b_diff(1) + b_diff(3) + b_diff(6) + b_diff(8)) 123 | + 0.23*(b_diff(9) + b_diff(10) + b_diff(11) + b_diff(12)) ) * c_comp; 124 | 125 | vec2 cs = vec2(L_compr_low, D_compr_low); 126 | 127 | if (overshoot_ctrl) { 128 | float maxedge = max4( max4(e[1],e[2],e[3],e[4]), max4(e[5],e[6],e[7],e[8]), 129 | max4(e[9],e[10],e[11],e[12]), e[0] ); 130 | 131 | // [ x ] 132 | // [ z, x, w ] 133 | // [ z, z, x, w, w ] 134 | // [ y, y, y, 0, y, y, y ] 135 | // [ w, w, x, z, z ] 136 | // [ w, x, z ] 137 | // [ x ] 138 | float sbe = soft_if(e[2],e[9], dxdy(c[22]))*soft_if(e[7],e[12],dxdy(c[13])) // x dir 139 | + soft_if(e[4],e[10],dxdy(c[19]))*soft_if(e[5],e[11],dxdy(c[16])) // y dir 140 | + soft_if(e[1],dxdy(c[24]),dxdy(c[21]))*soft_if(e[8],dxdy(c[14]),dxdy(c[17])) // z dir 141 | + soft_if(e[3],dxdy(c[23]),dxdy(c[18]))*soft_if(e[6],dxdy(c[20]),dxdy(c[15])); // w dir 142 | 143 | cs = mix(cs, vec2(L_compr_high, D_compr_high), sat(2.4002*sbe - 2.282)); 144 | } 145 | 146 | // Precalculated default squared kernel weights 147 | const vec3 w1 = vec3(0.5, 1.0, 1.41421356237); // 0.25, 1.0, 2.0 148 | const vec3 w2 = vec3(0.86602540378, 1.0, 0.54772255751); // 0.75, 1.0, 0.3 149 | 150 | // Transition to a concave kernel if the center edge val is above thr 151 | vec3 dW = pow(mix( w1, w2, sat(2.4*edge - 0.82)), vec3(2.0)); 152 | 153 | // Use lower weights for pixels in a more active area relative to center pixel area 154 | // This results in narrower and less visible overshoots around sharp edges 155 | float modif_e0 = 3.0 * e[0] + 0.02/2.5; 156 | 157 | float weights[12] = float[](( min(modif_e0/e[1], dW.y) ), 158 | ( dW.x ), 159 | ( min(modif_e0/e[3], dW.y) ), 160 | ( dW.x ), 161 | ( dW.x ), 162 | ( min(modif_e0/e[6], dW.y) ), 163 | ( dW.x ), 164 | ( min(modif_e0/e[8], dW.y) ), 165 | ( min(modif_e0/e[9], dW.z) ), 166 | ( min(modif_e0/e[10], dW.z) ), 167 | ( min(modif_e0/e[11], dW.z) ), 168 | ( min(modif_e0/e[12], dW.z) )); 169 | 170 | weights[0] = (max(max((weights[8] + weights[9])/4.0, weights[0]), 0.25) + weights[0])/2.0; 171 | weights[2] = (max(max((weights[8] + weights[10])/4.0, weights[2]), 0.25) + weights[2])/2.0; 172 | weights[5] = (max(max((weights[9] + weights[11])/4.0, weights[5]), 0.25) + weights[5])/2.0; 173 | weights[7] = (max(max((weights[10] + weights[11])/4.0, weights[7]), 0.25) + weights[7])/2.0; 174 | 175 | // Calculate the negative part of the laplace kernel and the low threshold weight 176 | float lowthrsum = 0.0; 177 | float weightsum = 0.0; 178 | float neg_laplace = 0.0; 179 | 180 | for (int pix = 0; pix < 12; ++pix) 181 | { 182 | float lowthr = sat((20.*4.5*c_comp*e[pix + 1] - 0.221)); 183 | 184 | neg_laplace += luma[pix+1] * luma[pix+1] * weights[pix] * lowthr; 185 | weightsum += weights[pix] * lowthr; 186 | lowthrsum += lowthr / 12.0; 187 | } 188 | 189 | neg_laplace = sqrt(neg_laplace / weightsum); 190 | 191 | // Compute sharpening magnitude function 192 | float sharpen_val = curve_height/(curve_height*curveslope*edge + 0.625); 193 | 194 | // Calculate sharpening diff and scale 195 | float sharpdiff = (c0_Y - neg_laplace)*(lowthrsum*sharpen_val + 0.01); 196 | 197 | // Calculate local near min & max, partial sort 198 | float temp; 199 | 200 | for (int i1 = 0; i1 < 24; i1 += 2) 201 | { 202 | temp = luma[i1]; 203 | luma[i1] = min(luma[i1], luma[i1+1]); 204 | luma[i1+1] = max(temp, luma[i1+1]); 205 | } 206 | 207 | for (int i2 = 24; i2 > 0; i2 -= 2) 208 | { 209 | temp = luma[0]; 210 | luma[0] = min(luma[0], luma[i2]); 211 | luma[i2] = max(temp, luma[i2]); 212 | 213 | temp = luma[24]; 214 | luma[24] = max(luma[24], luma[i2-1]); 215 | luma[i2-1] = min(temp, luma[i2-1]); 216 | } 217 | 218 | float min_dist = min(abs(luma[24] - c0_Y), abs(c0_Y - luma[0])); 219 | min_dist = min(min_dist, scale_lim*(1.0 - scale_cs) + min_dist*scale_cs); 220 | 221 | // Soft limited anti-ringing with tanh, wpmean to control compression slope 222 | sharpdiff = wpmean(max(sharpdiff, 0.0), soft_lim( max(sharpdiff, 0.0), min_dist ), cs.x ) 223 | - wpmean(min(sharpdiff, 0.0), soft_lim( min(sharpdiff, 0.0), min_dist ), cs.y ); 224 | 225 | float sharpdiff_lim = sat(c0_Y + sharpdiff) - c0_Y; 226 | /*float satmul = (c0_Y + max(sharpdiff_lim*0.9, sharpdiff_lim)*1.03 + 0.03)/(c0_Y + 0.03); 227 | vec3 res = c0_Y + sharpdiff_lim + (c[0] - c0_Y)*satmul; 228 | */ 229 | return vec4(sharpdiff_lim + c[0], HOOKED_texOff(0).a); 230 | } 231 | -------------------------------------------------------------------------------- /scripts/visualizer.lua: -------------------------------------------------------------------------------- 1 | -- mpv various audio visualization 2 | -- This is a simplified visualizer by snad 3 | -- you can find original in "removed_scripts" folder 4 | 5 | local opts = { 6 | mode = "noalbumart", 7 | -- off disable visualization 8 | -- noalbumart enable visualization when no albumart and no video 9 | -- novideo enable visualization when no video 10 | -- force always enable visualization 11 | 12 | name = "showcqtbar", 13 | -- off 14 | -- showcqtbar 15 | 16 | quality = "medium", 17 | 18 | height = 3, 19 | -- [3 .. 12] 20 | } 21 | 22 | local axis_0 = "image/png;base64," .. 23 | "iVBORw0KGgoAAAANSUhEUgAAB4AAAAAwCAQAAABaxq+2AAAACXBIWXMAAA7EAAAOxAGVKw4bAAATVklEQVR42u2df0xUZ7rHJ+EPkiabbGJiYkLSmJg0aTYxTTZNmiYb09ykZjO0QLHY+quy9Qe1YgG5Re62rlev" .. 24 | "etluXVevt62rrkq1FLG21epW7FqUZRFtq1LqLxAR1FnkNwIzw8x752V27gzDOe/zvuedA0f5fp9kd+SZ7zPv8zlvz5x35pwzLhcEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAE" .. 25 | "QRAEQRAEQRAEQRAEQRAEQRAEQRBkq1gyK2F3Q1HCkpFHHnnkkUceeeSRRx555JFH/lHNu0KJiEqQRx555JFHHnnkkUceeeSRR/4RyzMIgiAIgiAIgiAImgTCAhiCIAiCIAiCIAiaFHK53JGoq4j8sa4i+lfkkUce" .. 26 | "eeSRRx555JFHHnnkkX8k8tGHU9PrKgY7BjvqKqamGxVAHnnkkUceeeSRRx555JFHHvmHOG/0VAQCgUAgEAgEAoFAIB65AAIEAoFAIBAIBAKBQEyKAAIEAoFAIBAIBAKBQEyKGN+Xm5mV+tqUNP7oqblOxPHsvOcW" .. 27 | "JKc+upsb/MEf/MEf/MEf/MEf/MEf/MF/EvN3uX/5Skttd3P3rfh47IXwU8zyR3eovFBy6omP+j0jN+EKdt64WsnYB+tlvbPmt52PjKDzxoxM1Y0+avw3W86d3ju2xs9ePL134D4f3rC38czpvZ767OVy9UfxafZc" .. 28 | "rqv49Wsq4wN/8Ad/8Ad/8Ad/8Ad/8Ad/8Af/ceHvci97w/gXkn72YvgpZvnqA/Iv88yr7T/F+6tKZd3FBbG+z7erbQCj8Q/cHw1p9qL71+Kfc3KXXP383Hinr2/PJr3xgT/4gz/4gz/4gz/4gz/4gz/4g3/C+fP/" .. 29 | "eWf17XOMdVwr3xKOs6WxG2BsvnxLV5PaBmisCq3sh6r2F+bNXrS5uKYsGFDzbygq2/LPhnB7XU1qG2D0+A9tPfvxYAdjzTWxz7hdx1jAV7U/P/f5hVvX3vlhZILsl68f9DNWW8ar15b1tYbMwXdWWxsf+IM/+IM/" .. 30 | "+IM/+IM/+IM/+IM/+NvEP/x/deWM3azmj5582eVemhOqMBx7LnY0P33ky+vmvzN2eq/sALf9jg/pP/89+pcrlaqfJEzL8PUy1niGo3m3UHUTRMfP44/vMubrj2Z3b+Tj27Qm8u+k1K6bjFXukq8f8DEW6W965p3v" .. 31 | "+TSJnMKgNj7wB3/wB3/wB3/wB3/wB3/wB3/wt4n/6AFuKAr4qg9OTb9/9cfjRg2sf3vYW/OJy33ojz0tq3Jlh8c/f2g8E/uXWfMPvDctQwVh2fv87PCn5nI017/R2wBV+xnrbY1mm0KbtfHb2Ofv3dxxLWeFtQ3g" .. 32 | "cme9HhxmbP3b6uNT4V+wCvzBH/zBH/zBH/zBH/zBH/zBH/wV+EcH2NtaV87Xzm3njRuI5G/Xqbbf3czY8Q9VXaODn8N+pdLlPrqDf1n+zKvqG4CPv678hy88l/nnDQfeixlfaKN+pTW+0RsgVPGWWsfgD/7gD/7g" .. 33 | "D/7gD/7gD/7gD/7gbzv/6AAjartg3IAo/9gLC5aaQ3ngYSxyWfKTLy9elr08e/niZb/IkvW73Cvf5K+8Jp/7hwcZO7VH5fVHjz98EXZ+zPfX/THjM4uk1Kdfkd8A/Jz2s6Xyfl3+4vo0f2p8FH+V/qzwn5KWvXz0" .. 34 | "eNX4U35d/uL6NH9qfBR/lf6s8H/8paU5/7bQOn/Kr8tfXJ/mT42P4q/Sn7X9j9obwNj9D/0Gpbf/EYXM/kcc9P5Hvj/wfzj5p2S8nsNPELTKX+RPBH/z+nL8ReOT4S/bH+b/wzf/+fHtr+ZZ50/5E3H8b15f7vhf" .. 35 | "ND6Z43/Z/qzN/9TXspebn1RLz3+xX3/+i+rLzH/x+Oj5L9+fw/Y/0QEOtDdWdTWafwJhnl9XONDO22r+++MvGb1I/x3GSkv4o/xcfvn1vxQszJPzu9yXj/Gz4m9W8/B2M9Z/N/YMedo/Mv773N1c7akPeBkLeKNf" .. 36 | "kfffZezj35sh+kXWke1NZ7zd9cflN8C9i6FJslver8Ofri/mLzM+EX/p/izyT0qt+YQ7+EkUZr9eJuIv49fhT9cX85cZn4i/dH8W+adk/HiC82Ws8/qCper8Zfw6/On6Yv4y4xPxl+7PIv9wFBf4B4cHFy5T5y/j" .. 37 | "19v/U/Wp/T89PvH+X7I/i/xnzQ/4wjHs/f5zdf4yfh3+dH0xf5nxifhL96cx/5NTaz/lB14s+NmfrMx/yq87/8X16flPjY+a/1L9WeTf3hDZvjzSs1X5y/h1+NP1xfxlxifiL92f5fm/v8Tbwwd876LZD7yI5z/t" .. 38 | "15v/VH1q/tPjE89/yf4s83/jzZ4WXr/fY+39l/br8afqU/zp8Yn5S/andfyjtgAee/wjsQDm52h/sJ6xugqXe3Nx23dLc0Y3wPN/3sjYhcPxB6APPN7e0/uufsNYTZnRi7SdZ6xqH3/03ILwbz1x+R+EPwWg/TMy" .. 39 | "/QPxt7retlb+9ePPQX/6lfYGxtp/ivyb39+sttwM0YXD/Ox3xuQXwMmpQ52hEf5O3q/Dn64v5k/7xfxV+rPC/+udjN29eHJXczULXv9Wnb+MX4c/XV/Mn/aL+av0Z4V/+RbGWmpP7Lx8bHiw84Y6fxm/Dn+6vpg/" .. 40 | "7RfzV+nPCv8w0c4b/FXNfhtPxF/Gr8Ofri/mT/vF/FX6s8L/uQX8lhpXK69W/nRyxzp1/jJ+Hf50fTF/2i/mr9KftfmfksHvItp5o+aT74+sK1Sf/7Rfb/5T9an5T/mp+S/fnxX+7Q0DHXzrXq3sa2PM+DwXEX8Z" .. 41 | "vw5/ur6YP+0X81fpzwr/lW8Gh/taz5Y2fB3weerV9z8yfh3+dH0xf9ov5q/SnxX+Sandt/yD1QfPlvoHBtqNr5wV8Zfx6/Cn64v5034xf5X+rB7/qC2Axx7/SC+AXe6cFUmhtT2/21fs19zRfO7KpNSxB6BhHM3/" .. 42 | "CHijN++ORi0/A/x2BM30zBmZfJNEbsNN+49sD22uAX4GeTh6W0OHnOfkXz9+A7jcOzcw5u2N/Ovsx6F/9cxeFM1PSSt7f+6SyOZ6t3BKmsoC+Et+nrz/uQXyfh3+dH0xf9ov5q/Wnzr/tgvdzeHPmxrPDA/Gf/ND" .. 43 | "85fx6/Cn64v5034xf7X+1PnPyNxQFH508QvGjH8GXcRfxq/Dn64v5k/7xfzV+lPnz4NfecMPr+QWwKP5y/h1+NP1xfxpv5i/Wn/q/PkCj/rJCBF/Gb8Of7q+mD/tF/NX68/K/Oc/C/LdEeM9m8z8p/1685+qT81/" .. 44 | "yk/Nf5X+1PkX5UUW1b2t3c3q/GX8Ovzp+mL+tF/MX60/df6ndjMWXgx9f4Qx45PcRfxl/Dr86fpi/rRfzF+tP3X+c37D2NmPR/ooY2z3RlX+Mn4d/nR9MX/aL+av1p+14x+1BfDY4x9iAfyrefy22HcvFuZFwvNj" .. 45 | "7A46ml/91tgrbS98FgyEl50clNGX4LMX+QdDK/6GkuKUDP6Jwapcfi+xSH3K//xC/sV/6/nIZ2tPv1J3iLFgsCgvPBXo1x/d3zury7d46vkJE5H8E3P67vCv9feXhP/zyc+9d5mx26MOsUQLvJlZAT9jh7cW5hXl" .. 46 | "7fyvy8dYcOwZ6CK/Hn+6fjz/3JWx/Ck/xV+1P1X+z7wavrpjSlr3rQceWf7R7mi/Hn+6vpg/5af4q/Znbf7Pmr9t7WBHZ6M6f9qfiPkvqi8z/839cvNfvj91/s/O8/V1Xv/mL2YLPIo/5dflT9Wn+Iv9NH+1/lT5" .. 47 | "8wVe+5XmmpZzxz4wXmSI+dN+Pf50fTF/yk/xV+1Plf/UdP9gV+Oz8zYXz5ov//4bpUf79fjT9cX8KT/FX7U/a/t/fuhtdl2dzP5f5E/E/l9UX2b/b+6X2//L96fKf8c6xr7ckZz61Nx7Fx/8U50/7dfjT9cX86f8" .. 48 | "FH/V/lT5z10S/lbW5T7wnvE3lWL+tF+PP11fzJ/yU/xV+7O6/zEPuf2P6QI4ZwW/afRYRUqE8tHzxlkwEL8ybzoTWcvv2cRYSbHRy3y+nQ+K2709/EeLuSI7C7F/Q9G/nCHxT9pmLwpf78gVPuGZev3R448o4Csu" .. 49 | "iD6nYJW3N/x3X2+4fjC477/lFohzl4zl1/jtz9NkF6i6/OkFqJi/2B/P//mFUf61n0r2lwD+U9NbzjF24iM5/k1npqTFH6aY+RPD37y+HH8zvyx/YX/a/Lev438b6jS60YQMf5E/EfxF9WX4m/vl+BP9afL/6WQw" .. 50 | "WJhXuct4gUfzF/v1+Yvr0/xFfhn+ZH9a/J+aO3LC2OBgR/yPNcjxp/y6/Kn6FH+xn+Yv0Z8W/5wVoYOlS/wQLug3urMnxZ/y6/Kn6lP8xX6av0R/CXj/dblrP7W6/xH7E/P+a15f7v3XzC/7/ivsT5M/v8jM2xsc" .. 51 | "9vevfssKf7Ffn7+4Ps1f5JfhT/anxT8pta/V139o6+l9/Cp7fidkNf6UX5c/VZ/iL/bT/CX6S8j+xyxk9z+mC+CZWeFLmM02wOh8vyf+Mv+ms7EL0N//h/ELlRTfuxQF0Xn9kz9Ehij2z13CT20bObzs4tN7Wsb9" .. 52 | "a+FNMjx4cpfM68f3Fww+8DSdeePN+MOIS0fDt7LhajsfOa2RXuDNzOqO1g/6+9sb9peoLFB1+cssgEX8xf54/lPT4/mr9meF/8wsfgN44+sExvIvLRn7HJFfn7+ovgx/c78cf5X+rPB/Ys6R7aFlRqC5euyORYa/" .. 53 | "2K/PX1Rfhr+5X46/Sn+q/H9bwIKXjrrcZgs8ij/t1+NP1af4i/00f9X+1Od/aUlJ8ZS0pNT6rxiLvXGX7Pyn/LrzX1yfnv8iv8z8V+tPlf/WtfwvzdUH/nD/SjAYe/dQOf60X48/VZ/iL/bT/FX7s3b8w29VY3yC" .. 54 | "r8z+X+xPxPGPeX254x8zv+zxj3x/qvxTMtq+Y2ywI+ALBsreV+dP+/X4U/Up/mI/zV+1P/X5X5g30DHy19AxVs1B9flP+XXnv7g+Pf9Ffpn5r9af1f2PWcjuf0wXwLrx3ZHgcPgG2PwU5MXLzJ/5xJw1+dvWFuaN" .. 55 | "/hpf3q/7+lSkZBQXbFubn2t0g3xqgUmFrj8R9Y35O6c/M/7zlvCrDqpKrdbV9Seqvhl/p/Qnmv88PvuT3t36dP269UXz3wn9GfPnH230tXU18TeZtvPG9zgQha4/cfWN+TunP2r+5+cy9sX/WK+v69etT83/ie7P" .. 56 | "mP/qt/hN5vij4gLGTu9VrarrT1x9Y/7O6U80/wvz9N5hdP2JqC+a/07oz5j/Vx8ytnNDUuqMzMaqgH96pmpVXX/i6hvzd05/5vN/euamNTkrTu/jr2Slsq4/MfXN578z+qPef20J/RKHtjK25R3+6GZ1wKd+ADLR" .. 57 | "frl4FBbAD2d/G4t8vUE//2zvmVf/vHH8/U4fn939RWP3RsbMP+O13+/08dnT39VvOq/z4D/1dvuc+v5N1+/08dnd37SMyLV+H61nbO/m8fY7fXx29zc9c3io+xZ/lL2csb/9Zbz9Th+f3f2F4/xh0fkd9vudPj77" .. 58 | "+mv4OuhPGbmB0bH/ZczsJGP7/E4fn939RWL92wFf103Rrebs9Tt9fHb3Z1Mk4g1goH2o6+SuH08wVnfo4fNTUZR36Wj9cca6W+qP15ZLn1ueML/Tx2dvf88v5NcsdDXVH68/7rnMmOS93RLmd/r47O7P5W6ubq7+" .. 59 | "csfhrdUHh7p9/cY/82Cn3+njs7u/cJza034lcrOJifA7fXz29dfV2NNSuevQ1pqD3p6h7plZ4+13+vjs7s/l5u/sDX/9fHvHNWZ6irGdfqePz+7+eDzwdN+cSL/Tx2dff2Xv85+4OrXnhy98/d6elIzx9jt9fHb3" .. 60 | "9+TLteWndl//WzAw1Fmwavz9Th+f3f3ZHIkosmnNUBc/Abv1/IzMh9Evjspd0Yus/f2xN+seH7/Tx2dvf/OWjL4y4qXs8fU7fXx29+dyVx+MXJvR27ppzfj7nT4+u/vj8fM0/mP2jD3wTE2fCL/Tx2dnf2VbvD3h" .. 61 | "7dvdYnaFrZ1+p4/P7v74/e1b/hG+ccpXH06E3+njs7s/l/uxF/ru6Jzcrut3+vjs7a/20/A7TF9b9KdextPv9PHZ2196Nr/BHGOey79+bSL8Th+f3f3ZHIl6C8hZodP+RPsRCIRZpGTkrCjKe3Gx1dNbdP1OH5/d" .. 62 | "/SEmNh57YfGywjyzH5mx3+/08dndH4+s11flPv7SxPmdPj67+0NMZMzIzF055zfW3190/U4fn739TctYlauzutD1O318dvdna2DngkAgEAgEAoFAIBCISRFAgEAgEAgEAoFAIBCISRHRh1PT6yqGOoc66yqMr6NC" .. 63 | "HnnkkUceeeSRRx555JFHHvmHOB99WFcRuZGO8b00kUceeeSRRx555JFHHnnkkUf+Ic4zCIIgCIIgCIIgCJoEwgIYgiAIgiAIgiAImhRyRcVK/v+vJS4DIY888sgjjzzyyCOPPPLII4/8o5B3seTQU+6EooQlI488" .. 64 | "8sgjjzzyyCOPPPLII4/8o5qHIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCEqf/A/SNfayCCBqGAAAAAElFTkSuQmCC" 65 | 66 | local options = require 'mp.options' 67 | local msg = require 'mp.msg' 68 | 69 | options.read_options(opts) 70 | opts.height = math.min(12, math.max(3, opts.height)) 71 | opts.height = math.floor(opts.height) 72 | 73 | local function get_visualizer(name, quality) 74 | local w, h, fps 75 | 76 | if quality == "medium" then 77 | w = 1920 78 | fps = 30 79 | else 80 | msg.log("error", "invalid quality") 81 | return "" 82 | end 83 | 84 | h = w * opts.height / 16 85 | 86 | if name == "showcqtbar" then 87 | local axis_h = math.ceil(w * 12 / 1920) * 4 88 | 89 | return "[aid1] asplit [ao]," .. 90 | "afifo, aformat = channel_layouts = stereo," .. 91 | "firequalizer =" .. 92 | "gain = '1.4884e8 * f*f*f / (f*f + 424.36) / (f*f + 1.4884e8) / sqrt(f*f + 25122.25)':" .. 93 | "scale = linlin:" .. 94 | "wfunc = tukey:" .. 95 | "zero_phase = on:" .. 96 | "fft2 = on," .. 97 | "showcqt =" .. 98 | "fps =" .. fps .. ":" .. 99 | "size =" .. w .. "x" .. (h + axis_h)/2 .. ":" .. 100 | "count = 1:" .. 101 | "csp = bt709:" .. 102 | "bar_g = 2:" .. 103 | "sono_g = 4:" .. 104 | "bar_v = 9:" .. 105 | "sono_v = 17:" .. 106 | "sono_h = 0:" .. 107 | "axisfile = data\\\\:'" .. axis_0 .. "':" .. 108 | "axis_h =" .. axis_h .. ":" .. 109 | "font = 'Nimbus Mono L,Courier New,mono|bold':" .. 110 | "fontcolor = 'st(0, (midi(f)-53.5)/12); st(1, 0.5 - 0.5 * cos(PI*ld(0))); r(1-ld(1)) + b(ld(1))':" .. 111 | "tc = 0.33:" .. 112 | "attack = 0.033:" .. 113 | "tlength = 'st(0,0.17); 384*tc / (384 / ld(0) + tc*f /(1-ld(0))) + 384*tc / (tc*f / ld(0) + 384 /(1-ld(0)))'," .. 114 | "format = yuv420p," .. 115 | "split [v0]," .. 116 | "crop =" .. 117 | "h =" .. (h - axis_h)/2 .. ":" .. 118 | "y = 0," .. 119 | "vflip [v1];" .. 120 | "[v0][v1] vstack [vo]" 121 | 122 | elseif name == "off" then 123 | return "[aid1] afifo [ao]; [vid1] fifo [vo]" 124 | end 125 | 126 | msg.log("error", "invalid visualizer name") 127 | return "" 128 | end 129 | 130 | local function select_visualizer(atrack, vtrack, albumart) 131 | if opts.mode == "off" then 132 | return "" 133 | elseif opts.mode == "force" then 134 | return get_visualizer(opts.name, opts.quality) 135 | elseif opts.mode == "noalbumart" then 136 | if albumart == 0 and vtrack == 0 then 137 | return get_visualizer(opts.name, opts.quality) 138 | end 139 | return "" 140 | elseif opts.mode == "novideo" then 141 | if vtrack == 0 then 142 | return get_visualizer(opts.name, opts.quality) 143 | end 144 | return "" 145 | end 146 | 147 | msg.log("error", "invalid mode") 148 | return "" 149 | end 150 | 151 | local function visualizer_hook() 152 | local count = mp.get_property_number("track-list/count", -1) 153 | local atrack = 0 154 | local vtrack = 0 155 | local albumart = 0 156 | if count <= 0 then 157 | return 158 | end 159 | for tr = 0,count-1 do 160 | if mp.get_property("track-list/" .. tr .. "/type") == "audio" then 161 | atrack = atrack + 1 162 | else 163 | if mp.get_property("track-list/" .. tr .. "/type") == "video" then 164 | if mp.get_property("track-list/" .. tr .. "/albumart") == "yes" then 165 | albumart = albumart + 1 166 | else 167 | vtrack = vtrack + 1 168 | end 169 | end 170 | end 171 | end 172 | 173 | mp.set_property("options/lavfi-complex", select_visualizer(atrack, vtrack, albumart)) 174 | end 175 | 176 | mp.add_hook("on_preloaded", 50, visualizer_hook) --------------------------------------------------------------------------------