obs = obslua check_interval = 100 selected_sources = {} source_states = {} MONITOR_NONE = obs.OBS_MONITORING_TYPE_NONE function script_description() return [[ Sincroniza o mute das fontes de áudio com o monitoramento do OBS. Marque as fontes desejadas na lista. Para cada fonte marcada: • Ao mutar no mixer, o áudio ao vivo é mutado normalmente pelo OBS. • O monitoramento também é desligado automaticamente. • Ao desmutar, o monitoramento anterior é restaurado. • Funciona com microfones, capturas, mídias, navegador e demais fontes de áudio. ]] end local function safe_key(name) local result = "" for i = 1, #name do result = result .. string.format("%02X", string.byte(name, i)) end return "audio_source_" .. result end local function get_audio_source_names() local names = {} local sources = obs.obs_enum_sources() if sources ~= nil then for _, source in ipairs(sources) do local flags = obs.obs_source_get_output_flags(source) if bit.band(flags, obs.OBS_SOURCE_AUDIO) ~= 0 then table.insert(names, obs.obs_source_get_name(source)) end end obs.source_list_release(sources) end table.sort(names, function(a, b) return string.lower(a) < string.lower(b) end) return names end local function restore_source_monitoring(source_name) local state = source_states[source_name] if state == nil or not state.changed_by_script then return end local source = obs.obs_get_source_by_name(source_name) if source ~= nil then if state.saved_monitoring_type ~= nil and state.saved_monitoring_type ~= MONITOR_NONE then obs.obs_source_set_monitoring_type( source, state.saved_monitoring_type ) end obs.obs_source_release(source) end state.changed_by_script = false end local function remove_unselected_states() for source_name, _ in pairs(source_states) do if not selected_sources[source_name] then restore_source_monitoring(source_name) source_states[source_name] = nil end end end function check_sources() for source_name, enabled in pairs(selected_sources) do if enabled then local source = obs.obs_get_source_by_name(source_name) if source ~= nil then local muted = obs.obs_source_muted(source) local monitoring = obs.obs_source_get_monitoring_type(source) local state = source_states[source_name] if state == nil then state = { last_muted = nil, saved_monitoring_type = nil, changed_by_script = false } source_states[source_name] = state end if state.last_muted == nil then state.last_muted = muted if monitoring ~= MONITOR_NONE then state.saved_monitoring_type = monitoring end if muted and monitoring ~= MONITOR_NONE then state.saved_monitoring_type = monitoring obs.obs_source_set_monitoring_type( source, MONITOR_NONE ) state.changed_by_script = true end obs.obs_source_release(source) else if muted and not state.last_muted then monitoring = obs.obs_source_get_monitoring_type(source) if monitoring ~= MONITOR_NONE then state.saved_monitoring_type = monitoring obs.obs_source_set_monitoring_type( source, MONITOR_NONE ) state.changed_by_script = true else state.changed_by_script = false end elseif not muted and state.last_muted then if state.changed_by_script and state.saved_monitoring_type ~= nil and state.saved_monitoring_type ~= MONITOR_NONE then obs.obs_source_set_monitoring_type( source, state.saved_monitoring_type ) end state.changed_by_script = false end if not muted then monitoring = obs.obs_source_get_monitoring_type(source) if monitoring ~= MONITOR_NONE then state.saved_monitoring_type = monitoring end end state.last_muted = muted obs.obs_source_release(source) end else source_states[source_name] = nil end end end end function refresh_button_clicked(props, property) obs.obs_properties_apply_settings( props, obs.obs_data_create() ) return true end function script_properties() local props = obs.obs_properties_create() obs.obs_properties_add_text( props, "instructions", "Selecione as fontes que devem sincronizar mute e monitoramento:", obs.OBS_TEXT_INFO ) local names = get_audio_source_names() if #names == 0 then obs.obs_properties_add_text( props, "no_sources", "Nenhuma fonte de áudio foi encontrada.", obs.OBS_TEXT_INFO ) else for _, name in ipairs(names) do obs.obs_properties_add_bool( props, safe_key(name), name ) end end obs.obs_properties_add_int_slider( props, "check_interval", "Intervalo de verificação (ms)", 50, 1000, 50 ) obs.obs_properties_add_button( props, "refresh_sources", "Atualizar lista de fontes", refresh_button_clicked ) return props end function script_defaults(settings) obs.obs_data_set_default_int( settings, "check_interval", 100 ) end function script_update(settings) obs.timer_remove(check_sources) check_interval = obs.obs_data_get_int(settings, "check_interval") if check_interval < 50 then check_interval = 50 end selected_sources = {} local names = get_audio_source_names() for _, name in ipairs(names) do local enabled = obs.obs_data_get_bool(settings, safe_key(name)) if enabled then selected_sources[name] = true end end remove_unselected_states() obs.timer_add(check_sources, check_interval) end function script_load(settings) script_update(settings) end function script_unload() obs.timer_remove(check_sources) for source_name, _ in pairs(source_states) do restore_source_monitoring(source_name) end source_states = {} end