--- Auto Audio Source Mute -- -- Mutes selected audio source (if unmuted) obs = obslua bit = require("bit") source_def = {} source_def.id = "Auto_Mute_Source" source_def.output_flags = bit.bor(obs.OBS_SOURCE_CUSTOM_DRAW) muted = false volume = 0 source_ptr = nil incallback = false duck = false muteActive = 0 loaded_audio_source = "" source_def.get_name = function() return "Auto Mute/Duck Audio" end source_def.create = function(settings, source) data = {} sh = obs.obs_source_get_signal_handler(source) obs.signal_handler_connect(sh,"activate",active) --Set Active Callback obs.signal_handler_connect(sh,"deactivate",deactive) --Set Preview Callback source_ptr = source return data end function rename_callback() obs.timer_remove(rename_callback) local sources = obs.obs_enum_sources() if (sources ~= nil) then local t = 0 for _, source in ipairs(sources) do local source_id = obs.obs_source_get_unversioned_id(source) if source_id == "Auto_Mute_Source" then t = t + 1 end end if t>0 then for _, source in ipairs(sources) do local source_id = obs.obs_source_get_unversioned_id(source) if source_id == "Auto_Mute_Source" then local settings = obs.obs_source_get_settings(source) local audio_source_name = obs.obs_data_get_string(settings, "audio_prop") local direction = obs.obs_data_get_bool(settings,"dir") local duck = obs.obs_data_get_bool(settings,"duck") local duckVolume = 60+obs.obs_data_get_int(settings,"duckVolume") local setVolume = 60+obs.obs_data_get_int(settings,"setVolume") local value = duckVolume if (direction) then value = setVolume end local color = "50FF00" if (value > 40) then color = "FADB2C" end if (value > 51) then color = "FF4319" end local newname = "" if direction then if duck then newname = "(" .. t .. ") " .. audio_source_name .. " Vol set to " .. 60-setVolume .. string.format(" (%.1f db)",color,per_to_db(setVolume)) else newname = "(" .. t .. ") UnMute: " .. audio_source_name .. "" end else if duck then newname = "(" .. t .. ") " .. audio_source_name .. " Vol set to " .. 60-duckVolume .. string.format(" (%.1f db)",color,per_to_db(duckVolume)) else newname = "(" .. t .. ") Mute: " .. audio_source_name .. "" end end t = t - 1 obs.obs_data_release(settings) -- release memory obs.obs_source_set_name(source, newname) end end end end obs.source_list_release(sources) incallback = false end source_def.save = function (data, settings) if not incallback then obs.timer_add(rename_callback, 3000) -- wait long enough for save to complete so callback is only once incallback = true end end function change_duck_property(props, prop, settings) obs.obs_property_set_visible(obs.obs_properties_get(props, "duckVolume"), obs.obs_data_get_bool(settings, "duck")) return true end source_def.get_properties = function (data) props = obs.obs_properties_create() local source_prop = obs.obs_properties_add_list(props, "audio_prop", "Set Audio Source", obs.OBS_COMBO_TYPE_LIST, obs.OBS_COMBO_FORMAT_STRING) local sources = obs.obs_enum_sources() if sources ~= nil then local n = {} local source_id = nil for _, source in ipairs(sources) do if bit.band(obs.obs_source_get_output_flags(source),obs.OBS_SOURCE_AUDIO) > 0 then n[#n+1] = obs.obs_source_get_name(source) end end table.sort(n) for _, name in ipairs(n) do obs.obs_property_list_add_string(source_prop, name, name) end end obs.source_list_release(sources) obs.obs_properties_add_button(props, "show_help_button", "SHOW HELP", show_help_button) obs.obs_properties_add_bool(props,"dir","Unmute if Muted (Default is Mute if Unmuted): ") obs.obs_properties_add_bool(props,"restore","Restore Mute State/Volume Level on Exit: ") local duck_prop = obs.obs_properties_add_bool(props,"duck","Duck Volume instead of Mute: ") obs.obs_property_set_modified_callback(duck_prop, change_duck_property) local dv = obs.obs_properties_add_int_slider(props,"duckVolume","Ducking Volume:",-60,0,1) obs.obs_property_set_visible(dv, duck) return props end help = "▪▪▪▪▪ USAGE HELP ▪▪▪▪▪▲- CLICK TO CLOSE -▲▪▪▪▪▪\n\n" .. "Settings for Auto Mute/Duck Source \n" .. "==============================\n" .. "Normal operation is to mute selected source when then scene loads\n" .. "Check 'Unmute if Muted:' to unmute a selected source when the scene loads\n" .. "Check 'Restore Mute State/Volume level on Exit:' to restore original volume setting on scene close\n" .. "Check 'Duck Volume instead of Mute:' to set volume level for the selected source for this scene\n" .. "Ducking sets source volume to the selected Ducking Volume\n\n" .. "Note: OBS opens the next scene BEFORE it closes the prior scene!\n" .. " For this reason, Restore option is ignored if next scene sets the same source.\n" ----------------------------------------------------------------------------------------------------------------------- -- Show/Hide the Help Button Text ----------------------------------------------------------------------------------------------------------------------- function show_help_button(props, prop, settings) local hb = obs.obs_properties_get(props, "show_help_button") showhelp = not showhelp if showhelp then obs.obs_property_set_description(hb, help) else obs.obs_property_set_description(hb, "SHOW HELP") end return true end function script_description() return [[AUTO MUTE-DUCK AUDIO SOURCE
Ver 1.2    by DCStrato

Mutes/Unmutes or sets Audio level for a Selected Audio
Source during the Current Scene with optional Restore.

Property options are in the Source when added to a Scene]] end function per_to_db(level) local def = level / 60.0 local db = 0 if (def >= 1.0) then db = 0.0 elseif (def <= 0.0) then db = -100; else db = 6 - (102 * (1/(17 ^ def))) end return db end function db_to_mul(db) if ( db == 0) then return 0 else return 10 ^ (db / 20.0) end end function mul_to_db(mul) if (mul == 0) then return 1; else return 20 * math.log10(mul) end end function active(cd) muteActive = muteActive + 1 local source = obs.calldata_source(cd,"source") local settings = obs.obs_source_get_settings(source) local audio_source_name = obs.obs_data_get_string(settings, "audio_prop") local direction = obs.obs_data_get_bool(settings,"dir") duck = obs.obs_data_get_bool(settings,"duck") local duckVolume = per_to_db(60+obs.obs_data_get_int(settings,"duckVolume")) obs.obs_data_release(settings) local audio_source = obs.obs_get_source_by_name(audio_source_name) if audio_source ~= nil then muted = obs.obs_source_muted(audio_source) volume = obs.obs_source_get_volume(audio_source) if duck then if volume ~= duckVolume then obs.obs_source_set_volume(audio_source,db_to_mul(setVolume)) -- setVolume if not the same end else if not direction then if not muted then obs.obs_source_set_muted(audio_source,true) -- mute if unmuted end else if muted then obs.obs_source_set_muted(audio_source,false) -- unmute if muted end end end obs.obs_source_release(audio_source) end loaded_audio_source = audio_source_name end function deactive(cd) local source = obs.calldata_source(cd,"source") local settings = obs.obs_source_get_settings(source) local audio_source_name = obs.obs_data_get_string(settings, "audio_prop") local direction = obs.obs_data_get_bool(settings,"dir") local force = obs.obs_data_get_bool(settings,"force") local restore = obs.obs_data_get_bool(settings,"restore") local duck = obs.obs_data_get_bool(settings,"duck") local duckVolume = per_to_db(60+obs.obs_data_get_int(settings,"duckVolume")) local setVolume = per_to_db(60+obs.obs_data_get_int(settings,"setVolume")) obs.obs_data_release(settings) local audio_source = obs.obs_get_source_by_name(audio_source_name) if audio_source ~= nil and restore and (muteActive == 1 or (audio_source_name ~= loaded_source_name)) then if duck then obs.obs_source_set_volume(audio_source,volume) -- restore prior volume else obs.obs_source_set_muted(audio_source,muted) -- restore prior mute state end obs.obs_source_release(audio_source) end muteActive = muteActive - 1 end obs.obs_register_source(source_def)