Skip to content

Instantly share code, notes, and snippets.

@myfreeer
Last active January 19, 2025 09:23
Show Gist options
  • Save myfreeer/d744c445aa71c0eeb165ca39cf6c0511 to your computer and use it in GitHub Desktop.
Save myfreeer/d744c445aa71c0eeb165ca39cf6c0511 to your computer and use it in GitHub Desktop.
mpv user-script to cycle between lavfi's denoise filters, tested over mpv 0.25.0-58-g99cef59fc
-- settings
-- key_binding: press the key specified below
-- to cycle between denoise filters below,
-- set it to nil to disable the binding
local key_binding = "n"
-- key_binding_reverse cycle between denoise filters below
-- in reverse order, set it to nil to disable the binding,
-- set it to a single-char string to enable
local key_binding_reverse = nil
-- denoisers: specify names of denoise libavfilter filters
-- from `mpv --vf=lavfi=help` command
-- where the last 3 filters (dctdnoiz, owdenoise, nlmeans)
-- are too slow to be used in playback
local denoisers = {
"removegrain"
,"atadenoise"
,"hqdn3d"
,"vaguedenoiser"
-- ,"dctdnoiz"
-- ,"owdenoise"
-- ,"nlmeans"
}
local denoiser_count = #denoisers
local filter_index = 0
local script_name = mp.get_script_name()
local denoise_label = string.format("%s-denoise", script_name)
-- from https://github.com/mpv-player/mpv/blob/39e04e929483847a3e0722d86d53f69837ed99db/TOOLS/lua/autocrop.lua
function del_filter_if_present(label)
-- necessary because mp.command('vf del @label:filter') raises an
-- error if the filter doesn't exist
local vfs = mp.get_property_native("vf")
for i,vf in pairs(vfs) do
if vf["label"] == label then
table.remove(vfs, i)
mp.set_property_native("vf", vfs)
return true
end
end
return false
end
function cycle_denoise()
if not del_filter_if_present(denoise_label) then
filter_index = 0
end
filter_index = filter_index + 1
if filter_index > denoiser_count then
mp.osd_message("denoise filters removed", osd_time)
return
end
-- insert the filter
mp.command(
string.format(
'vf add @%s:lavfi=graph="%s"',
denoise_label, denoisers[filter_index]
)
)
end
function cycle_denoise_reverse()
if not del_filter_if_present(denoise_label) then
filter_index = denoiser_count
else
filter_index = filter_index - 1
end
if filter_index < 1 then
mp.osd_message("denoise filters removed", osd_time)
return
end
-- insert the filter
mp.command(
string.format(
'vf add @%s:lavfi=graph="%s"',
denoise_label, denoisers[filter_index]
)
)
end
if key_binding then
mp.add_key_binding(key_binding, "denoise", cycle_denoise)
end
if key_binding_reverse then
mp.add_key_binding(key_binding_reverse, "denoise-reverse", cycle_denoise_reverse)
end
@myfreeer
Copy link
Author

@RafeeDaBoy You can ask this in one of:

@geextahslex
Copy link

Hi. How can I use 2 at the same time? In this example I want to use "atadenoise" and "hqdn3d"
Thank you :)

@myfreeer
Copy link
Author

Hi. How can I use 2 at the same time? In this example I want to use "atadenoise" and "hqdn3d" Thank you :)

@geextahslex Open console, type vf add lavfi=graph=atadenoise, enter, type vf add lavfi=graph=hqdn3d, enter

@geextahslex
Copy link

But how to do that without typing something into a console? Isn't it possible to change the script to have this option added?

@myfreeer
Copy link
Author

But how to do that without typing something into a console? Isn't it possible to change the script to have this option added?

@geextahslex Yes, it's possible, here is the docs of mpv and lua, use lua 5.1 syntax since luajit is used.
If coding in lua is not an option, you can also try javascript api.

@geextahslex
Copy link

@myfreeer The noise is most of the time present in the lows 0-60srgb. When it's affecting the whole image, it blurrs the mids and highlights with no reason. Is it possible to limit the affected range of the video filter (srgb0-60)? This would be very usefull. It would keep details in the highlights, like faces etc.

@myfreeer
Copy link
Author

myfreeer commented May 2, 2024

@myfreeer The noise is most of the time present in the lows 0-60srgb. When it's affecting the whole image, it blurrs the mids and highlights with no reason. Is it possible to limit the affected range of the video filter (srgb0-60)? This would be very usefull. It would keep details in the highlights, like faces etc.

@geextahslex The filters referenced by this script is ffmpeg filters, check the docs for detailed usage of filters, or maybe try VapourSynth filter if your build includes it.

@geextahslex
Copy link

Hi, I try to limit the effect of lavfi atadenoise to a specific srgb threshold but I have no idea how to make this "work"
this would be the ffmpeg command

-vf "split [original][denoised];
[denoised] atadenoise [denoised_out];
[original] lutyuv='u=128:v=128' [gray];
[gray][denoised_out]
blend=all_expr='if(between(A,0,25),B,if(between(A,25,35),B+(35-A)*(B-A)/10,A))'"

So how to put this inside mpv? ^^'

@myfreeer
Copy link
Author

@geextahslex
So how to put this inside mpv? ^^'

See CONFIGURATION FILES, using this can make mpv load specified options on startup.

@geextahslex
Copy link

@myfreeer yeah I already fixed that, no worries mate :)

@veganomy
Copy link

veganomy commented Jan 13, 2025

How to use this script ? Kept the file in my scripts directory. What next ?

PS: I use no-input-default-bindings and have my own bindings through input.conf

@myfreeer
Copy link
Author

How to use this script ? Kept the file in my scripts directory. What next ?

PS: I use no-input-default-bindings and have my own bindings through input.conf

Edit the key binding here, and press it when the player is active.

Have not tested how no-input-default-bindings affects this.

@veganomy
Copy link

@myfreeer That is exactly why I asked. Doesn't work with no-input-default-bindings

@myfreeer
Copy link
Author

@myfreeer That is exactly why I asked. Doesn't work with no-input-default-bindings

@veganomy You'll need to change mp.add_key_binding to mp.add_forced_key_binding in line 89 and 93 according to the doc

@veganomy
Copy link

veganomy commented Jan 19, 2025

Why not just use forced function in your script? Like what's the point of preventing the bindings from users who do no-input-default-bindings ? Like I don't even use n binding and the script doesn't work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment