LOOKING FOR Scene timeline scanner script

L

lindynasty71

Member
Joined
May 8, 2025
Messages
36
Reaction score
22
Points
8
In the old f95 thread, the one that got deleted, there was a script someone made that scanned desired folders for timeline scenes and you could even filter by length. Does anyone have it still? It was a python script, an updated version of Shallty's.
 
L

Latikaris

Member
Joined
Mar 7, 2025
Messages
15
Reaction score
22
Points
3
In the old f95 thread, the one that got deleted, there was a script someone made that scanned desired folders for timeline scenes and you could even filter by length. Does anyone have it still? It was a python script, an updated version of Shallty's.
Oh, I know exactly what you are looking for. I got it:

Python:
import ctypes
import glob
import os
import shutil

os.system('cls' if os.name == 'nt' else 'clear')
print("")
print("")
ctypes.windll.kernel32.SetConsoleTitleW("TIMELINE CHECKER")

input_path = 'C:/.../UserData/Studio/scene/folderIn'
output_path = 'C:/.../UserData/Studio/scene/folderOut'
timeline_length = 2.0

if not os.path.exists(output_path):
    os.makedirs(output_path)

print(f"\nSearching .png files...\n")
files = glob.glob(input_path + '/**/*.png', recursive=True)
total_files = len(files)

print(f"\n({total_files}) .png files founded.\n")
count = 0
tl_count = 0

check_list = ['cameraOPos"', 'cameraORot"', 'cameraOZoom"', 'cameraFOV"', 'cameraPos"', 'cameraRot"', 'timeScale"']

for current_file in files:
    has_time_greater_than_value = False
    if os.path.isfile(current_file):
        with open(current_file, 'rt', encoding="ansi") as fp:
            for index, line in enumerate(fp):
                if line.count("Timeline") >= 2:
                    if 'timeline' in line:
                        elements = line.strip().split()
                        for element in elements:
                            if 'time="' in element:
                                try:
                                    time_value = float(element.split('time="')[1].replace('"', ''))
                                    if time_value > timeline_length:
                                        has_time_greater_than_value = True
                                except ValueError:
                                    continue

                            if has_time_greater_than_value and 'id="' in element and not any(
                                    check_string in element for check_string in check_list):
                                tl_count += 1
                                file_name = os.path.split(current_file)
                                print('\nTimeline scene found: ' + file_name[1] + '\n')
                                fp.close()
                                shutil.move(current_file, output_path + '\\' + file_name[1])
                                break
                        else:
                            continue
                        break
            else:
                fp.close()
    count += 1
    print(f"\n({count}/{total_files}) Timeline scene count: [{tl_count}]\n")

print("\n╭⋟────────────────────────────────────────────────────────────────╮")
print(f'\n                 Total timeline scenes found: [{tl_count}/{total_files}]\n')
print("╰────────────────────────────────────────────────────────────────⋞╯\n\n")
 
L

lindynasty71

Member
Joined
May 8, 2025
Messages
36
Reaction score
22
Points
8
Oh, I know exactly what you are looking for. I got it:

Python:
import ctypes
import glob
import os
import shutil

os.system('cls' if os.name == 'nt' else 'clear')
print("")
print("")
ctypes.windll.kernel32.SetConsoleTitleW("TIMELINE CHECKER")

input_path = 'C:/.../UserData/Studio/scene/folderIn'
output_path = 'C:/.../UserData/Studio/scene/folderOut'
timeline_length = 2.0

if not os.path.exists(output_path):
    os.makedirs(output_path)

print(f"\nSearching .png files...\n")
files = glob.glob(input_path + '/**/*.png', recursive=True)
total_files = len(files)

print(f"\n({total_files}) .png files founded.\n")
count = 0
tl_count = 0

check_list = ['cameraOPos"', 'cameraORot"', 'cameraOZoom"', 'cameraFOV"', 'cameraPos"', 'cameraRot"', 'timeScale"']

for current_file in files:
    has_time_greater_than_value = False
    if os.path.isfile(current_file):
        with open(current_file, 'rt', encoding="ansi") as fp:
            for index, line in enumerate(fp):
                if line.count("Timeline") >= 2:
                    if 'timeline' in line:
                        elements = line.strip().split()
                        for element in elements:
                            if 'time="' in element:
                                try:
                                    time_value = float(element.split('time="')[1].replace('"', ''))
                                    if time_value > timeline_length:
                                        has_time_greater_than_value = True
                                except ValueError:
                                    continue

                            if has_time_greater_than_value and 'id="' in element and not any(
                                    check_string in element for check_string in check_list):
                                tl_count += 1
                                file_name = os.path.split(current_file)
                                print('\nTimeline scene found: ' + file_name[1] + '\n')
                                fp.close()
                                shutil.move(current_file, output_path + '\\' + file_name[1])
                                break
                        else:
                            continue
                        break
            else:
                fp.close()
    count += 1
    print(f"\n({count}/{total_files}) Timeline scene count: [{tl_count}]\n")

print("\n╭⋟────────────────────────────────────────────────────────────────╮")
print(f'\n                 Total timeline scenes found: [{tl_count}/{total_files}]\n')
print("╰────────────────────────────────────────────────────────────────⋞╯\n\n")
THANK YOU SO MUCH I THOUGHT IT WAS LOST MEDIA
 
kloeny233

kloeny233

Administrator
Staff member
Joined
Aug 21, 2024
Messages
60
Reaction score
436
Points
53
btw what does it do? identify the non timeline vs timeline scene?
Yes. The above one seems to have problems when I run it. I found another one.

Python:
import os
import shutil

class TimelineDetector:
    """
    The functionality of this class is identical to the original code you provided.
    It is responsible for analyzing the content of a single file to determine its type.
    """
    def __init__(self, file_path: str = None):
        self.file_path = file_path
        
    def is_scene_data(self, content_str: str) -> bool:
        """Checks if the content is scene data."""
        return "KStudio" in content_str
        
    def check_timeline(self, content_str: str) -> tuple[str, str, float]:
            """
            Checks the timeline type and returns the timeline status and duration.
            Returns:
                tuple (timeline_status, image_type, duration)
                timeline_status: "has_timeline" or "no_timeline"
                image_type: "dynamic", "static", or None
                duration: float or None
            """
            if "timeline" in content_str:  # First, check if "timeline" exists
                # Check if it's static (it's static if "Timeline" is not present)
                if "Timeline" not in content_str:
                    return "has_timeline", "static", None
                else:
                    # It's dynamic, now check for duration
                    if "duration" in content_str:
                        dur_pos = content_str.find("duration")
                        search_pos = dur_pos + len("duration")
                        
                        while search_pos < len(content_str):
                            if content_str[search_pos].isdigit():
                                num_start = search_pos
                                num_end = num_start
                                while num_end < len(content_str) and (content_str[num_end].isdigit() or content_str[num_end] == '.'):
                                    num_end += 1
                                try:
                                    duration = float(content_str[num_start:num_end])
                                    return "has_timeline", "dynamic", duration
                                except ValueError:
                                    return "has_timeline", "dynamic", None
                            search_pos += 1
                    return "has_timeline", "dynamic", None
            return "no_timeline", None, None

def batch_process_animated_images(input_dir: str, output_dir: str):
    """
    Iterates through the input directory, finds all dynamic images,
    and moves them to the output directory.

    Args:
        input_dir (str): The path to the source folder containing .png files.
        output_dir (str): The path to the destination folder for dynamic images.
    """
    # Ensure the output directory exists, create it if it doesn't
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
        print(f"Created output directory: {output_dir}")

    detector = TimelineDetector()
    animated_image_count = 0

    print(f"Starting scan of input directory: {input_dir}")
    print("Operation Mode: Move Files")

    # Iterate over all files in the input directory
    for filename in os.listdir(input_dir):
        # Only process .png files
        if filename.lower().endswith(".png"):
            file_path = os.path.join(input_dir, filename)
            
            # Skip subdirectories, process only files
            if not os.path.isfile(file_path):
                continue

            try:
                with open(file_path, 'rb') as f:
                    content = f.read()
                    content_str = content.decode('utf-8', errors='ignore')

                # 1. Check if it's valid scene data
                if not detector.is_scene_data(content_str):
                    print(f"Skipped (not scene data): {filename}")
                    continue
                
                # 2. Check the timeline status
                timeline_status, image_type, duration = detector.check_timeline(content_str)
                
                # 3. If it's a dynamic image with a timeline, move it
                if timeline_status == "has_timeline" and image_type == "dynamic":
                    destination_path = os.path.join(output_dir, filename)
                    # Use shutil.move to move the file
                    shutil.move(file_path, destination_path)
                    duration_info = f" (duration: {duration}s)" if duration is not None else ""
                    print(f"Found dynamic image, moved: {filename}{duration_info}")
                    animated_image_count += 1
                else:
                    print(f"Skipped (not a dynamic image): {filename}")

            except Exception as e:
                print(f"Error processing file {filename}: {e}")

    print("\nBatch processing complete.")
    print(f"Total files moved: {animated_image_count} dynamic images to {output_dir}")

def main():
    # ==================================================================
    # === Please configure your paths here ===
    # ==================================================================
    
    # Replace "Please_paste_your_full_input_directory_path_here" with the path to the folder containing your .png files.
    # Example (Windows): "C:\\Users\\YourUser\\Desktop\\input"
    # Example (macOS):   "/Users/YourUser/Desktop/input"
    INPUT_DIRECTORY = "Please_paste_your_full_input_directory_path_here"

    # Replace "Please_paste_your_full_output_directory_path_here" with the path to the folder where you want to store the dynamic images.
    # Example (Windows): "C:\\Users\\YourUser\\Desktop\\output_animated"
    # Example (macOS):   "/Users/YourUser/Desktop/output_animated"
    OUTPUT_DIRECTORY = "Please_paste_your_full_output_directory_path_here"

    # ==================================================================
    # === End of configuration. Please do not modify below this line. ===
    # ==================================================================

    # Check if the paths have been set
    if "Please_paste" in INPUT_DIRECTORY or "Please_paste" in OUTPUT_DIRECTORY:
        print("Error: You have not configured the input or output directory paths.")
        print("Please open this .py file with a text editor and fill in the values for INPUT_DIRECTORY and OUTPUT_DIRECTORY.")
        input("\nPress Enter to exit...")
        return
        
    # Check if the input path exists and is a directory
    if not os.path.isdir(INPUT_DIRECTORY):
        print(f"Error: The input path '{INPUT_DIRECTORY}' is not a valid directory.")
        input("\nPress Enter to exit...")
        return
        
    # Check if the input and output paths are the same
    if os.path.abspath(INPUT_DIRECTORY) == os.path.abspath(OUTPUT_DIRECTORY):
        print(f"Error: The input and output directories cannot be the same path.")
        input("\nPress Enter to exit...")
        return

    # Execute the batch process
    batch_process_animated_images(INPUT_DIRECTORY, OUTPUT_DIRECTORY)
    
    input("\nAll tasks are complete. Press Enter to exit...")

if __name__ == "__main__":
    main()
 
L

lindynasty71

Member
Joined
May 8, 2025
Messages
36
Reaction score
22
Points
8
Yes. The above one seems to have problems when I run it. I found another one.

Python:
import os
import shutil

class TimelineDetector:
    """
    The functionality of this class is identical to the original code you provided.
    It is responsible for analyzing the content of a single file to determine its type.
    """
    def __init__(self, file_path: str = None):
        self.file_path = file_path
       
    def is_scene_data(self, content_str: str) -> bool:
        """Checks if the content is scene data."""
        return "KStudio" in content_str
       
    def check_timeline(self, content_str: str) -> tuple[str, str, float]:
            """
            Checks the timeline type and returns the timeline status and duration.
            Returns:
                tuple (timeline_status, image_type, duration)
                timeline_status: "has_timeline" or "no_timeline"
                image_type: "dynamic", "static", or None
                duration: float or None
            """
            if "timeline" in content_str:  # First, check if "timeline" exists
                # Check if it's static (it's static if "Timeline" is not present)
                if "Timeline" not in content_str:
                    return "has_timeline", "static", None
                else:
                    # It's dynamic, now check for duration
                    if "duration" in content_str:
                        dur_pos = content_str.find("duration")
                        search_pos = dur_pos + len("duration")
                       
                        while search_pos < len(content_str):
                            if content_str[search_pos].isdigit():
                                num_start = search_pos
                                num_end = num_start
                                while num_end < len(content_str) and (content_str[num_end].isdigit() or content_str[num_end] == '.'):
                                    num_end += 1
                                try:
                                    duration = float(content_str[num_start:num_end])
                                    return "has_timeline", "dynamic", duration
                                except ValueError:
                                    return "has_timeline", "dynamic", None
                            search_pos += 1
                    return "has_timeline", "dynamic", None
            return "no_timeline", None, None

def batch_process_animated_images(input_dir: str, output_dir: str):
    """
    Iterates through the input directory, finds all dynamic images,
    and moves them to the output directory.

    Args:
        input_dir (str): The path to the source folder containing .png files.
        output_dir (str): The path to the destination folder for dynamic images.
    """
    # Ensure the output directory exists, create it if it doesn't
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
        print(f"Created output directory: {output_dir}")

    detector = TimelineDetector()
    animated_image_count = 0

    print(f"Starting scan of input directory: {input_dir}")
    print("Operation Mode: Move Files")

    # Iterate over all files in the input directory
    for filename in os.listdir(input_dir):
        # Only process .png files
        if filename.lower().endswith(".png"):
            file_path = os.path.join(input_dir, filename)
           
            # Skip subdirectories, process only files
            if not os.path.isfile(file_path):
                continue

            try:
                with open(file_path, 'rb') as f:
                    content = f.read()
                    content_str = content.decode('utf-8', errors='ignore')

                # 1. Check if it's valid scene data
                if not detector.is_scene_data(content_str):
                    print(f"Skipped (not scene data): {filename}")
                    continue
               
                # 2. Check the timeline status
                timeline_status, image_type, duration = detector.check_timeline(content_str)
               
                # 3. If it's a dynamic image with a timeline, move it
                if timeline_status == "has_timeline" and image_type == "dynamic":
                    destination_path = os.path.join(output_dir, filename)
                    # Use shutil.move to move the file
                    shutil.move(file_path, destination_path)
                    duration_info = f" (duration: {duration}s)" if duration is not None else ""
                    print(f"Found dynamic image, moved: {filename}{duration_info}")
                    animated_image_count += 1
                else:
                    print(f"Skipped (not a dynamic image): {filename}")

            except Exception as e:
                print(f"Error processing file {filename}: {e}")

    print("\nBatch processing complete.")
    print(f"Total files moved: {animated_image_count} dynamic images to {output_dir}")

def main():
    # ==================================================================
    # === Please configure your paths here ===
    # ==================================================================
   
    # Replace "Please_paste_your_full_input_directory_path_here" with the path to the folder containing your .png files.
    # Example (Windows): "C:\\Users\\YourUser\\Desktop\\input"
    # Example (macOS):   "/Users/YourUser/Desktop/input"
    INPUT_DIRECTORY = "Please_paste_your_full_input_directory_path_here"

    # Replace "Please_paste_your_full_output_directory_path_here" with the path to the folder where you want to store the dynamic images.
    # Example (Windows): "C:\\Users\\YourUser\\Desktop\\output_animated"
    # Example (macOS):   "/Users/YourUser/Desktop/output_animated"
    OUTPUT_DIRECTORY = "Please_paste_your_full_output_directory_path_here"

    # ==================================================================
    # === End of configuration. Please do not modify below this line. ===
    # ==================================================================

    # Check if the paths have been set
    if "Please_paste" in INPUT_DIRECTORY or "Please_paste" in OUTPUT_DIRECTORY:
        print("Error: You have not configured the input or output directory paths.")
        print("Please open this .py file with a text editor and fill in the values for INPUT_DIRECTORY and OUTPUT_DIRECTORY.")
        input("\nPress Enter to exit...")
        return
       
    # Check if the input path exists and is a directory
    if not os.path.isdir(INPUT_DIRECTORY):
        print(f"Error: The input path '{INPUT_DIRECTORY}' is not a valid directory.")
        input("\nPress Enter to exit...")
        return
       
    # Check if the input and output paths are the same
    if os.path.abspath(INPUT_DIRECTORY) == os.path.abspath(OUTPUT_DIRECTORY):
        print(f"Error: The input and output directories cannot be the same path.")
        input("\nPress Enter to exit...")
        return

    # Execute the batch process
    batch_process_animated_images(INPUT_DIRECTORY, OUTPUT_DIRECTORY)
   
    input("\nAll tasks are complete. Press Enter to exit...")

if __name__ == "__main__":
    main()
If you have trouble getting the first script to work, it was probably because the script uses \ and not / sometimes. Dunno why.
 
Top