mirror of https://github.com/mpv-player/mpv
acompressor.lua: Convert to use mp.options and lavfi filter bridge
This commit is contained in:
parent
f550fdaa91
commit
207458c7a9
|
@ -3,48 +3,80 @@
|
|||
--
|
||||
-- See https://ffmpeg.org/ffmpeg-filters.html#acompressor for explanation
|
||||
-- of the parameteres.
|
||||
--
|
||||
-- Default key bindings:
|
||||
-- n: Toggle dynamic range compression on or off
|
||||
-- F1/Shift+F1: Increase/Decrease threshold parameter
|
||||
-- F2/Shift+F2: Increase/Decrease ratio parameter
|
||||
-- F3/Shift+F3: Increase/Decrease knee parameter
|
||||
-- F4/Shift+F4: Increase/Decrease makeup gain parameter
|
||||
-- F5/Shift+F5: Increase/Decrease attack parameter
|
||||
-- F6/Shift+F6: Increase/Decrease release parameter
|
||||
--
|
||||
-- To change key bindings in input.conf use:
|
||||
-- BINDING script-message-to acompressor toggle-acompressor
|
||||
-- BINDING script-message-to acompressor update-param PARAM INCREMENT
|
||||
-- BINDING is the key binding to use, PARAM is either 'attack', 'release',
|
||||
-- 'threshold', 'ratio', 'knee' or 'makeup' and INCREMENT is a signed floating
|
||||
-- point value to add to the current parameter value.
|
||||
--
|
||||
-- You may also just adjust default parameters to your liking in this table.
|
||||
|
||||
local mp = require 'mp'
|
||||
local options = require 'mp.options'
|
||||
|
||||
local o = {
|
||||
default_enable = false,
|
||||
show_osd = true,
|
||||
osd_timeout = 4000,
|
||||
filter_label = mp.get_script_name(),
|
||||
|
||||
key_toggle = 'n',
|
||||
key_increase_threshold = 'F1',
|
||||
key_decrease_threshold = 'Shift+F1',
|
||||
key_increase_ratio = 'F2',
|
||||
key_decrease_ratio = 'Shift+F2',
|
||||
key_increase_knee = 'F3',
|
||||
key_decrease_knee = 'Shift+F3',
|
||||
key_increase_makeup = 'F4',
|
||||
key_decrease_makeup = 'Shift+F4',
|
||||
key_increase_attack = 'F5',
|
||||
key_decrease_attack = 'Shift+F5',
|
||||
key_increase_release = 'F6',
|
||||
key_decrease_release = 'Shift+F6',
|
||||
|
||||
default_threshold = -25.0,
|
||||
default_ratio = 3.0,
|
||||
default_knee = 2.0,
|
||||
default_makeup = 8.0,
|
||||
default_attack = 20.0,
|
||||
default_release = 250.0,
|
||||
|
||||
step_threshold = -2.5,
|
||||
step_ratio = 1.0,
|
||||
step_knee = 1.0,
|
||||
step_makeup = 1.0,
|
||||
step_attack = 10.0,
|
||||
step_release = 10.0,
|
||||
}
|
||||
options.read_options(o)
|
||||
|
||||
local params = {
|
||||
-- 'hide' defines wether the parameter should be hidden from OSD display (it will still be included in ffmpeg filter graph).
|
||||
-- 'input_format' is used to parse the value back from a obtained filter graph.
|
||||
-- 'output_format' defines how the value shall be formatted for creating the filter graph.
|
||||
{ name = 'Attack', value= 20, min=0.01, max=2000, hide= 20, input_format='attack=(%d+[.%d+]*)', output_format='%g' },
|
||||
{ name = 'Release', value=250, min=0.01, max=9000, hide=250, input_format='release=(%d+[.%d+]*)', output_format='%g' },
|
||||
{ name = 'Threshold', value=-25, min= -30, max= 0, hide=nil, input_format='threshold=(-%d+[.%d+]*)dB', output_format='%gdB' },
|
||||
{ name = 'Ratio', value= 3, min= 1, max= 20, hide=nil, input_format='ratio=(%d+[.%d+]*)', output_format='%g' },
|
||||
{ name = 'Knee', value= 2, min= 1, max= 10, hide= 2, input_format='knee=(%d+[.%d+]*)dB', output_format='%gdB' },
|
||||
{ name = 'Makeup', value= 8, min= 0, max= 24, hide=nil, input_format='makeup=(%d+[.%d+]*)dB', output_format='%gdB' }
|
||||
{ name = 'attack', min=0.01, max=2000, hide_default=true, dB='' },
|
||||
{ name = 'release', min=0.01, max=9000, hide_default=true, dB='' },
|
||||
{ name = 'threshold', min= -30, max= 0, hide_default=false, dB='dB' },
|
||||
{ name = 'ratio', min= 1, max= 20, hide_default=false, dB='' },
|
||||
{ name = 'knee', min= 1, max= 10, hide_default=true, dB='dB' },
|
||||
{ name = 'makeup', min= 0, max= 24, hide_default=false, dB='dB' },
|
||||
}
|
||||
|
||||
-- Defines the mpv filter label to be used. This allows us to easily add/replace/remove it, so
|
||||
-- it should be left so something meaningful and unique.
|
||||
local filter_label = 'acompressor'
|
||||
local function parse_value(value)
|
||||
-- Using nil here because tonumber differs between lua 5.1 and 5.2 when parsing fractions in combination with explicit base argument set to 10.
|
||||
-- And we can't omit it because gsub returns 2 values which would get unpacked and cause more problems. Gotta love scripting languages.
|
||||
return tonumber(value:gsub('dB$', ''), nil)
|
||||
end
|
||||
|
||||
local function format_value(value, dB)
|
||||
return string.format('%g%s', value, dB)
|
||||
end
|
||||
|
||||
local function show_osd(filter)
|
||||
if not o.show_osd then
|
||||
return
|
||||
end
|
||||
|
||||
if not filter.enabled then
|
||||
mp.commandv('show-text', 'Dynamic range compressor: disabled', o.osd_timeout)
|
||||
return
|
||||
end
|
||||
|
||||
local function update_filter()
|
||||
local graph = {}
|
||||
local pretty = {}
|
||||
|
||||
for _,param in pairs(params) do
|
||||
graph[#graph+1] = string.format('%s=' .. param.output_format, string.lower(param.name), param.value)
|
||||
if param.hide ~= param.value then
|
||||
pretty[#pretty+1] = string.format('%s: ' .. param.output_format, param.name, param.value)
|
||||
for _,param in ipairs(params) do
|
||||
local value = parse_value(filter.params[param.name])
|
||||
if not (param.hide_default and value == o['default_' .. param.name]) then
|
||||
pretty[#pretty+1] = string.format('%s: %g%s', param.name:gsub("^%l", string.upper), value, param.dB)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -54,49 +86,49 @@ local function update_filter()
|
|||
pretty = '\n(' .. table.concat(pretty, ', ') .. ')'
|
||||
end
|
||||
|
||||
mp.command(string.format('no-osd af add @%s:lavfi=[acompressor=%s]; show-text "Dynamic range compressor: enabled%s" 4000', filter_label, table.concat(graph, ':'), pretty))
|
||||
mp.commandv('show-text', 'Dynamic range compressor: enabled' .. pretty, o.osd_timeout)
|
||||
end
|
||||
|
||||
local function read_filter()
|
||||
local graph = nil
|
||||
local function get_filter()
|
||||
local af = mp.get_property_native('af', {})
|
||||
|
||||
for i = 1, #af do
|
||||
if af[i]['name'] == 'lavfi' and af[i]['label'] == 'acompressor' then
|
||||
graph = af[i]['params']['graph']
|
||||
break
|
||||
if af[i].label == o.filter_label then
|
||||
return af, i
|
||||
end
|
||||
end
|
||||
|
||||
if graph == nil then
|
||||
return false
|
||||
end
|
||||
af[#af+1] = {
|
||||
name = 'acompressor',
|
||||
label = o.filter_label,
|
||||
enabled = false,
|
||||
params = {},
|
||||
}
|
||||
|
||||
for _,param in pairs(params) do
|
||||
local value = tonumber(string.match(graph, param.input_format))
|
||||
if value ~= nil and value >= param.min and value <= param.max then
|
||||
param.value = value
|
||||
end
|
||||
af[#af].params[param.name] = format_value(o['default_' .. param.name], param.dB)
|
||||
end
|
||||
return true
|
||||
|
||||
return af, #af
|
||||
end
|
||||
|
||||
local function toggle_acompressor()
|
||||
if read_filter() then
|
||||
mp.command(string.format('no-osd af del @%s; show-text "Dynamic range compressor: disabled"', filter_label))
|
||||
else
|
||||
update_filter()
|
||||
end
|
||||
local af, i = get_filter()
|
||||
af[i].enabled = not af[i].enabled
|
||||
mp.set_property_native('af', af)
|
||||
show_osd(af[i])
|
||||
end
|
||||
|
||||
local function update_param(name, increment)
|
||||
-- The current filter values could come from a watch_later config.
|
||||
-- read_filter() will parse them, so that we don't clobber those with our default values.
|
||||
read_filter()
|
||||
for _,param in pairs(params) do
|
||||
if string.lower(param.name) == string.lower(name) then
|
||||
param.value = math.max(param.min, math.min(param.value + increment, param.max))
|
||||
update_filter()
|
||||
if param.name == string.lower(name) then
|
||||
local af, i = get_filter()
|
||||
local value = parse_value(af[i].params[param.name])
|
||||
value = math.max(param.min, math.min(value + increment, param.max))
|
||||
af[i].params[param.name] = format_value(value, param.dB)
|
||||
af[i].enabled = true
|
||||
mp.set_property_native('af', af)
|
||||
show_osd(af[i])
|
||||
return
|
||||
end
|
||||
end
|
||||
|
@ -104,23 +136,20 @@ local function update_param(name, increment)
|
|||
mp.msg.error('Unknown parameter "' .. name .. '"')
|
||||
end
|
||||
|
||||
mp.add_key_binding("n", "toggle-acompressor", toggle_acompressor)
|
||||
mp.add_key_binding(o.key_toggle, "toggle-acompressor", toggle_acompressor)
|
||||
mp.register_script_message('update-param', update_param)
|
||||
|
||||
mp.add_key_binding("F1", 'acompressor-inc-threshold', function() update_param('threshold', -5); end, { repeatable = true })
|
||||
mp.add_key_binding("Shift+F1", 'acompressor-dec-threshold', function() update_param('Threshold', 5); end, { repeatable = true })
|
||||
for _,param in pairs(params) do
|
||||
for direction,step in pairs({increase=1, decrease=-1}) do
|
||||
mp.add_key_binding(o['key_' .. direction .. '_' .. param.name],
|
||||
'acompressor-' .. direction .. '-' .. param.name,
|
||||
function() update_param(param.name, step*o['step_' .. param.name]); end,
|
||||
{ repeatable = true })
|
||||
end
|
||||
end
|
||||
|
||||
mp.add_key_binding("F2", 'acompressor-inc-ratio', function() update_param('Ratio', 1); end, { repeatable = true })
|
||||
mp.add_key_binding("Shift+F2", 'acompressor-dec-ratio', function() update_param('Ratio', -1); end, { repeatable = true })
|
||||
|
||||
mp.add_key_binding("F3", 'acompressor-inc-knee', function() update_param('Knee', 1); end, { repeatable = true })
|
||||
mp.add_key_binding("Shift+F3", 'acompressor-dec-knee', function() update_param('Knee', -1); end, { repeatable = true })
|
||||
|
||||
mp.add_key_binding("F4", 'acompressor-inc-makeup', function() update_param('Makeup', 1); end, { repeatable = true })
|
||||
mp.add_key_binding("Shift+F4", 'acompressor-dec-makeup', function() update_param('Makeup', -1); end, { repeatable = true })
|
||||
|
||||
mp.add_key_binding("F5", 'acompressor-inc-attack', function() update_param('Attack', 10); end, { repeatable = true })
|
||||
mp.add_key_binding("Shift+F5", 'acompressor-dec-attack', function() update_param('Attack', -10); end, { repeatable = true })
|
||||
|
||||
mp.add_key_binding("F6", 'acompressor-inc-release', function() update_param('Release', 10); end, { repeatable = true })
|
||||
mp.add_key_binding("Shift+F6", 'acompressor-dec-release', function() update_param('Release', -10); end, { repeatable = true })
|
||||
if o.default_enable then
|
||||
local af, i = get_filter()
|
||||
af[i].enabled = true
|
||||
mp.set_property_native('af', af)
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue