Advertisement
firef0x

File Collector for OBS

Jan 23rd, 2025
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.92 KB | Software | 0 0
  1. -- OBS File Collector Script
  2. -- This script collects all local files used in OBS sources and filters
  3. -- and copies them to a specified directory
  4.  
  5. local obs = obslua
  6. local ffi = require("ffi")
  7.  
  8. -- Windows-specific FFI declarations for file operations
  9. ffi.cdef[[
  10.     int CreateDirectoryA(const char* lpPathName, void* lpSecurityAttributes);
  11.     int CopyFileA(const char* lpExistingFileName, const char* lpNewFileName, int bFailIfExists);
  12. ]]
  13.  
  14. -- Mac-specific FFI declarations for file operations
  15. ffi.cdef[[
  16.     int mkdir(const char* pathname, int mode);
  17. ]]
  18.  
  19. -- Global variables
  20. local collected_files = {}
  21. local target_directory = ""
  22.  
  23. -- Helper function to check if a file exists
  24. function file_exists(file_path)
  25.     local f = io.open(file_path, "r")
  26.     if f then
  27.         f:close()
  28.         return true
  29.     end
  30.     return false
  31. end
  32.  
  33. -- Helper function to process file path
  34. function process_file_path(file_path)
  35.     if file_path and file_path ~= "" then
  36.         -- Convert path separators to match the current OS
  37.         local normalized_path = file_path:gsub([[\]], "/")
  38.         -- Add to collection if not already present
  39.         if not collected_files[normalized_path] then
  40.             collected_files[normalized_path] = true
  41.             print("Found file: " .. normalized_path)
  42.         end
  43.     end
  44. end
  45.  
  46. -- Helper function to copy a file
  47. function copy_file(source_path, dest_path)
  48.     -- Normalize paths for cross-platform compatibility
  49.     source_path = source_path:gsub([[\]], "/")
  50.     dest_path = dest_path:gsub([[\]], "/")
  51.    
  52.     if not file_exists(source_path) then
  53.         print("Source file not found: " .. source_path)
  54.         return false
  55.     end
  56.  
  57.     -- Create target directory if it doesn't exist
  58.     local dir = dest_path:match("(.*)/")
  59.     if dir then
  60.         -- Create all parent directories recursively
  61.         local current_dir = ""
  62.         for part in dir:gmatch("([^/]+)") do
  63.             current_dir = current_dir .. part .. "/"
  64.             if ffi.os == "Windows" then
  65.                 ffi.C.CreateDirectoryA(current_dir:gsub("/", "\\"), nil)
  66.             else
  67.                 ffi.C.mkdir(current_dir, 0x1ED)
  68.             end
  69.         end
  70.     end
  71.  
  72.     -- Copy the file using Lua's io facilities (works cross-platform)
  73.     local success = false
  74.     local source = io.open(source_path, "rb")
  75.     if source then
  76.         local dest = io.open(dest_path, "wb")
  77.         if dest then
  78.             success = true
  79.             local chunk_size = 8192
  80.             while true do
  81.                 local chunk = source:read(chunk_size)
  82.                 if not chunk then break end
  83.                 dest:write(chunk)
  84.             end
  85.             dest:close()
  86.         end
  87.         source:close()
  88.     end
  89.     return success
  90. end
  91.  
  92. -- Function to process source settings
  93. function process_source_settings(settings)
  94.     if not settings then return end
  95.    
  96.     -- Get all properties of the source
  97.     local properties = obs.obs_properties_create()
  98.     if properties then
  99.         -- Known file properties for different source types
  100.         local common_file_properties = {
  101.             "local_file",
  102.             "file",
  103.             "path",
  104.             "script_path",
  105.             "lua_script",  -- Added for Lua script sources
  106.             "python_script",  -- Added for Python script sources
  107.             "js_script"  -- Added for JavaScript script sources
  108.         }
  109.        
  110.         for _, prop_name in ipairs(common_file_properties) do
  111.             local path = obs.obs_data_get_string(settings, prop_name)
  112.             if path and path ~= "" then
  113.                 process_file_path(path)
  114.             end
  115.         end
  116.        
  117.         obs.obs_properties_destroy(properties)
  118.     end
  119. end
  120.  
  121. -- Function to process filters
  122. function process_filters(source, scene_name, source_name, scene_printed)
  123.     local filters = obs.obs_source_enum_filters(source)
  124.     for _, filter in ipairs(filters) do
  125.         local filter_name = obs.obs_source_get_name(filter)
  126.         local filter_id = obs.obs_source_get_id(filter)
  127.         local settings = obs.obs_source_get_settings(filter)
  128.         local filter_printed = false
  129.        
  130.         -- Common file properties to check for all filter types
  131.         local file_properties = {
  132.             "file",              -- For image files
  133.             "local_file",        -- For media files
  134.             "path",             -- Generic path property
  135.             "image_path",       -- For image masks
  136.             "mask_path",        -- For mask filters
  137.             "lut_file",         -- For LUT/color correction filters
  138.             "image_file"        -- For image files
  139.         }
  140.        
  141.         -- Check all possible file properties for any filter type
  142.         for _, prop_name in ipairs(file_properties) do
  143.             local file_path = obs.obs_data_get_string(settings, prop_name)
  144.             if file_path and file_path ~= "" then
  145.                 if not scene_printed then
  146.                     print("\nScene: " .. scene_name)
  147.                     scene_printed = true
  148.                 end
  149.                 if not filter_printed then
  150.                     print("\n  Source: " .. source_name)
  151.                     print("    Filter: " .. filter_name .. " (" .. filter_id .. ")")
  152.                     filter_printed = true
  153.                 end
  154.                 print("    File (" .. prop_name .. "): " .. tostring(file_path))
  155.                 collected_files[file_path] = "filter"
  156.             end
  157.         end
  158.        
  159.         obs.obs_data_release(settings)
  160.     end
  161.     obs.source_list_release(filters)
  162.     return scene_printed
  163. end
  164.  
  165. -- Add this new function to process groups
  166. function process_group_sources(group_source)
  167.     local scene = obs.obs_group_from_source(group_source)
  168.     if scene then
  169.         local items = obs.obs_scene_enum_items(scene)
  170.         if items then
  171.             for _, item in ipairs(items) do
  172.                 local source = obs.obs_sceneitem_get_source(item)
  173.                 if source then
  174.                     local source_id = obs.obs_source_get_id(source)
  175.                     local settings = obs.obs_source_get_settings(source)
  176.                    
  177.                     -- Process the source settings
  178.                     process_source_settings(settings)
  179.                    
  180.                     -- If this is another group, process it recursively
  181.                     if source_id == "group" then
  182.                         process_group_sources(source)
  183.                     end
  184.                    
  185.                     -- Process filters
  186.                     process_filters(source, "Group", obs.obs_source_get_name(source), false)
  187.                    
  188.                     obs.obs_data_release(settings)
  189.                 end
  190.             end
  191.             obs.sceneitem_list_release(items)
  192.         end
  193.     end
  194. end
  195.  
  196. -- Function to collect files from all sources
  197. function collect_files()
  198.     -- First get all scenes
  199.     local scenes = obs.obs_frontend_get_scenes()
  200.     if scenes then
  201.         print("\n=== Collecting Files ===")
  202.         for _, scene in ipairs(scenes) do
  203.             local scene_name = obs.obs_source_get_name(scene)
  204.             local scene_printed = false
  205.            
  206.             -- Get scene items in this scene
  207.             local scene_items = obs.obs_scene_from_source(scene)
  208.             if scene_items then
  209.                 local items = obs.obs_scene_enum_items(scene_items)
  210.                 if items then
  211.                     for _, item in ipairs(items) do
  212.                         local source = obs.obs_sceneitem_get_source(item)
  213.                         local source_name = obs.obs_source_get_name(source)
  214.                         local source_id = obs.obs_source_get_id(source)
  215.                         local has_files = false
  216.                        
  217.                         local settings = obs.obs_source_get_settings(source)
  218.                        
  219.                         -- Process based on source type
  220.                         if source_id == "group" then
  221.                             -- Process group sources
  222.                             process_group_sources(source)
  223.                         elseif source_id == "ffmpeg_source" then
  224.                             local local_file = obs.obs_data_get_string(settings, "local_file")
  225.                             if local_file and local_file ~= "" then
  226.                                 if not scene_printed then
  227.                                     print("\nScene: " .. scene_name)
  228.                                     scene_printed = true
  229.                                 end
  230.                                 print("\n  Source: " .. source_name)
  231.                                 print("  Media file: " .. tostring(local_file))
  232.                                 process_file_path(local_file)
  233.                                 has_files = true
  234.                             end
  235.                         elseif source_id == "image_source" then
  236.                             local file = obs.obs_data_get_string(settings, "file")
  237.                             if file and file ~= "" then
  238.                                 if not scene_printed then
  239.                                     print("\nScene: " .. scene_name)
  240.                                     scene_printed = true
  241.                                 end
  242.                                 print("\n  Source: " .. source_name)
  243.                                 print("  Image file: " .. tostring(file))
  244.                                 process_file_path(file)
  245.                                 has_files = true
  246.                             end
  247.                         elseif source_id == "browser_source" then
  248.                             local is_local_file = obs.obs_data_get_bool(settings, "is_local_file")
  249.                             local local_file = obs.obs_data_get_string(settings, "local_file")
  250.                            
  251.                             if is_local_file and local_file and local_file ~= "" then
  252.                                 if not scene_printed then
  253.                                     print("\nScene: " .. scene_name)
  254.                                     scene_printed = true
  255.                                 end
  256.                                 print("\n  Source: " .. source_name)
  257.                                 print("  Browser file: " .. tostring(local_file))
  258.                                
  259.                                 -- Process the HTML file
  260.                                 process_file_path(local_file)
  261.                                 has_files = true
  262.                                
  263.                                 -- Try to read the HTML file to find linked resources
  264.                                 local f = io.open(local_file, "r")
  265.                                 if f then
  266.                                     local content = f:read("*all")
  267.                                     f:close()
  268.                                    
  269.                                     -- Get the directory of the HTML file
  270.                                     local dir = local_file:match("(.*[/\\])")
  271.                                    
  272.                                     -- Look for local resources in the HTML
  273.                                     for resource in content:gmatch('src="([^"]+)"') do
  274.                                         if not resource:match("^https?://") then
  275.                                             -- This is a local resource
  276.                                             local resource_path = dir .. resource
  277.                                             print("    Found resource: " .. resource_path)
  278.                                             process_file_path(resource_path)
  279.                                         end
  280.                                     end
  281.                                    
  282.                                     -- Also look for CSS files
  283.                                     for css in content:gmatch('href="([^"]+%.css)"') do
  284.                                         if not css:match("^https?://") then
  285.                                             local css_path = dir .. css
  286.                                             print("    Found CSS: " .. css_path)
  287.                                             process_file_path(css_path)
  288.                                         end
  289.                                     end
  290.                                 end
  291.                             end
  292.                         elseif source_id == "script_source" then
  293.                             local script_path = obs.obs_data_get_string(settings, "script_path")
  294.                             if script_path and script_path ~= "" then
  295.                                 if not scene_printed then
  296.                                     print("\nScene: " .. scene_name)
  297.                                     scene_printed = true
  298.                                 end
  299.                                 print("\n  Source: " .. source_name)
  300.                                 print("  Script file: " .. tostring(script_path))
  301.                                 process_file_path(script_path)
  302.                                 has_files = true
  303.                             end
  304.                         end
  305.                        
  306.                         -- Process filters
  307.                         scene_printed = process_filters(source, scene_name, source_name, scene_printed)
  308.                        
  309.                         obs.obs_data_release(settings)
  310.                     end
  311.                     obs.sceneitem_list_release(items)
  312.                 end
  313.             end
  314.         end
  315.         obs.source_list_release(scenes)
  316.     end
  317. end
  318.  
  319. -- Function to copy collected files
  320. function copy_collected_files()
  321.     local copied_count = 0
  322.     local failed_count = 0
  323.    
  324.     -- Create media and filter_files directories with proper path separators
  325.     local path_sep = ffi.os == "Windows" and "\\" or "/"
  326.     local media_dir = target_directory .. path_sep .. "media"
  327.     local filter_dir = target_directory .. path_sep .. "filter_files"
  328.    
  329.     -- Create base directories
  330.     if ffi.os == "Windows" then
  331.         ffi.C.CreateDirectoryA(media_dir:gsub("/", "\\"), nil)
  332.         ffi.C.CreateDirectoryA(filter_dir:gsub("/", "\\"), nil)
  333.     else
  334.         ffi.C.mkdir(media_dir, 0x1ED)
  335.         ffi.C.mkdir(filter_dir, 0x1ED)
  336.     end
  337.    
  338.     for file_path, file_type in pairs(collected_files) do
  339.         local file_name = file_path:match("([^/\\]+)$")
  340.         local dest_path
  341.        
  342.         if file_type == "filter" then
  343.             dest_path = filter_dir .. path_sep .. file_name
  344.         else
  345.             dest_path = media_dir .. path_sep .. file_name
  346.         end
  347.        
  348.         if copy_file(file_path, dest_path) then
  349.             copied_count = copied_count + 1
  350.             print("Copied: " .. file_path .. " -> " .. dest_path)
  351.         else
  352.             failed_count = failed_count + 1
  353.             print("Failed to copy: " .. file_path)
  354.         end
  355.     end
  356.    
  357.     return copied_count, failed_count
  358. end
  359.  
  360. -- Script hook functions
  361. function script_description()
  362.     return [[Collects and copies all local files used in OBS sources and filters to a specified directory.
  363.  
  364. Author: Barathi Kasiraja
  365. Date  : 2025-01-19]]
  366. end
  367.  
  368. function script_properties()
  369.     local props = obs.obs_properties_create()
  370.    
  371.     obs.obs_properties_add_path(props, "target_directory", "Target Directory",
  372.         obs.OBS_PATH_DIRECTORY, "", nil)
  373.    
  374.     obs.obs_properties_add_button(props, "collect_button", "Collect Files",
  375.         function()
  376.             if target_directory == "" then
  377.                 print("Please select a target directory first!")
  378.                 return false
  379.             end
  380.            
  381.             collected_files = {}
  382.             collect_files()
  383.            
  384.             local copied, failed = copy_collected_files()
  385.             print(string.format("Collection complete! Copied: %d, Failed: %d", copied, failed))
  386.            
  387.             return true
  388.         end)
  389.    
  390.     return props
  391. end
  392.  
  393. function script_update(settings)
  394.     target_directory = obs.obs_data_get_string(settings, "target_directory")
  395. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement