obs = obslua -- ============================================================ -- OCULTAR FONTE/GRUPO QUANDO UMA MIDIA TERMINAR -- OBS Studio Lua Script -- ============================================================ rules = {} rule_count = 1 timer_interval_ms = 200 -- ------------------------------------------------------------ -- Utilidades -- ------------------------------------------------------------ local function log_info(msg) obs.script_log(obs.LOG_INFO, "[Ocultar ao terminar] " .. msg) end local function get_all_source_names() local names = {} local sources = obs.obs_enum_sources() if sources ~= nil then for _, source in ipairs(sources) do local name = obs.obs_source_get_name(source) if name ~= nil and name ~= "" then table.insert(names, name) 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 add_source_list(props, id, label) local p = obs.obs_properties_add_list( props, id, label, obs.OBS_COMBO_TYPE_LIST, obs.OBS_COMBO_FORMAT_STRING ) obs.obs_property_list_add_string(p, "-- selecione --", "") local names = get_all_source_names() for _, name in ipairs(names) do obs.obs_property_list_add_string(p, name, name) end return p end -- Procura e altera a visibilidade de uma fonte/grupo em uma cena, -- inclusive dentro de grupos. local function set_visible_recursive(scene, target_name, visible) if scene == nil or target_name == nil or target_name == "" then return false end local found = false local items = obs.obs_scene_enum_items(scene) if items ~= nil then for _, item in ipairs(items) do local source = obs.obs_sceneitem_get_source(item) if source ~= nil then local name = obs.obs_source_get_name(source) if name == target_name then obs.obs_sceneitem_set_visible(item, visible) found = true end -- Se for grupo, procura também dentro dele. if obs.obs_source_is_group(source) then local group_scene = obs.obs_group_from_source(source) if group_scene ~= nil then if set_visible_recursive(group_scene, target_name, visible) then found = true end end end end end obs.sceneitem_list_release(items) end return found end -- Oculta todas as ocorrências do alvo em todas as cenas. -- Isso evita depender de qual cena está atualmente no Program. local function hide_target_everywhere(target_name) if target_name == nil or target_name == "" then return false end local found = false local scenes = obs.obs_frontend_get_scenes() if scenes ~= nil then for _, scene_source in ipairs(scenes) do local scene = obs.obs_scene_from_source(scene_source) if scene ~= nil then if set_visible_recursive(scene, target_name, false) then found = true end end end obs.source_list_release(scenes) end return found end local function media_state(source_name) if source_name == nil or source_name == "" then return nil end local source = obs.obs_get_source_by_name(source_name) if source == nil then return nil end local state = obs.obs_source_media_get_state(source) obs.obs_source_release(source) return state end -- ------------------------------------------------------------ -- Monitoramento -- ------------------------------------------------------------ function check_rules() for i = 1, rule_count do local rule = rules[i] if rule ~= nil and rule.enabled and rule.media ~= nil and rule.media ~= "" and rule.target ~= nil and rule.target ~= "" then local state = media_state(rule.media) if state ~= nil then -- Só dispara uma vez por término. if state == obs.OBS_MEDIA_STATE_ENDED then if not rule.was_ended then local ok = hide_target_everywhere(rule.target) if ok then log_info( "Regra " .. i .. ": mídia '" .. rule.media .. "' terminou -> ocultando '" .. rule.target .. "'." ) else log_info( "Regra " .. i .. ": mídia terminou, mas o alvo '" .. rule.target .. "' não foi encontrado em nenhuma cena." ) end rule.was_ended = true end else -- Ao tocar/reiniciar/parar e voltar a reproduzir, -- deixa a regra armada para o próximo término. rule.was_ended = false end end end end end -- ------------------------------------------------------------ -- Interface -- ------------------------------------------------------------ MAX_RULES = 20 properties_ref = nil local function set_rule_visible(props, i, visible) local ids = { "enabled_" .. i, "media_" .. i, "target_" .. i, "sep_" .. i } for _, id in ipairs(ids) do local p = obs.obs_properties_get(props, id) if p ~= nil then obs.obs_property_set_visible(p, visible) end end end function refresh_rule_visibility(props) if props == nil then return end for i = 1, MAX_RULES do set_rule_visible(props, i, i <= rule_count) end end function add_rule_button_clicked(props, prop) if rule_count < MAX_RULES then rule_count = rule_count + 1 refresh_rule_visibility(props) log_info("Nova regra adicionada: " .. rule_count) end return true end function remove_rule_button_clicked(props, prop) if rule_count > 1 then -- Limpa a regra que está sendo removida da memória de execução. if rules[rule_count] ~= nil then rules[rule_count].enabled = false rules[rule_count].media = "" rules[rule_count].target = "" rules[rule_count].was_ended = false end rule_count = rule_count - 1 refresh_rule_visibility(props) log_info("Última regra removida. Total: " .. rule_count) end return true end function script_properties() local props = obs.obs_properties_create() properties_ref = props obs.obs_properties_add_text( props, "info", "QUANDO A MÍDIA TERMINAR → OCULTAR FONTE/GRUPO.\nUse + para abrir uma nova regra.", obs.OBS_TEXT_INFO ) -- Criamos todas as propriedades uma única vez. -- O botão + apenas revela a próxima. Isso funciona de forma -- mais confiável no painel de Scripts do OBS. for i = 1, MAX_RULES do obs.obs_properties_add_bool( props, "enabled_" .. i, "Regra " .. i .. " - Ativa" ) add_source_list( props, "media_" .. i, "Mídia monitorada " .. i ) add_source_list( props, "target_" .. i, "Ocultar quando terminar " .. i ) obs.obs_properties_add_text( props, "sep_" .. i, "────────────────────────────────────", obs.OBS_TEXT_INFO ) end obs.obs_properties_add_button( props, "add_rule", "+ ADICIONAR NOVA REGRA", add_rule_button_clicked ) obs.obs_properties_add_button( props, "remove_rule", "− REMOVER ÚLTIMA REGRA", remove_rule_button_clicked ) refresh_rule_visibility(props) return props end function script_defaults(settings) for i = 1, MAX_RULES do obs.obs_data_set_default_bool(settings, "enabled_" .. i, true) obs.obs_data_set_default_string(settings, "media_" .. i, "") obs.obs_data_set_default_string(settings, "target_" .. i, "") end end function script_update(settings) rules = {} for i = 1, MAX_RULES do rules[i] = { enabled = obs.obs_data_get_bool(settings, "enabled_" .. i), media = obs.obs_data_get_string(settings, "media_" .. i), target = obs.obs_data_get_string(settings, "target_" .. i), was_ended = false } end end function script_load(settings) rule_count = 1 -- Se já existirem regras preenchidas salvas, reabre até a última. for i = 2, MAX_RULES do local media = obs.obs_data_get_string(settings, "media_" .. i) local target = obs.obs_data_get_string(settings, "target_" .. i) if (media ~= nil and media ~= "") or (target ~= nil and target ~= "") then rule_count = i end end script_update(settings) obs.timer_add(check_rules, timer_interval_ms) log_info("Script carregado.") end function script_unload() obs.timer_remove(check_rules) end function script_description() return [[ OCULTAR FONTE/GRUPO QUANDO UMA MÍDIA TERMINAR Exemplo: Mídia monitorada: MUSICA VITORIA Ocultar quando terminar: PASTA VITORIA Quando a mídia chega ao final, o OBS desativa a visibilidade da fonte ou grupo escolhido. Use o botão + para criar várias regras independentes. ]] end