Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- OBS File Collector Script
- -- This script collects all local files used in OBS sources and filters
- -- and copies them to a specified directory
- local obs = obslua
- local ffi = require("ffi")
- -- Windows-specific FFI declarations for file operations
- ffi.cdef[[
- int CreateDirectoryA(const char* lpPathName, void* lpSecurityAttributes);
- int CopyFileA(const char* lpExistingFileName, const char* lpNewFileName, int bFailIfExists);
- ]]
- -- Mac-specific FFI declarations for file operations
- ffi.cdef[[
- int mkdir(const char* pathname, int mode);
- ]]
- -- Global variables
- local collected_files = {}
- local target_directory = ""
- -- Helper function to check if a file exists
- function file_exists(file_path)
- local f = io.open(file_path, "r")
- if f then
- f:close()
- return true
- end
- return false
- end
- -- Helper function to process file path
- function process_file_path(file_path)
- if file_path and file_path ~= "" then
- -- Convert path separators to match the current OS
- local normalized_path = file_path:gsub([[\]], "/")
- -- Add to collection if not already present
- if not collected_files[normalized_path] then
- collected_files[normalized_path] = true
- print("Found file: " .. normalized_path)
- end
- end
- end
- -- Helper function to copy a file
- function copy_file(source_path, dest_path)
- -- Normalize paths for cross-platform compatibility
- source_path = source_path:gsub([[\]], "/")
- dest_path = dest_path:gsub([[\]], "/")
- if not file_exists(source_path) then
- print("Source file not found: " .. source_path)
- return false
- end
- -- Create target directory if it doesn't exist
- local dir = dest_path:match("(.*)/")
- if dir then
- -- Create all parent directories recursively
- local current_dir = ""
- for part in dir:gmatch("([^/]+)") do
- current_dir = current_dir .. part .. "/"
- if ffi.os == "Windows" then
- ffi.C.CreateDirectoryA(current_dir:gsub("/", "\\"), nil)
- else
- ffi.C.mkdir(current_dir, 0x1ED)
- end
- end
- end
- -- Copy the file using Lua's io facilities (works cross-platform)
- local success = false
- local source = io.open(source_path, "rb")
- if source then
- local dest = io.open(dest_path, "wb")
- if dest then
- success = true
- local chunk_size = 8192
- while true do
- local chunk = source:read(chunk_size)
- if not chunk then break end
- dest:write(chunk)
- end
- dest:close()
- end
- source:close()
- end
- return success
- end
- -- Function to process source settings
- function process_source_settings(settings)
- if not settings then return end
- -- Get all properties of the source
- local properties = obs.obs_properties_create()
- if properties then
- -- Known file properties for different source types
- local common_file_properties = {
- "local_file",
- "file",
- "path",
- "script_path",
- "lua_script", -- Added for Lua script sources
- "python_script", -- Added for Python script sources
- "js_script" -- Added for JavaScript script sources
- }
- for _, prop_name in ipairs(common_file_properties) do
- local path = obs.obs_data_get_string(settings, prop_name)
- if path and path ~= "" then
- process_file_path(path)
- end
- end
- obs.obs_properties_destroy(properties)
- end
- end
- -- Function to process filters
- function process_filters(source, scene_name, source_name, scene_printed)
- local filters = obs.obs_source_enum_filters(source)
- for _, filter in ipairs(filters) do
- local filter_name = obs.obs_source_get_name(filter)
- local filter_id = obs.obs_source_get_id(filter)
- local settings = obs.obs_source_get_settings(filter)
- local filter_printed = false
- -- Common file properties to check for all filter types
- local file_properties = {
- "file", -- For image files
- "local_file", -- For media files
- "path", -- Generic path property
- "image_path", -- For image masks
- "mask_path", -- For mask filters
- "lut_file", -- For LUT/color correction filters
- "image_file" -- For image files
- }
- -- Check all possible file properties for any filter type
- for _, prop_name in ipairs(file_properties) do
- local file_path = obs.obs_data_get_string(settings, prop_name)
- if file_path and file_path ~= "" then
- if not scene_printed then
- print("\nScene: " .. scene_name)
- scene_printed = true
- end
- if not filter_printed then
- print("\n Source: " .. source_name)
- print(" Filter: " .. filter_name .. " (" .. filter_id .. ")")
- filter_printed = true
- end
- print(" File (" .. prop_name .. "): " .. tostring(file_path))
- collected_files[file_path] = "filter"
- end
- end
- obs.obs_data_release(settings)
- end
- obs.source_list_release(filters)
- return scene_printed
- end
- -- Add this new function to process groups
- function process_group_sources(group_source)
- local scene = obs.obs_group_from_source(group_source)
- if scene then
- local items = obs.obs_scene_enum_items(scene)
- if items then
- for _, item in ipairs(items) do
- local source = obs.obs_sceneitem_get_source(item)
- if source then
- local source_id = obs.obs_source_get_id(source)
- local settings = obs.obs_source_get_settings(source)
- -- Process the source settings
- process_source_settings(settings)
- -- If this is another group, process it recursively
- if source_id == "group" then
- process_group_sources(source)
- end
- -- Process filters
- process_filters(source, "Group", obs.obs_source_get_name(source), false)
- obs.obs_data_release(settings)
- end
- end
- obs.sceneitem_list_release(items)
- end
- end
- end
- -- Function to collect files from all sources
- function collect_files()
- -- First get all scenes
- local scenes = obs.obs_frontend_get_scenes()
- if scenes then
- print("\n=== Collecting Files ===")
- for _, scene in ipairs(scenes) do
- local scene_name = obs.obs_source_get_name(scene)
- local scene_printed = false
- -- Get scene items in this scene
- local scene_items = obs.obs_scene_from_source(scene)
- if scene_items then
- local items = obs.obs_scene_enum_items(scene_items)
- if items then
- for _, item in ipairs(items) do
- local source = obs.obs_sceneitem_get_source(item)
- local source_name = obs.obs_source_get_name(source)
- local source_id = obs.obs_source_get_id(source)
- local has_files = false
- local settings = obs.obs_source_get_settings(source)
- -- Process based on source type
- if source_id == "group" then
- -- Process group sources
- process_group_sources(source)
- elseif source_id == "ffmpeg_source" then
- local local_file = obs.obs_data_get_string(settings, "local_file")
- if local_file and local_file ~= "" then
- if not scene_printed then
- print("\nScene: " .. scene_name)
- scene_printed = true
- end
- print("\n Source: " .. source_name)
- print(" Media file: " .. tostring(local_file))
- process_file_path(local_file)
- has_files = true
- end
- elseif source_id == "image_source" then
- local file = obs.obs_data_get_string(settings, "file")
- if file and file ~= "" then
- if not scene_printed then
- print("\nScene: " .. scene_name)
- scene_printed = true
- end
- print("\n Source: " .. source_name)
- print(" Image file: " .. tostring(file))
- process_file_path(file)
- has_files = true
- end
- elseif source_id == "browser_source" then
- local is_local_file = obs.obs_data_get_bool(settings, "is_local_file")
- local local_file = obs.obs_data_get_string(settings, "local_file")
- if is_local_file and local_file and local_file ~= "" then
- if not scene_printed then
- print("\nScene: " .. scene_name)
- scene_printed = true
- end
- print("\n Source: " .. source_name)
- print(" Browser file: " .. tostring(local_file))
- -- Process the HTML file
- process_file_path(local_file)
- has_files = true
- -- Try to read the HTML file to find linked resources
- local f = io.open(local_file, "r")
- if f then
- local content = f:read("*all")
- f:close()
- -- Get the directory of the HTML file
- local dir = local_file:match("(.*[/\\])")
- -- Look for local resources in the HTML
- for resource in content:gmatch('src="([^"]+)"') do
- if not resource:match("^https?://") then
- -- This is a local resource
- local resource_path = dir .. resource
- print(" Found resource: " .. resource_path)
- process_file_path(resource_path)
- end
- end
- -- Also look for CSS files
- for css in content:gmatch('href="([^"]+%.css)"') do
- if not css:match("^https?://") then
- local css_path = dir .. css
- print(" Found CSS: " .. css_path)
- process_file_path(css_path)
- end
- end
- end
- end
- elseif source_id == "script_source" then
- local script_path = obs.obs_data_get_string(settings, "script_path")
- if script_path and script_path ~= "" then
- if not scene_printed then
- print("\nScene: " .. scene_name)
- scene_printed = true
- end
- print("\n Source: " .. source_name)
- print(" Script file: " .. tostring(script_path))
- process_file_path(script_path)
- has_files = true
- end
- end
- -- Process filters
- scene_printed = process_filters(source, scene_name, source_name, scene_printed)
- obs.obs_data_release(settings)
- end
- obs.sceneitem_list_release(items)
- end
- end
- end
- obs.source_list_release(scenes)
- end
- end
- -- Function to copy collected files
- function copy_collected_files()
- local copied_count = 0
- local failed_count = 0
- -- Create media and filter_files directories with proper path separators
- local path_sep = ffi.os == "Windows" and "\\" or "/"
- local media_dir = target_directory .. path_sep .. "media"
- local filter_dir = target_directory .. path_sep .. "filter_files"
- -- Create base directories
- if ffi.os == "Windows" then
- ffi.C.CreateDirectoryA(media_dir:gsub("/", "\\"), nil)
- ffi.C.CreateDirectoryA(filter_dir:gsub("/", "\\"), nil)
- else
- ffi.C.mkdir(media_dir, 0x1ED)
- ffi.C.mkdir(filter_dir, 0x1ED)
- end
- for file_path, file_type in pairs(collected_files) do
- local file_name = file_path:match("([^/\\]+)$")
- local dest_path
- if file_type == "filter" then
- dest_path = filter_dir .. path_sep .. file_name
- else
- dest_path = media_dir .. path_sep .. file_name
- end
- if copy_file(file_path, dest_path) then
- copied_count = copied_count + 1
- print("Copied: " .. file_path .. " -> " .. dest_path)
- else
- failed_count = failed_count + 1
- print("Failed to copy: " .. file_path)
- end
- end
- return copied_count, failed_count
- end
- -- Script hook functions
- function script_description()
- return [[Collects and copies all local files used in OBS sources and filters to a specified directory.
- Author: Barathi Kasiraja
- Date : 2025-01-19]]
- end
- function script_properties()
- local props = obs.obs_properties_create()
- obs.obs_properties_add_path(props, "target_directory", "Target Directory",
- obs.OBS_PATH_DIRECTORY, "", nil)
- obs.obs_properties_add_button(props, "collect_button", "Collect Files",
- function()
- if target_directory == "" then
- print("Please select a target directory first!")
- return false
- end
- collected_files = {}
- collect_files()
- local copied, failed = copy_collected_files()
- print(string.format("Collection complete! Copied: %d, Failed: %d", copied, failed))
- return true
- end)
- return props
- end
- function script_update(settings)
- target_directory = obs.obs_data_get_string(settings, "target_directory")
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement