feat(v5.1): Asynchronous architecture, Preferences redesign, and RIFE padding fix.
This commit is contained in:
@@ -1,2 +1 @@
|
||||
Download the AI-onnx.zip file from the releases section, prioritizing the latest available version.
|
||||
https://github.com/Ivan-Ayub97/Warlock-Studio/releases/download/v5.0/AI-onnx.zip
|
||||
|
||||
Binary file not shown.
+229
-167
@@ -1,18 +1,80 @@
|
||||
# Warlock-Studio - Comprehensive Changelog History
|
||||
_Warlock-Studio | Changelog History_
|
||||
|
||||
# Version 5.1
|
||||
|
||||
**Release date:** December 11, 2025
|
||||
**Kernel Version:** 5.1.0 (Codename: Asynchronous-Warlock)
|
||||
**Architecture:** Distributed / Multi-Threaded UI
|
||||
|
||||
### Asynchronous I/O Architecture & File Queue System
|
||||
|
||||
The application's file ingestion and management layer has been architecturally decoupled from the main GUI thread. The legacy synchronous file loader has been deprecated in favor of a reactive, non-blocking subsystem driven by the new **`file_queue_manager.py`** module.
|
||||
|
||||
#### Multi-Threaded Ingestion Pipeline (`FileQueueManager`)
|
||||
|
||||
- **Parallelized Metadata Extraction:** Implemented a `ThreadPoolExecutor` worker pool strategy. Heavy I/O operations—including `cv2.VideoCapture` metadata reading, frame extraction, and resolution calculation—are now offloaded to background threads, eliminating UI freezes ("Application Not Responding") during batch imports.
|
||||
- **Thread-Safe Message Bus:** A `queue.Queue` messaging pattern was established to marshal data between worker threads and the main Tkinter loop. The `_check_queue` polling mechanism ensures atomic widget updates, preventing race conditions and segmentation faults common in multi-threaded GUI applications.
|
||||
- **Object-Oriented State Encapsulation:** Introduced the `QueueItem` class to encapsulate file-specific state (loading status, error flags, thumbnail blobs, and resolution metrics). This allows for granular error handling where a single corrupt file no longer halts the entire batch loading process.
|
||||
- **Lazy Thumbnail Generation:** Video and image thumbnails are now generated and cached asynchronously using a secure `PIL` <-> `OpenCV` bridge, reducing initial memory footprint during large batch operations.
|
||||
|
||||
#### Viewport State Management (Main Orchestrator)
|
||||
|
||||
- **Dynamic View Switching:** The main application logic now implements explicit view controllers (`show_drop_zone` and `show_file_manager`) to seamlessly toggle between the "Drag & Drop" landing state and the active "Queue Management" interface.
|
||||
- **Drop Zone Expansion:** The drag-and-drop event listeners have been registered across the entire container hierarchy (`drop_zone_frame`, buttons, labels), eliminating "dead zones" where file drops were previously ignored.
|
||||
|
||||
### Preferences System Re-engineering
|
||||
|
||||
The configuration subsystem (`warlock_preferences.py`) has been rewritten from the ground up, abandoning the linear vertical scrolling design for a categorized **Sidebar Navigation Architecture**.
|
||||
|
||||
#### Diagnostic & Maintenance Suite
|
||||
|
||||
- **Integrated Log Viewer:** Embedded a read-only `CTkTextbox` that dynamically streams the content of the active `warlock_studio.log` file. Users can now audit FFmpeg stderr output and internal errors directly within the GUI without navigating the host file system.
|
||||
- **Debug Package Export:** Introduced the `export_debug_info` routine. This function aggregates the current JSON configuration, recent log files, and system hardware telemetry into a timestamped `.zip` archive, streamlining the bug reporting process for developers.
|
||||
- **Binary Path Overrides:** Added manual path selectors for `ffmpeg.exe` and `exiftool.exe`. This resolves path resolution conflicts on systems with non-standard environment variables or portable deployments.
|
||||
|
||||
#### Hardware & Execution Configuration
|
||||
|
||||
- **Strict ONNX Provider Enforcement:** Implemented a user-accessible selector for the AI Execution Backend (`Auto`, `CUDA`, `DirectML`, `CPU`). This allows users to forcefully bypass the internal driver heuristic engine if automatic detection fails on hybrid GPU setups.
|
||||
- **Refined "NEO Engine":** The hardware scanning logic was optimized to prioritize `GPUtil` direct querying for NVIDIA GPUs while maintaining a robust WMI/WQL fallback chain for AMD and Intel architectures, ensuring accurate VRAM reporting.
|
||||
|
||||
### AI Algorithm Precision & Mathematical Corrections
|
||||
|
||||
#### RIFE Dynamic Padding (Artifact Elimination)
|
||||
|
||||
Resolved a critical mathematical deficiency in the RIFE (Real-Time Intermediate Flow Estimation) interpolation pipeline where input resolutions not divisible by 32 generated black banding or green-screen artifacts.
|
||||
|
||||
- **Reflective Padding Logic:** Implemented `pad_image_to_divisor` within the `AI_interpolation` class. This routine calculates the modulo-32 remainder and dynamically applies reflective border padding (`cv2.copyMakeBorder`) to the input tensor before inference.
|
||||
- **Surgical Post-Inference Cropping:** A corresponding `crop_padding` routine removes the synthetic borders from the output tensor with pixel-perfect precision, ensuring the generated frames match the original resolution exactly without visual distortion.
|
||||
|
||||
#### Face Restoration Stabilization
|
||||
|
||||
- **Float32 Precision Enforcement:** The `AI_face_restoration` class now strictly enforces `float32` precision. The experimental `fp16` auto-detection was removed to prevent `NaN` (Not a Number) tensor propagation observed on specific CUDA driver versions and older Pascal/Maxwell architectures.
|
||||
- **Alpha Channel Integrity Protocol:** Refined the RGBA handling pipeline ("Split-Merge Strategy"). The Alpha channel is now strictly processed via Bicubic interpolation, while only the RGB channels undergo GAN-based restoration. This prevents the generation of noise artifacts in transparency masks.
|
||||
|
||||
### Operational Safety & Visual Identity
|
||||
|
||||
#### Process Execution Guards
|
||||
|
||||
- **Confirmation Interceptor:** Injected a `messagebox.askyesno` guard clause into the `upscale_button_command`. This prevents accidental initiation of resource-intensive workloads.
|
||||
- **Shutdown Race Condition Fix:** The `on_app_close` handler now captures window attributes (`is_topmost`) _before_ the destruction sequence begins, resolving `TclError: application has been destroyed` exceptions that previously corrupted preference saving on exit.
|
||||
|
||||
#### "Warlock Identity" Thematic Unification
|
||||
|
||||
- **High-Contrast Palette:** The interface theme has been standardized to a "Dark & Gold" palette. Backgrounds have been deepened to `#0A0A0A` (Near Black) to maximize contrast for image previewing, with semantic color coding (Success Green, Error Red, Warlock Gold) applied consistently across the new Preferences and Queue modules.
|
||||
|
||||
---
|
||||
|
||||
## Version 5.0
|
||||
# Version 5.0
|
||||
|
||||
**Release date:** November 22, 2025
|
||||
**Kernel Version:** 5.0.0 (Codename: NEO-Refactor)
|
||||
**Architecture:** Modular / Component-Based
|
||||
|
||||
### 1. Architectural Re-engineering & System Decoupling
|
||||
### Architectural Re-engineering & System Decoupling
|
||||
|
||||
The application core has undergone a foundational transformation, migrating from a legacy monolithic script architecture (v4.3) to a distributed, component-oriented modular system. This refactoring significantly reduces cyclomatic complexity, enforces Separation of Concerns (SoC), and isolates failure domains for improved fault tolerance.
|
||||
|
||||
#### 1.1. Component Atomization & Isolation
|
||||
#### Component Atomization & Isolation
|
||||
|
||||
The legacy `Warlock-Studio (1).py` codebase has been segmented into specialized operational subsystems:
|
||||
|
||||
@@ -36,54 +98,54 @@ The legacy `Warlock-Studio (1).py` codebase has been segmented into specialized
|
||||
- Provides an abstraction layer over `tkinterdnd2`.
|
||||
- Implements the `DnDCTk` class, which inherits from `CTk` and `TkinterDnD.DnDWrapper`, injecting native OS file drag-and-drop event listeners into the custom UI toolkit.
|
||||
|
||||
### 2. "NEO Engine": Telemetry, Heuristics & Persistence
|
||||
### "NEO Engine": Telemetry, Heuristics & Persistence
|
||||
|
||||
#### 2.1. Advanced Hardware Introspection (`HardwareScanner` Class)
|
||||
#### Advanced Hardware Introspection (`HardwareScanner` Class)
|
||||
|
||||
Implemented a robust Hardware Abstraction Layer (HAL) within `warlock_preferences.py`, utilizing `wmi`, `psutil`, and `GPUtil` libraries for deep system profiling:
|
||||
|
||||
- **CPU Topology Analysis:** Differentiates between physical and logical cores to optimize `cpu_count` allocation for FFmpeg encoding and frame extraction threads.
|
||||
- **Memory Mapping:** Performs real-time analysis of total vs. available RAM to preemptively throttle batch sizes and prevent page file thrashing (swapping).
|
||||
- **GPU Heuristic Detection:** Implements a deterministic priority chain for VRAM detection:
|
||||
1. **Priority A:** `GPUtil` (Direct NVIDIA API access).
|
||||
2. **Priority B:** `WMI` (Win32_VideoController query for AMD/Intel).
|
||||
3. **Fallback:** Synthetic estimation based on system heuristics.
|
||||
1. **Priority A:** `GPUtil` (Direct NVIDIA API access).
|
||||
2. **Priority B:** `WMI` (Win32_VideoController query for AMD/Intel).
|
||||
3. **Fallback:** Synthetic estimation based on system heuristics.
|
||||
- **Algorithmic Optimization (`get_smart_recommendations`):** A logic engine that accepts hardware telemetry and computes the **"Safe VRAM Limit"** via the formula `max(0.5, vram_gb - 1.5)`. It dynamically prescribes Tile Resolutions and Thread Concurrency based on hardware tiers (Low-End vs. High-End).
|
||||
|
||||
#### 2.2. Serialized Configuration Management (`ConfigManager`)
|
||||
#### Serialized Configuration Management (`ConfigManager`)
|
||||
|
||||
- **JSON State Persistence:** Deprecated hardcoded global variables in favor of a structured `warlock_config.json` file.
|
||||
- **Robust Serialization:** The `ConfigManager` handles the marshaling and unmarshaling of user preferences (UI scaling factors, window opacity, process priority).
|
||||
- **Integrity Validation:** The `load_config` method implements schema validation, automatically injecting default key-value pairs if the configuration file is corrupted or missing fields during boot.
|
||||
|
||||
### 3. AI Inference Engine Stabilization (ONNX Runtime Backend)
|
||||
### AI Inference Engine Stabilization (ONNX Runtime Backend)
|
||||
|
||||
#### 3.1. Deterministic Session Initialization
|
||||
#### Deterministic Session Initialization
|
||||
|
||||
- **Strict Type Enforcement:** The `create_onnx_session` factory was hardened to enforce strict integer typing (`int`) for the `device_id` parameter.
|
||||
- _Correction:_ In v4.3, passing device IDs as string literals (e.g., `"0"`) caused silent initialization failures on strict `DirectML` backends. The new logic creates an explicit mapping table (`'GPU 1' -> 0`).
|
||||
- **Hierarchical Execution Priority:** Implemented a failover chain for `ExecutionProviders` to maximize hardware acceleration compatibility:
|
||||
1. **Primary:** `CUDAExecutionProvider` (NVIDIA Optimized via cuDNN).
|
||||
2. **Secondary:** `DmlExecutionProvider` (DirectX 12 Abstraction Layer).
|
||||
3. **Failover:** `CPUExecutionProvider` (Universal x64 instruction set).
|
||||
1. **Primary:** `CUDAExecutionProvider` (NVIDIA Optimized via cuDNN).
|
||||
2. **Secondary:** `DmlExecutionProvider` (DirectX 12 Abstraction Layer).
|
||||
3. **Failover:** `CPUExecutionProvider` (Universal x64 instruction set).
|
||||
|
||||
#### 3.2. Precision Standardization in Face Restoration (`AI_face_restoration`)
|
||||
#### Precision Standardization in Face Restoration (`AI_face_restoration`)
|
||||
|
||||
- **Mandatory Float32 Inference:** The experimental `fp16` (half-precision) auto-detection logic used in v4.3 was deprecated.
|
||||
- _Rationale:_ It caused `NaN` (Not a Number) tensor propagation on older GPUs lacking dedicated Tensor Cores. The engine now defaults to **`float32`** unless the ONNX model metadata explicitly mandates a lower precision dtype.
|
||||
- **"Split-Merge" Channel Strategy:** A sophisticated pipeline was developed to handle RGBA (Transparency) artifacts:
|
||||
1. **Channel Splitting:** The Alpha channel is isolated from the RGB tensor.
|
||||
2. **Hybrid Scaling:** RGB channels are processed via the Neural Network; the Alpha channel is scaled using **Bicubic Interpolation** (`INTER_CUBIC`) to preserve edge fidelity without introducing GAN-generated noise into the transparency mask.
|
||||
3. **Tensor Reconstruction:** Post-inference concatenation (`numpy.concatenate`) reassembles the final image tensor.
|
||||
1. **Channel Splitting:** The Alpha channel is isolated from the RGB tensor.
|
||||
2. **Hybrid Scaling:** RGB channels are processed via the Neural Network; the Alpha channel is scaled using **Bicubic Interpolation** (`INTER_CUBIC`) to preserve edge fidelity without introducing GAN-generated noise into the transparency mask.
|
||||
3. **Tensor Reconstruction:** Post-inference concatenation (`numpy.concatenate`) reassembles the final image tensor.
|
||||
|
||||
#### 3.3. Heuristic OOM (Out-Of-Memory) Recovery
|
||||
#### Heuristic OOM (Out-Of-Memory) Recovery
|
||||
|
||||
- **Recursive Dynamic Tiling:** The `upscale_video_frames_async` pipeline now wraps inference calls within a specialized `try...except` block listening for specific `cuda`, `memory`, or `allocation` exceptions.
|
||||
- **Recovery Algorithm:** Upon trapping a VRAM overflow event, the orchestrator intercepts the crash, dynamically downscales the `max_resolution` (Tile Size) by a factor of 2 (e.g., `100% -> 50%`), and triggers a recursive retry of the failed frame. This ensures batch job completion even during transient memory spikes.
|
||||
|
||||
### 4. Video Processing Pipeline & FFmpeg Orchestration
|
||||
### Video Processing Pipeline & FFmpeg Orchestration
|
||||
|
||||
#### 4.1. Redundant Encoding Pipeline (Codec Fallback Loop)
|
||||
#### Redundant Encoding Pipeline (Codec Fallback Loop)
|
||||
|
||||
The `video_encoding` function has been refactored into a transactional state machine with automatic rollback and retry capabilities:
|
||||
|
||||
@@ -91,18 +153,18 @@ The `video_encoding` function has been refactored into a transactional state mac
|
||||
- **Failure Handling:** Captures `subprocess.CalledProcessError` or non-zero exit codes (indicative of driver timeouts or resource locking).
|
||||
- **Attempt 1 (Software Failover):** Automatically switches context to the CPU-based `libx264` encoder. This guarantees output file delivery even in catastrophic GPU driver failure scenarios.
|
||||
|
||||
#### 4.2. Lossless Intermediate Serialization
|
||||
#### Lossless Intermediate Serialization
|
||||
|
||||
- **PNG Standardization:** The `extract_video_frames` function has strictly deprecated the use of `.jpg` (v4.3) for temporary frame storage. The pipeline now mandates **`.png`** containers, eliminating compression artifacts (generation loss) before the pixel data enters the neural network input layer.
|
||||
|
||||
#### 4.3. Temporal Frame Synchronization
|
||||
#### Temporal Frame Synchronization
|
||||
|
||||
- **FPS Multiplier Logic:** An explicit `fps_multiplier` argument was injected into the `video_encoding` signature.
|
||||
- _Functionality:_ This allows the orchestrator to mathematically calculate the target framerate (`source_fps * multiplier`) specifically for **RIFE Interpolation** tasks (x2, x4, x8), ensuring frame-perfect Audio/Video synchronization in the final container muxing.
|
||||
|
||||
### 5. UI/UX & Advanced Diagnostic Tools
|
||||
### UI/UX & Advanced Diagnostic Tools
|
||||
|
||||
#### 5.1. Integrated Debugging Console (`IntegratedConsole`)
|
||||
#### Integrated Debugging Console (`IntegratedConsole`)
|
||||
|
||||
- **Stream Interception:** The `StreamRedirector` class hooks into the Python interpreter's I/O layer to capture `sys.stdout` and `sys.stderr`.
|
||||
- **Real-Time Visualization:** A dedicated `CTkTextbox` widget renders logs with Regex-based syntax highlighting (INFO=Blue, ERROR=Red, WARNING=Yellow, SUCCESS=Green), empowering end-users to diagnose underlying FFmpeg or ONNX runtime issues without external CLI tools.
|
||||
@@ -112,13 +174,13 @@ The `video_encoding` function has been refactored into a transactional state mac
|
||||
- **Contextual Widget Injection:** Implemented the `clear_dynamic_menus` routine to manipulate the widget tree (DOM) at runtime.
|
||||
- _Behavior:_ Upon selecting a **RIFE** model, "Blending" controls are destroyed and "Frame Generation" selectors (Slowmotion factors) are dynamically injected into the layout. This prevents invalid configuration states at the UI level.
|
||||
|
||||
#### 5.3. Window Management & Responsive Layout
|
||||
#### Window Management & Responsive Layout
|
||||
|
||||
- **Reactive Geometry Engine:** The `window.resizable(True, True)` flag was enabled, and the initial viewport geometry was increased to **85%** of screen height. The `grid` and `place` geometry managers were recalibrated to respond dynamically to window resizing events, accommodating the new bottom-docked console.
|
||||
|
||||
### 6. Deployment & System Integration Strategy
|
||||
### Deployment & System Integration Strategy
|
||||
|
||||
#### 6.1. Relocation of Default Installation Directory
|
||||
#### Relocation of Default Installation Directory
|
||||
|
||||
- **Privilege Escalation Mitigation:** The default installation target within the Inno Setup script (`.iss`) has been migrated from `%ProgramFiles%` to **`%userprofile%\Documents\Warlock-Studio`**.
|
||||
- **Write-Access Assurance:** This critical deployment change addresses `PermissionDenied` (WinError 5) exceptions encountered in v4.3 on systems with strict UAC (User Account Control) policies. By deploying to the user space, the application guarantees atomic read/write access for:
|
||||
@@ -129,51 +191,51 @@ The `video_encoding` function has been refactored into a transactional state mac
|
||||
|
||||
---
|
||||
|
||||
## Version 4.3
|
||||
# Version 4.3
|
||||
|
||||
**Release date:** November 15, 2025
|
||||
|
||||
### 1. Critical Stability & Process Synchronization
|
||||
### Critical Stability & Process Synchronization
|
||||
|
||||
#### 1.1. Forced Writer Thread Synchronization (Critical Stability Fix)
|
||||
#### Forced Writer Thread Synchronization (Critical Stability Fix)
|
||||
|
||||
- Implemented explicit and mandatory synchronization using the `t.join()` function for **all frame writing threads** (`writer_threads`) within the main video orchestrator (`upscale_orchestrator`).
|
||||
- This change is **critical for workflow integrity**, ensuring that all AI-upscaled frames are completely written and closed on disk before initiating the FFmpeg video encoding process.
|
||||
- **Technical Impact:** Resolves intermittent encoding failures (`File Not Found` or `Input/Output error`) that could occur when FFmpeg attempted to read files still being written by concurrent threads.
|
||||
|
||||
#### 1.2. Graceful Termination for Process Monitoring Thread
|
||||
#### Graceful Termination for Process Monitoring Thread
|
||||
|
||||
- The status monitoring thread (`upscale_monitor_thread`) has been enhanced to handle unexpected failures or abrupt terminations of the main upscaling process.
|
||||
- An explicit `break` statement was added to the `except Exception` block that manages errors reading from the status queue (`process_status_q`).
|
||||
- **Technical Impact:** If the main upscaling process (`Process`) fails or hangs, the monitoring thread now **terminates its execution gracefully and immediately** instead of becoming a "zombie thread," allowing the user interface to correctly reset global status controls.
|
||||
|
||||
#### 1.3. Reinforced Frame Sequence Integrity Validation
|
||||
#### Reinforced Frame Sequence Integrity Validation
|
||||
|
||||
- A robust verification function was introduced to validate the integrity of the frame sequence on disk before starting the AI upscaling.
|
||||
- This measure is vital for `Resume` operations and now explicitly validates:
|
||||
- The **physical existence** of every frame path (`os_path_exists`).
|
||||
- The **readability** of the image file (`image_read`), preventing segmentation faults or memory errors if the file is corrupted or incomplete.
|
||||
|
||||
### 2. Performance Improvements and Technical Refinements
|
||||
### Performance Improvements and Technical Refinements
|
||||
|
||||
#### 2.1. Aggressive Post-Process Memory Optimization
|
||||
#### Aggressive Post-Process Memory Optimization
|
||||
|
||||
- A memory optimization step (`optimize_memory_usage`) with calls to `gc.collect()` was implemented after the last upscaled frames are saved to disk and before video encoding starts.
|
||||
- **Purpose:** To reduce peak RAM usage by aggressively freeing any residual NumPy arrays and image references held in memory, ensuring the system has maximum memory available for the FFmpeg encoding subprocess.
|
||||
|
||||
#### 2.2. Clarification of Tiling and VRAM Logic
|
||||
#### Clarification of Tiling and VRAM Logic
|
||||
|
||||
- Detailed internal documentation (`# comments`) was added to the validation function (`check_upscale_settings`) to **explain the calculation logic for tile size** based on the user's VRAM limiter and the AI model's usage factor.
|
||||
- **Clarified Formula:** `tiles_resolution = (ModelUsageFactor * VRAM_GB) * 100`. This is a technical refinement ensuring transparency and justification for the internal calculation.
|
||||
|
||||
#### 2.3. Robustness and Clarification in Video Encoding (FFmpeg Command Line) 🎬
|
||||
#### Robustness and Clarification in Video Encoding (FFmpeg Command Line) 🎬
|
||||
|
||||
- **Explicit Stream Mapping:** Within `create_video_with_ffmpeg`, the FFmpeg command line now uses **more explicit and safer stream mapping** (`-map 0:v:0 -map 0:a:0?`). This ensures that the first video stream is selected obligatorily, and the first audio stream is selected optionally, resolving ambiguity issues in inputs containing multiple video or audio streams.
|
||||
- **Data Stream Exclusion:** The **`-dn`** (Disable Data stream) argument was introduced into the base FFmpeg command line. This instructs the encoder to ignore unnecessary _data streams_ (such as subtitles or complex metadata) that are not relevant to the video or audio, **simplifying the muxing process and improving compatibility** across various players.
|
||||
|
||||
### 3. Aesthetic and UI/UX Refinements
|
||||
### Aesthetic and UI/UX Refinements
|
||||
|
||||
#### 3.1. Complete Aesthetic Overhaul: Crimson Gold Dark Theme 🌑
|
||||
#### Complete Aesthetic Overhaul: Crimson Gold Dark Theme 🌑
|
||||
|
||||
- The application's entire color scheme was replaced (migrating from a v4.2.1 red/yellow palette) with a high-contrast **"Crimson Gold Dark Theme"**:
|
||||
- **Background:** Deep Black (`#121212`).
|
||||
@@ -181,18 +243,18 @@ The `video_encoding` function has been refactored into a transactional state mac
|
||||
- **Primary Accent:** Pure Gold (`#FFD700`).
|
||||
- Dropdown menus (`CTkOptionMenu`) were styled with explicit **`corner_radius=0`** for a more modern, defined, and flat aesthetic.
|
||||
|
||||
#### 3.2. Detailed Visualization of File Information in Queue
|
||||
#### Detailed Visualization of File Information in Queue
|
||||
|
||||
- Clarity of information in the queue widget (`FileWidget.add_file_information`) was improved by breaking down the complete resolution transformation sequence into three lines, eliminating ambiguity about intermediate dimensions:
|
||||
- **AI Input:** Shows the final input resolution.
|
||||
- **AI Output:** Shows the native resolution after upscaling by the AI model factor.
|
||||
- **Video Output:** Shows the final resolution of the encoded video.
|
||||
|
||||
#### 3.3. Visual Consistency and Updated Menu Separators
|
||||
#### Visual Consistency and Updated Menu Separators
|
||||
|
||||
- The visual separator in all dropdown menus has been updated from the string `"<------------------>"` (v4.2.1) to a cleaner, more discreet sequence of dots: **`• • • • • • • • • • • •`**.
|
||||
|
||||
#### 3.4. Refined Dynamic Menu Logic
|
||||
#### Refined Dynamic Menu Logic
|
||||
|
||||
- The conditional visibility logic for menus in `select_AI_from_menu` was refined for a smoother user experience:
|
||||
- The **Frame Interpolation** control is only visible for RIFE models.
|
||||
@@ -200,48 +262,48 @@ The `video_encoding` function has been refactored into a transactional state mac
|
||||
|
||||
---
|
||||
|
||||
## Version 4.2.1
|
||||
# Version 4.2.1
|
||||
|
||||
**Release date:** 27 October 2025
|
||||
|
||||
### 1. Critical Bug Fixes & Core Functionality
|
||||
### Critical Bug Fixes & Core Functionality
|
||||
|
||||
#### 1.1. Resolved Critical Audio Passthrough Failure in Video Encoding
|
||||
#### Resolved Critical Audio Passthrough Failure in Video Encoding
|
||||
|
||||
- Addressed a major bug introduced in v4.2 where all generated videos were encoded without audio. This was caused by the accidental omission of the `ffprobe.exe` executable (a key component of the FFmpeg suite) from the application's `Assets` directory and the final build package.
|
||||
- The `video_encoding` pipeline relies on media analysis (performed by `ffmpeg` or `ffprobe`) to detect the presence of audio streams in the source video. Due to the missing executable, the `audio_info_command` subprocess would fail, causing the application to incorrectly assume all input videos had no audio.
|
||||
- By restoring the `ffprobe.exe` binary to the application bundle, the audio detection step now executes successfully, enabling the proper copying (`-c:a copy`) or re-encoding (`-c:a aac`) of the original audio track into the final processed video.
|
||||
|
||||
#### 1.2. Fixed Invalid UI State Persistence
|
||||
#### Fixed Invalid UI State Persistence
|
||||
|
||||
- Addressed a critical UI logic bug where AI model settings could persist incorrectly when switching between model types. The `select_AI_from_menu` function now properly resets conflicting global variables:
|
||||
- **RIFE Selection:** When an interpolation model (e.g., RIFE, RIFE_Lite) is selected, the **`selected_blending_factor`** is now automatically reset to `0` (OFF), as blending is not a valid operation for this model.
|
||||
- **Upscaling/Face Selection:** Conversely, when any upscaling or face restoration model (e.g., BSRGAN, GFPGAN) is selected, the **`selected_frame_generation_option`** is automatically reset to `OFF`.
|
||||
- This prevents users from applying invalid or non-functional setting combinations, ensuring a more intuitive and error-free workflow.
|
||||
|
||||
#### 1.3. Fixed File Thumbnail Generation Crash
|
||||
#### Fixed File Thumbnail Generation Crash
|
||||
|
||||
- Reworked the `FileWidget.extract_file_icon` method to be more robust during the conversion of an OpenCV (NumPy) image to a `CTkImage` for file previews.
|
||||
- The process no longer relies on the `mode='RGB'` parameter within `pillow_image_fromarray`, which could fail with certain `numpy` array layouts.
|
||||
- It now uses an explicit, two-step conversion (`pil_img = pillow_image_fromarray(source_icon)` followed by `pil_img = pil_img.convert("RGB")`), ensuring correct channel order and preventing potential `Pillow`/`numpy` compatibility crashes when loading file thumbnails.
|
||||
|
||||
### 2. UI Corrections & Usability Enhancements
|
||||
### UI Corrections & Usability Enhancements
|
||||
|
||||
#### 2.1. Corrected Supported File Extension List
|
||||
#### Corrected Supported File Extension List
|
||||
|
||||
- The helper text on the file selection screen has been corrected to more accurately list the supported file extensions. It now properly includes `jpeg` and `tiff` and removes incorrect entries (`heic`, `gif`, `mpg`, `qt`, `3gp`) to align with the application's actual processing capabilities.
|
||||
|
||||
#### 2.2. Implemented Fixed Application Window
|
||||
#### Implemented Fixed Application Window
|
||||
|
||||
- The main application window is now non-resizable (`window.resizable(False, False)`). This change was implemented to ensure a stable and predictable UI layout, preventing the relative-coordinate-based widget placement (`relx`, `rely`) from breaking, overlapping, or scaling improperly when the window is resized.
|
||||
|
||||
#### 2.3. Improved Dialog Window Behavior
|
||||
#### Improved Dialog Window Behavior
|
||||
|
||||
- Removed the `self.attributes("-topmost", True)` flag from the `MessageBox` class (which handles error and info dialogs). This stops popup windows from aggressively forcing themselves to be the top-most window on the entire desktop. Dialogs now behave as standard application-modal windows, resolving a key usability issue where they could "steal focus" or obstruct other programs.
|
||||
|
||||
### 3. Thematic & Visual Redesign
|
||||
### Thematic & Visual Redesign
|
||||
|
||||
#### 3.1. New "Inferno" Thematic Redesign
|
||||
#### New "Inferno" Thematic Redesign
|
||||
|
||||
- Version 4.2.1 introduces a significant visual overhaul, moving away from the previous gold-and-grey theme to a high-contrast, dark-mode "inferno" theme. This new palette uses a deep red background with bright yellow and white text, designed to improve readability and reduce eye strain.
|
||||
|
||||
@@ -258,105 +320,105 @@ The color scheme has been updated as follows:
|
||||
| **Warning Color** | `#E02CDA` (Magenta) | `#FF8C00` (Orange) |
|
||||
| **Error Color** | `#070087` (Dark Blue) | `#DC143C` (Crimson) |
|
||||
|
||||
#### 3.2. Monospaced Typography Shift
|
||||
#### Monospaced Typography Shift
|
||||
|
||||
- The application's global font has been changed from `"Segoe UI"` to `"Consola"`. This provides a more uniform, technical aesthetic across all UI elements, enhancing readability for file names, numeric values, and status messages.
|
||||
|
||||
#### 3.3. Dropdown Menu Readability
|
||||
#### Dropdown Menu Readability
|
||||
|
||||
- Updated the visual separators in dropdown menus from `----` to `<------------------>` for clearer, more pronounced grouping of model categories.
|
||||
|
||||
---
|
||||
|
||||
## Version 4.2
|
||||
# Version 4.2
|
||||
|
||||
**Release date:** 6 October 2025
|
||||
|
||||
### 1. Core Architecture & Performance Engineering
|
||||
### Core Architecture & Performance Engineering
|
||||
|
||||
#### 1.1. Advanced ONNX Runtime Integration & Execution Provider Strategy
|
||||
#### Advanced ONNX Runtime Integration & Execution Provider Strategy
|
||||
|
||||
- **Intelligent Provider Prioritization & Fallback Mechanism**: The core AI model loading architecture has been fundamentally re-engineered for superior performance and resilience. The new implementation leverages a prioritized provider list (`['CUDAExecutionProvider', 'DmlExecutionProvider', 'CPUExecutionProvider']`) within the `onnxruntime.InferenceSession` constructor. It first attempts to initialize a session using the **`CUDAExecutionProvider`**, which offers the highest performance by interfacing directly with NVIDIA's CUDA cores and Tensor Cores. If this fails (due to lack of an NVIDIA GPU, driver issues, or CUDA toolkit incompatibility), the system gracefully falls back and attempts initialization with the **`DmlExecutionProvider`**, utilizing Windows' DirectML API for broader hardware acceleration across various GPU vendors (NVIDIA, AMD, Intel). As a final failsafe, if no GPU acceleration provider can be initialized, it defaults to the **`CPUExecutionProvider`**, ensuring the application remains functional on any machine, albeit with reduced performance.
|
||||
- **Centralized Session Management & Code Refactoring**: A new, unified function, `create_onnx_session`, has been introduced to abstract and centralize all ONNX session creation logic. This eliminates the redundant and error-prone boilerplate code that was previously duplicated within the `_load_inferenceSession` method of each individual AI class (`AI_upscale`, `AI_interpolation`, `AI_face_restoration`). This refactoring adheres to the **Don't Repeat Yourself (DRY)** principle, significantly improving code maintainability, reducing the surface area for bugs, and ensuring a consistent and robust model loading strategy across the entire application.
|
||||
- **Enhanced Error Handling & Diagnostics**: The `try...except` block encapsulating the session creation loop is now more sophisticated. It logs specific warnings when a provider fails to initialize and clearly indicates which provider it is falling back to. This provides transparent diagnostics that are critical for troubleshooting performance issues related to hardware acceleration.
|
||||
|
||||
#### 1.2. PyInstaller Packaging & Distribution Overhaul
|
||||
#### PyInstaller Packaging & Distribution Overhaul
|
||||
|
||||
- **Aggressive Dependency Pruning for Size Optimization**: The PyInstaller `.spec` file has been meticulously optimized to drastically reduce the final distribution size. An extensive `excludes` list has been implemented to explicitly instruct PyInstaller's analysis engine to ignore and not bundle large, non-essential packages. This prevents the recursive inclusion of entire scientific and machine learning ecosystems like `torch`, `transformers`, `matplotlib`, `pandas`, `scipy`, and `PyQt5`, which are often pulled in as sub-dependencies but are not required for this application's runtime. This strategic pruning reduces the package size by hundreds of megabytes.
|
||||
- **Robust Hidden Import Declaration for Runtime Stability**: The `.spec` file now includes a `hiddenimports` list containing `onnxruntime.capi._pybind_state`, `onnxruntime.providers`, and `moviepy.editor`. This is critical for ensuring runtime stability, as these modules are often loaded dynamically (e.g., via `__import__` or C extensions) in a way that PyInstaller's static analysis cannot detect. Explicitly declaring them forces their inclusion, preventing `ModuleNotFoundError` crashes when the packaged application attempts to access these components.
|
||||
- **Strategic Shift to "One-Folder" Distribution**: The build strategy has been transitioned from a "one-file" mode to a more robust and efficient "one-folder" mode. This is achieved by using the `COLLECT` block in the `.spec` file. Instead of bundling all dependencies into a single large executable that must be decompressed to a temporary directory (`_MEIPASS`) on every launch, the "one-folder" approach places the executable alongside its required `.dll`, `.pyd`, and data files. This results in significantly faster application startup times and avoids potential conflicts with antivirus software or system permissions related to executing from temporary locations.
|
||||
|
||||
### 2. Installer & Distribution Strategy Refinement
|
||||
### Installer & Distribution Strategy Refinement
|
||||
|
||||
#### 2.1. Transition to a Full Offline Installer Model
|
||||
#### Transition to a Full Offline Installer Model
|
||||
|
||||
- **Self-Contained & Hermetic Package**: The application's distribution model has been fundamentally shifted from a lightweight online/web installer to a comprehensive **offline installer**. All required runtime assets, most notably the large AI model files (`.onnx`), are now bundled directly within the Inno Setup executable. This creates a fully self-contained package that guarantees a successful installation without any external dependencies.
|
||||
- **Elimination of Network Dependencies & Points of Failure**: This architectural change enhances installation reliability exponentially. It completely removes the dependency on an active internet connection during setup and eliminates critical points of failure, such as GitHub/SourceForge server downtime, network interruptions, firewalls, or changes in download URLs. The user is assured of a complete, atomic installation from a single authoritative file.
|
||||
- **Radical Simplification of Installer Logic**: As a direct result of bundling all assets, the entire Pascal Script `[Code]` section in `Setup.iss` has been **completely removed**. This eliminates dozens of lines of complex logic responsible for creating custom download pages, handling HTTP requests, managing user cancellations, and, most critically, invoking external processes like PowerShell for archive extraction (`Expand-Archive`). This simplification makes the installer script significantly more robust, predictable, and easier to maintain.
|
||||
- **Streamlined User Experience**: The installer's UI has been simplified by removing the "Download AI Models" task from the `[Tasks]` section. This avoids user confusion and streamlines the setup process, as the action is no longer necessary. The output filename is also now explicitly suffixed with `-Full-Installer` to clearly communicate its offline nature.
|
||||
|
||||
### 3. UI, UX & Developer Experience Enhancements
|
||||
### UI, UX & Developer Experience Enhancements
|
||||
|
||||
#### 3.1. Enhanced Application Startup & Initial Feedback
|
||||
#### Enhanced Application Startup & Initial Feedback
|
||||
|
||||
- **Professional Splash Screen Implementation**: A new `SplashScreen` class provides immediate visual feedback upon application launch. This improves the _perceived performance_ by displaying a branded loading screen with status messages while core components and AI models are being initialized in the background. It prevents the appearance of a hung or unresponsive application during the initial loading phase.
|
||||
- **Runtime Environment Diagnostics**: At startup, the application now programmatically queries and prints the available ONNX Runtime providers by calling `onnxruntime.get_available_providers()`. This information is outputted to the console, serving as an invaluable, zero-effort diagnostic tool. It allows both end-users and developers to instantly verify which hardware acceleration backends are detected and available to the application, aiding in performance tuning and troubleshooting.
|
||||
|
||||
#### 3.2. Improved Debugging and Diagnosability
|
||||
#### Improved Debugging and Diagnosability
|
||||
|
||||
- **Persistent Console for Runtime Output**: The PyInstaller build configuration was modified to set `console=True`. This forces the application to run with an attached console window that captures the `stdout` and `stderr` streams. This is a critical enhancement for diagnostics, as it makes all print statements, logging output, warnings, and unhandled exception tracebacks immediately visible, providing a clear and persistent record of the application's runtime behavior for effective bug reporting and debugging.
|
||||
|
||||
---
|
||||
|
||||
## Version 4.1
|
||||
# Version 4.1
|
||||
|
||||
**Release date:** 1 August 2025
|
||||
|
||||
### 1. Model Enhancement and Utilization
|
||||
### Model Enhancement and Utilization
|
||||
|
||||
#### 1.1. Enhanced GPU Utilization and Error Handling
|
||||
#### Enhanced GPU Utilization and Error Handling
|
||||
|
||||
- **Robust Provider Configuration**: Added a private method `_select_providers` to intelligently select ONNX runtime providers based on the chosen GPU and improve model execution efficiency.
|
||||
- **Dynamic Fall-back Mechanism**: Enhanced `_load_inferenceSession` to prioritize loading models on GPU providers and gracefully fallback to CPU providers if GPU initialization fails, coupled with detailed logging.
|
||||
- **Improved Model Initialization**: Ensured comprehensive validation and error handling during model loading to enhance stability across various hardware environments.
|
||||
|
||||
### 2. Compatibility and Runtime Improvements
|
||||
### Compatibility and Runtime Improvements
|
||||
|
||||
#### 2.1. Addressed NumPy and OpenCV Compatibility
|
||||
#### Addressed NumPy and OpenCV Compatibility
|
||||
|
||||
- **Resolved Import Errors**: Fixed critical compatibility issues between NumPy 2.x and OpenCV by downgrading to NumPy 1.26.4, preventing `_ARRAY_API not found` and `numpy.core.multiarray failed to import` errors.
|
||||
- **Critical Module Validation**: Ensured that all critical libraries (OpenCV, ONNX Runtime, CustomTkinter) load successfully without compatibility warnings, enhancing overall application reliability.
|
||||
- **Runtime Environment Stability**: Resolved module loading conflicts that previously caused application crashes during startup.
|
||||
|
||||
### 3. Performance Optimization
|
||||
### Performance Optimization
|
||||
|
||||
#### 3.1. Memory and Resource Management
|
||||
#### Memory and Resource Management
|
||||
|
||||
- **Contiguous Memory Utilization**: Enhanced use of `numpy.ascontiguousarray` throughout image processing pipelines to optimize memory usage during intensive AI processing tasks.
|
||||
- **GPU Memory Error Recovery**: Improved handling of GPU memory allocation failures with automatic fallback to CPU processing when DirectML providers are unavailable.
|
||||
- **Processing Pipeline Optimization**: Streamlined AI model loading and inference execution for better resource utilization across different hardware configurations.
|
||||
|
||||
### 4. Code Quality and Error Handling
|
||||
### Code Quality and Error Handling
|
||||
|
||||
#### 4.1. Enhanced Error Resilience
|
||||
#### Enhanced Error Resilience
|
||||
|
||||
- **Syntax Error Resolution**: Fixed critical syntax error in `_load_inferenceSession` method that prevented proper AI model initialization.
|
||||
- **Improved Error Messaging**: Enhanced logging capabilities with more informative error messages and warnings for better user diagnostics and troubleshooting.
|
||||
- **Graceful Degradation**: Implemented improved fallback strategies for GPU resource issues, effectively preventing application crashes by dynamically adjusting processing pathways.
|
||||
- **Provider Validation**: Added comprehensive validation for ONNX runtime providers with automatic fallback from GPU to CPU execution when hardware acceleration is unavailable.
|
||||
|
||||
### 5. UI and User Experience
|
||||
### UI and User Experience
|
||||
|
||||
#### 5.1. Application Stability and Feedback
|
||||
#### Application Stability and Feedback
|
||||
|
||||
- **Startup Reliability**: Resolved critical startup issues that prevented the application from launching due to module compatibility problems.
|
||||
- **Processing Status Updates**: Enhanced real-time feedback during AI model loading and image/video processing operations.
|
||||
- **Error Notification**: Improved error dialogs and status messages to provide clearer information about processing states and potential issues.
|
||||
- **Hardware Compatibility**: Better detection and handling of different GPU configurations, with informative warnings when falling back to CPU processing.
|
||||
|
||||
### 6. Technical Improvements
|
||||
### Technical Improvements
|
||||
|
||||
#### 6.1. Model Loading Architecture
|
||||
#### Model Loading Architecture
|
||||
|
||||
- **Modular Provider Selection**: Separated provider selection logic into dedicated methods for better code organization and maintainability.
|
||||
- **Robust Model Validation**: Enhanced file existence checking and model integrity validation before attempting to load AI models.
|
||||
@@ -364,13 +426,13 @@ The color scheme has been updated as follows:
|
||||
|
||||
---
|
||||
|
||||
## Version 4.0.1
|
||||
# Version 4.0.1
|
||||
|
||||
**Release date:** 27 July 2025
|
||||
|
||||
### 1. Model Cleanup and Optimization
|
||||
### Model Cleanup and Optimization
|
||||
|
||||
#### 1.1. SuperResolution-10 Model Removal
|
||||
#### SuperResolution-10 Model Removal
|
||||
|
||||
- **Model Deprecation**: Removed the SuperResolution-10 model from the application due to performance and compatibility issues.
|
||||
- **Code Cleanup**: Eliminated the dedicated `AI_super_resolution` class and all related processing pipelines.
|
||||
@@ -379,7 +441,7 @@ The color scheme has been updated as follows:
|
||||
- **Streamlined Processing**: Simplified the upscaling orchestrator by removing SuperResolution-specific routing logic.
|
||||
- **Model List Cleanup**: Removed `SuperResolution_models_list` from the main AI models collection.
|
||||
|
||||
#### 1.2. Performance Improvements
|
||||
#### Performance Improvements
|
||||
|
||||
- **Reduced Memory Footprint**: Application now uses less memory without the SuperResolution-10 model overhead.
|
||||
- **Simplified Code Paths**: Cleaner processing logic with fewer conditional branches for model selection.
|
||||
@@ -387,63 +449,63 @@ The color scheme has been updated as follows:
|
||||
|
||||
---
|
||||
|
||||
## Version 4.0
|
||||
# Version 4.0
|
||||
|
||||
**Release date:** 18 July 2025
|
||||
|
||||
### 1. AI Model Integration & Enhancement
|
||||
### AI Model Integration & Enhancement
|
||||
|
||||
#### 1.1. SuperResolution-10 Model Implementation
|
||||
#### SuperResolution-10 Model Implementation
|
||||
|
||||
- **New AI Model Integration**: Added support for the SuperResolution-10 model, providing advanced super-resolution capabilities with 10x upscaling factor. This model is specifically designed for very low-resolution images and excels at significant resolution increases.
|
||||
- **Specialized Processing Pipeline**: Created a dedicated `AI_super_resolution` class that inherits from the new `AI_model_base` class, implementing proper preprocessing (CHW format conversion, normalization) and postprocessing (HWC format conversion, value clipping) for optimal results.
|
||||
- **Model Information Integration**: Added comprehensive model information in the AI model selector dialog, including year (2023), function (high-resolution image enhancement), and specialized use cases.
|
||||
|
||||
#### 1.2. AI Architecture Improvements
|
||||
#### AI Architecture Improvements
|
||||
|
||||
- **Base Class Implementation**: Created the missing `AI_model_base` class that provides common functionality for all AI models, including ONNX model loading with GPU acceleration support and proper error handling.
|
||||
- **Enhanced Model Loading**: Implemented robust model loading with provider selection (DML, CPU) and comprehensive error handling for missing model files.
|
||||
- **VRAM Management**: Added VRAM usage information for SuperResolution-10 (0.8 GB) to help users optimize their GPU memory usage.
|
||||
|
||||
### 2. Code Quality & Stability
|
||||
### Code Quality & Stability
|
||||
|
||||
#### 2.1. Import System Optimization
|
||||
#### Import System Optimization
|
||||
|
||||
- **Fixed Import Errors**: Resolved critical `NameError: name 'numpy_ndarray' is not defined` by properly organizing imports at the top of the file.
|
||||
- **Consolidated Imports**: Removed duplicate import sections and properly structured the import hierarchy for better maintainability.
|
||||
- **Type Annotation Fixes**: Corrected type annotations throughout the codebase to use the proper imported numpy types.
|
||||
|
||||
#### 2.2. Enhanced Error Handling
|
||||
#### Enhanced Error Handling
|
||||
|
||||
- **Model Loading Resilience**: Implemented try-catch blocks for model loading operations with meaningful error messages.
|
||||
- **Graceful Degradation**: Added fallback mechanisms that return the original image if super-resolution enhancement fails, ensuring the application never crashes.
|
||||
- **Debug Information**: Enhanced logging with model loading status and error reporting for better troubleshooting.
|
||||
|
||||
### 3. User Interface Updates
|
||||
### User Interface Updates
|
||||
|
||||
#### 3.1. Model Selection Enhancement
|
||||
#### Model Selection Enhancement
|
||||
|
||||
- **Updated Model List**: SuperResolution-10 is now properly integrated into the AI model dropdown menu and categorized appropriately.
|
||||
- **Information Dialog Updates**: Added detailed information about the SuperResolution-10 model in the help dialog, including its capabilities and recommended use cases.
|
||||
- **Model Orchestration**: Enhanced the upscaling orchestrator to properly detect and route SuperResolution model tasks to the appropriate processing pipeline.
|
||||
|
||||
### 4. Technical Improvements
|
||||
### Technical Improvements
|
||||
|
||||
#### 4.1. Processing Pipeline Optimization
|
||||
#### Processing Pipeline Optimization
|
||||
|
||||
- **Specialized Image Processing**: Implemented dedicated image processing functions for super-resolution models that handle the unique requirements of the SuperResolution-10 model.
|
||||
- **Memory Efficiency**: Optimized image preprocessing and postprocessing to minimize memory usage during super-resolution operations.
|
||||
- **Performance Monitoring**: Added processing time tracking for super-resolution operations to help users understand processing performance.
|
||||
|
||||
#### 4.2. Integration Completeness
|
||||
#### Integration Completeness
|
||||
|
||||
- **Full Model Integration**: SuperResolution-10 is now fully integrated into all aspects of the application, from model selection to processing to output generation.
|
||||
- **Consistent User Experience**: The super-resolution workflow follows the same patterns as other AI models, ensuring a consistent user experience.
|
||||
- **Quality Assurance**: Implemented comprehensive testing to ensure the SuperResolution-10 model works correctly with both individual images and batch processing.
|
||||
|
||||
### 5. Smart AI Model Distribution System
|
||||
### Smart AI Model Distribution System
|
||||
|
||||
#### 5.1. Automatic Model Download
|
||||
#### Automatic Model Download
|
||||
|
||||
- **Lightweight Installer**: Significantly reduced installer size from 1.4GB to approximately 300MB by removing AI models from the installation package.
|
||||
- **On-Demand Download**: Implemented intelligent model downloading system that automatically fetches required AI models (327MB) when the application is first launched.
|
||||
@@ -451,13 +513,13 @@ The color scheme has been updated as follows:
|
||||
- **Fallback URLs**: Integrated multiple download sources (GitHub Releases, SourceForge) to ensure reliable model availability.
|
||||
- **Resume Capability**: Download system supports resuming interrupted downloads and validates file integrity.
|
||||
|
||||
#### 5.2. PyInstaller Optimization
|
||||
#### PyInstaller Optimization
|
||||
|
||||
- **Optimized Packaging**: Updated `.spec` file to exclude AI model directory from executable packaging, reducing final executable size by over 1GB.
|
||||
- **Enhanced Dependencies**: Added model downloader module to the build process with proper hidden imports for requests, threading, and file handling libraries.
|
||||
- **Improved Compression**: Increased optimization level and added module exclusions to further reduce executable size.
|
||||
|
||||
#### 5.3. Installation Experience
|
||||
#### Installation Experience
|
||||
|
||||
- **Smart Setup Script**: Created enhanced Inno Setup configuration that can optionally download models during installation or defer to first-run.
|
||||
- **User Choice**: Users can choose between offline installation (models downloaded on first run) or full installation with models included.
|
||||
@@ -466,21 +528,21 @@ The color scheme has been updated as follows:
|
||||
|
||||
---
|
||||
|
||||
## Version 3.0
|
||||
# Version 3.0
|
||||
|
||||
**Release date:** 16 July 2025
|
||||
|
||||
### 1. Major Features & Core Capabilities
|
||||
### Major Features & Core Capabilities
|
||||
|
||||
#### 1.1. AI-Powered Face Restoration (GFPGAN)
|
||||
#### AI-Powered Face Restoration (GFPGAN)
|
||||
|
||||
- **New `AI_face_restoration` Class**: A new, specialized class has been implemented to handle face restoration models. This class is architected to manage the unique preprocessing and post-processing requirements of models like GFPGAN, distinct from standard upscaling models.
|
||||
- **GFPGAN Model Integration**: The GFPGAN v1.4 model has been added to the AI model repository and is now selectable from the UI. It is listed under a new `Face_restoration_models_list` category. The main orchestrator (`upscale_orchestrator`) now detects when a face restoration model is selected and routes the task to the appropriate `AI_face_restoration` instance.
|
||||
- **Specialized Processing Pipeline**: The new class introduces a dedicated pipeline for face enhancement. This includes resizing the input image to the model's required dimensions (e.g., 512x512 for GFPGAN), handling color channel conversions, and post-processing the output to restore the image to its original dimensions.
|
||||
|
||||
### 2. UI/UX Modernisation
|
||||
### UI/UX Modernisation
|
||||
|
||||
#### 2.1. Complete Thematic Redesign
|
||||
#### Complete Thematic Redesign
|
||||
|
||||
- The application has undergone a significant visual overhaul with a new, professionally designed color scheme to improve aesthetics and user comfort during long sessions. The new theme provides better contrast and a more modern look.
|
||||
|
||||
@@ -493,104 +555,104 @@ The color scheme has been updated as follows:
|
||||
| Button Hover | `#FF6666` (Light Red) | `background_color` |
|
||||
| Info Button | `#B22222` (Dark Red) | `widget_background_color` |
|
||||
|
||||
#### 2.2. Enhanced Splash Screen
|
||||
#### Enhanced Splash Screen
|
||||
|
||||
- **Dynamic Progress Bar**: The splash screen now features a `CTkProgressBar` to provide visual feedback on the application's loading status, enhancing the startup experience.
|
||||
- **Smooth Fade-Out Animation**: A new `fade_out` method using a cosine function has been implemented for a smooth, animated exit transition instead of an abrupt disappearance.
|
||||
- **Improved Information Display**: The splash screen now prominently displays the application version number.
|
||||
|
||||
#### 2.3. Redesigned and Resizable Message Boxes
|
||||
#### Redesigned and Resizable Message Boxes
|
||||
|
||||
- The `MessageBox` class was significantly improved to handle large blocks of text, such as detailed error messages. It now implements a `CTkScrollableFrame`, ensuring that content is always accessible without forcing the dialog to an unmanageable size.
|
||||
- The dialogs now have defined `minsize` and `maxsize` properties for better window management.
|
||||
|
||||
#### 2.4. Improved UI Readability
|
||||
#### Improved UI Readability
|
||||
|
||||
- The main AI model dropdown menu is now logically grouped by model type (Upscaling, Denoising, Face Restoration, Interpolation), with a `MENU_LIST_SEPARATOR` between categories. This makes it easier for users to find and select the appropriate AI model for their task.
|
||||
|
||||
### 3. Performance and Code Optimisation
|
||||
### Performance and Code Optimisation
|
||||
|
||||
#### 3.1. Memory Optimisation with Contiguous Arrays
|
||||
#### Memory Optimisation with Contiguous Arrays
|
||||
|
||||
- Widespread use of `numpy.ascontiguousarray` has been implemented across the codebase. This is applied during critical image handling steps in `AI_upscale.preprocess_image`, `AI_interpolation.concatenate_images`, and the new `AI_face_restoration.preprocess_face_image` class. This ensures data is aligned in memory, which can significantly speed up operations in backend libraries like OpenCV and ONNX Runtime.
|
||||
|
||||
#### 3.2. Refined Data Type Handling
|
||||
#### Refined Data Type Handling
|
||||
|
||||
- The `AI_upscale` class now explicitly ensures input images are converted to `float32` before normalization, improving precision and preventing potential data type mismatches during inference.
|
||||
- The `AI_face_restoration` class is configured to intelligently select between `float16` and `float32` based on the specific model's requirements (`fp16: True` in config), further optimizing performance and VRAM usage for compatible models.
|
||||
|
||||
### 4. Codebase Health and Maintainability
|
||||
### Codebase Health and Maintainability
|
||||
|
||||
#### 4.1. Specialised Class for Face Restoration
|
||||
#### Specialised Class for Face Restoration
|
||||
|
||||
- The logic for face restoration has been fully encapsulated within the new `AI_face_restoration` class, separating it from the general-purpose `AI_upscale` class. This object-oriented approach makes the code more modular, readable, and easier to extend with different face enhancement models in the future.
|
||||
|
||||
#### 4.2. Robust BGRA to BGR Conversion
|
||||
#### Robust BGRA to BGR Conversion
|
||||
|
||||
- The application now explicitly handles images with an alpha channel (4-channel BGRA) when using face restoration models. A new import for `COLOR_BGRA2BGR` was added, and it is used within `preprocess_face_image` to convert images to the 3-channel BGR format expected by the GFPGAN model. This prevents runtime errors and ensures correct processing of PNGs or other images with transparency.
|
||||
|
||||
---
|
||||
|
||||
## Version 2.2
|
||||
# Version 2.2
|
||||
|
||||
**Release date:** 7 July 2025
|
||||
|
||||
### 1. Major Enhancements and Stability Overhaul
|
||||
### Major Enhancements and Stability Overhaul
|
||||
|
||||
#### 1.1. Comprehensive Logging System
|
||||
#### Comprehensive Logging System
|
||||
|
||||
- Implemented a full-featured `logging` system that writes to files in the user's `Documents` folder (`warlock_studio.log` and `error_log.txt`). This provides detailed diagnostics for debugging without relying solely on console output.
|
||||
- A unified `log_and_report_error` function centralizes error handling, ensuring all critical issues are both logged and displayed to the user.
|
||||
|
||||
#### 1.2. Proactive Environment Validation
|
||||
#### Proactive Environment Validation
|
||||
|
||||
- The application now performs pre-flight checks before processing begins to prevent common failures.
|
||||
- Includes validation for Python version, required modules (`validate_environment`), FFmpeg availability, disk space, and available RAM (`validate_system_requirements`).
|
||||
- Verifies that all input file paths exist and are accessible (`validate_file_paths`) and that the output directory is writable (`validate_output_path`).
|
||||
|
||||
#### 1.3. Resilient Video Encoding Pipeline
|
||||
#### Resilient Video Encoding Pipeline
|
||||
|
||||
- The entire `video_encoding` function was overhauled for maximum reliability.
|
||||
- **Codec Fallback:** The system now tests for hardware codec availability (NVENC, AMF, QSV) before encoding. If a selected hardware encoder is not functional, it automatically falls back to the highly compatible `libx264` software encoder.
|
||||
- **Robust Audio Handling:** Implements a fallback chain for audio processing. It first attempts to directly copy the audio stream; if that fails, it attempts to re-encode it; if that also fails, it finalizes the video without audio, ensuring a video file is always produced.
|
||||
|
||||
#### 1.4. Graceful Shutdown and Cleanup
|
||||
#### Graceful Shutdown and Cleanup
|
||||
|
||||
- Implemented `atexit` and `signal` handlers to ensure that temporary files are cleaned up and child processes are terminated safely, even on unexpected exits.
|
||||
- Replaced abrupt `process.kill()` calls with the more graceful `process.terminate()` to allow for cleaner process shutdown.
|
||||
|
||||
### 2. Performance and Memory Optimization
|
||||
### Performance and Memory Optimization
|
||||
|
||||
#### 2.1. Aggressive Memory Management
|
||||
#### Aggressive Memory Management
|
||||
|
||||
- Video frame processing (`upscale_video_frames_async`) no longer holds large numbers of frames in RAM. It now writes small batches to disk and immediately calls the garbage collector (`gc.collect()`) to free memory, dramatically reducing the risk of crashes on long videos.
|
||||
|
||||
#### 2.2. Dynamic GPU VRAM Error Recovery
|
||||
#### Dynamic GPU VRAM Error Recovery
|
||||
|
||||
- The AI orchestration logic can now recover from GPU "out of memory" errors during tiling. If an error is detected, it automatically reduces the tile resolution and retries the operation on that specific frame, preventing a total process failure.
|
||||
|
||||
### 3. Critical Bug Fixes
|
||||
### Critical Bug Fixes
|
||||
|
||||
#### 3.1. Resolved Video Encoding Race Condition
|
||||
#### Resolved Video Encoding Race Condition
|
||||
|
||||
- Fixed a critical bug where video encoding could start before all frame-writing threads were complete. The system now tracks all writer threads and explicitly waits for them to finish (`thread.join()`) before beginning the final video encoding, preventing corrupted or incomplete videos.
|
||||
|
||||
#### 3.2. Corrected Persistent Stop Flag
|
||||
#### Corrected Persistent Stop Flag
|
||||
|
||||
- The `stop_thread_flag` is now reset (`.clear()`) at the start of each "Make Magic" execution, fixing a bug where a previously stopped job would prevent a new one from running.
|
||||
|
||||
#### 3.3. Eliminated Status Update Race Condition
|
||||
#### Eliminated Status Update Race Condition
|
||||
|
||||
- Implemented a `threading.Lock` (`global_status_lock`) to protect shared flags that update the GUI. This prevents race conditions where multiple threads could attempt to modify the status simultaneously.
|
||||
|
||||
### 4. UI / UX Refinements
|
||||
### UI / UX Refinements
|
||||
|
||||
#### 4.1. Updated Splash Screen
|
||||
#### Updated Splash Screen
|
||||
|
||||
- Reduced splash screen duration to 10 seconds for a faster application start-up.
|
||||
- Corrected asset path to `Assets/banner.png` for proper display.
|
||||
|
||||
#### 4.2. New Application Theme
|
||||
#### New Application Theme
|
||||
|
||||
| Element | New Value | Old Value (v2.1) |
|
||||
| :---------------- | :--------------- | :------------------- |
|
||||
@@ -598,42 +660,42 @@ The color scheme has been updated as follows:
|
||||
| Widget background | `#5A5A5A` (Grey) | `#960707` (Dark Red) |
|
||||
| Accent/Border | Gold & Red | Blue & Red |
|
||||
|
||||
### 5. Codebase Health and Maintainability
|
||||
### Codebase Health and Maintainability
|
||||
|
||||
#### 5.1. Enhanced Checkpointing and Recovery
|
||||
#### Enhanced Checkpointing and Recovery
|
||||
|
||||
- Added functions (`create_checkpoint`, `load_checkpoint`) to save and resume the progress of video frame processing, allowing recovery from interruptions.
|
||||
|
||||
#### 5.2. Hardened Core Methods
|
||||
#### Hardened Core Methods
|
||||
|
||||
- Core methods in AI classes now include checks for `None` inputs and feature default fallbacks (`case _:`) in `match` statements to prevent unexpected errors with unsupported data.
|
||||
|
||||
---
|
||||
|
||||
## Version 2.1
|
||||
# Version 2.1
|
||||
|
||||
**Release date:** 23 June 2025
|
||||
|
||||
### 1. Major Enhancements and Stability Overhaul
|
||||
### Major Enhancements and Stability Overhaul
|
||||
|
||||
#### 1.1. Robust Error Handling
|
||||
#### Robust Error Handling
|
||||
|
||||
- Model loading (`AI_upscale`, `AI_interpolation`) wrapped in `try…except FileNotFoundError, OSError`; meaningful error messages propagate to GUI.
|
||||
- `extract_video_frames()` validates file existence, `cv2.VideoCapture.isOpened()`, and frame count > 0.
|
||||
- `video_encoding()` captures `subprocess.CalledProcessError`, logs `stderr`, and continues with fallback strategies.
|
||||
- Audio passthrough failures now trigger a silent audio‑less encode instead of total job abort.
|
||||
|
||||
#### 1.2. Safe Thread and Process Management
|
||||
#### Safe Thread and Process Management
|
||||
|
||||
- Deprecated error‑raising thread stop replaced with `threading.Event` (`stop_thread_flag`) polled at defined checkpoints.
|
||||
|
||||
#### 1.3. Resilient Core Processing
|
||||
#### Resilient Core Processing
|
||||
|
||||
- `copy_file_metadata()` now verifies `exiftool.exe` availability and the existence of source/target before execution.
|
||||
|
||||
### 2. UI / UX Refinements
|
||||
### UI / UX Refinements
|
||||
|
||||
#### 2.1. Refined Colour Palette
|
||||
#### Refined Colour Palette
|
||||
|
||||
| Element | New Value |
|
||||
| ----------------- | ------------------------------- |
|
||||
@@ -641,112 +703,112 @@ The color scheme has been updated as follows:
|
||||
| Widget background | `#960707` |
|
||||
| Active border | Red (same as widget background) |
|
||||
|
||||
### 3. Code‑base Maintainability
|
||||
### Code‑base Maintainability
|
||||
|
||||
#### 3.1. Improved Code Organisation
|
||||
#### Improved Code Organisation
|
||||
|
||||
- File‑extension lists extracted to `filetypes.py` as `SUPPORTED_IMAGE_EXTENSIONS`, `SUPPORTED_VIDEO_EXTENSIONS`.
|
||||
|
||||
#### 3.2. Dependency and Initialisation
|
||||
#### Dependency and Initialisation
|
||||
|
||||
- Added imports: `shutil.move`, `subprocess.CalledProcessError`, `threading.Event`.
|
||||
- Global variables initialised in `init_globals()` for deterministic start‑up.
|
||||
|
||||
---
|
||||
|
||||
## Version 2.0
|
||||
# Version 2.0
|
||||
|
||||
**Release date:** 6 June 2025
|
||||
|
||||
### 1. Major Features
|
||||
### Major Features
|
||||
|
||||
#### 1.1. AI Frame Interpolation Support (`AI_interpolation` class)
|
||||
#### AI Frame Interpolation Support (`AI_interpolation` class)
|
||||
|
||||
- Supports RIFE‑based ONNX models; generates 1 (×2), 3 (×4), or 7 (×8) intermediate frames.
|
||||
- Provides both real‑time preview and batch processing modes.
|
||||
- Integrates with `FrameScheduler` for temporal upscaling pipelines.
|
||||
|
||||
#### 1.2. RIFE Models Integration
|
||||
#### RIFE Models Integration
|
||||
|
||||
- Added **RIFE** and **RIFE_Lite** to model repository.
|
||||
- `RIFE_models_list` enumerates available checkpoints; `AI_models_list` now merges SRVGGNetCompact, BSRGAN, IRCNN, and RIFE families.
|
||||
|
||||
### 2. Enhancements
|
||||
### Enhancements
|
||||
|
||||
#### 2.1. Visual/UI Redesign
|
||||
#### Visual/UI Redesign
|
||||
|
||||
- Application renamed to **“Warlock‑Studio”** (with hyphen).
|
||||
- New dark palette (`#121212`, `#454242`) with bright white text (`#FFFFFF`) and accent red (`#FF0E0E`).
|
||||
|
||||
#### 2.2. Version‑Specific User Preferences
|
||||
#### Version‑Specific User Preferences
|
||||
|
||||
- User configuration stored as `Warlock-Studio_<major>.<minor>_UserPreference.json` to avoid backward‑compatibility clashes.
|
||||
|
||||
#### 2.3. Modular and Scalable Layout System
|
||||
#### Modular and Scalable Layout System
|
||||
|
||||
- Added GUI constants defined in `layout_constants.py` (e.g., `OFFSET_Y_OPTIONS`, `COLUMN_1_5`).
|
||||
|
||||
#### 2.4. Extended File‑Type Compatibility
|
||||
#### Extended File‑Type Compatibility
|
||||
|
||||
- Updated `SUPPORTED_FILE_EXTENSIONS` and `SUPPORTED_VIDEO_EXTENSIONS` to include modern codecs (e.g., HEIC, AVIF, WebM).
|
||||
|
||||
#### 2.5. Improved GPU Execution Support
|
||||
#### Improved GPU Execution Support
|
||||
|
||||
- `provider_options` enumerates up to four DirectML devices (Auto, GPU 1 – GPU 4); selection persists across sessions.
|
||||
|
||||
### 3. Technical Refinements
|
||||
### Technical Refinements
|
||||
|
||||
#### 3.1. Model List Structure
|
||||
#### Model List Structure
|
||||
|
||||
- Menu drop‑downs now grouped by category separated by `MENU_LIST_SEPARATOR` for readability.
|
||||
|
||||
#### 3.2. Advanced Interpolation Logic
|
||||
#### Advanced Interpolation Logic
|
||||
|
||||
- Implements tree‑based frame generation (e.g., D→A‑B‑C) with dependency tracking to avoid redundant inference passes.
|
||||
|
||||
#### 3.3. Improved Numeric Precision and Post‑Processing
|
||||
#### Improved Numeric Precision and Post‑Processing
|
||||
|
||||
- Normalisation uses 32‑bit floats with epsilon guarding; RGBA conversion paths optimised using `numexpr`.
|
||||
|
||||
### 4. UI / UX Refinements
|
||||
### UI / UX Refinements
|
||||
|
||||
#### 4.1. Resizable Message Dialogs
|
||||
#### Resizable Message Dialogs
|
||||
|
||||
- `MessageBox`; Tk `resizable(True, True)`.
|
||||
|
||||
#### 4.2. Improved Dialog Formatting
|
||||
#### Improved Dialog Formatting
|
||||
|
||||
- Uniform spacing, font hierarchy, and default‑value display.
|
||||
|
||||
### 5. Minor Fixes
|
||||
### Minor Fixes
|
||||
|
||||
#### 5.1. Code Corrections
|
||||
#### Code Corrections
|
||||
|
||||
- Corrected typo `ttext_color` → `text_color`.
|
||||
- Expanded inline comments and reorganised sections for clarity.
|
||||
|
||||
---
|
||||
|
||||
## Version 1.1
|
||||
# Version 1.1
|
||||
|
||||
**Release date:** 20 May 2025
|
||||
|
||||
### 1. Major Improvements
|
||||
### Major Improvements
|
||||
|
||||
#### 1.1. Program Start‑up Optimisation
|
||||
#### Program Start‑up Optimisation
|
||||
|
||||
- Launch time reduced via lazy module loading.
|
||||
|
||||
#### 1.2. Model Loading Improvements
|
||||
#### Model Loading Improvements
|
||||
|
||||
- Parallel prefetch and checksum verification.
|
||||
|
||||
#### 1.3. General Performance Optimisation
|
||||
#### General Performance Optimisation
|
||||
|
||||
- Core refactor, improved I/O scheduling, and smarter resource allocation.
|
||||
|
||||
### 2. Minor Fixes
|
||||
### Minor Fixes
|
||||
|
||||
#### 2.1. Accessibility
|
||||
#### Accessibility
|
||||
|
||||
- User‑interface tweaks for better accessibility (focus indicators, tab order).
|
||||
|
||||
+279
-462
@@ -1,514 +1,331 @@
|
||||
% =======================================================================================
|
||||
% 1. DOCUMENT SETUP & PACKAGES
|
||||
% =======================================================================================
|
||||
\documentclass[11pt, a4paper]{article}
|
||||
\documentclass[a4paper,11pt]{article}
|
||||
|
||||
% --- ESSENTIAL PACKAGES ---
|
||||
% =========================================================
|
||||
% PACKAGES & CONFIGURATION
|
||||
% =========================================================
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[english]{babel}
|
||||
|
||||
% --- PAGE LAYOUT & STYLE ---
|
||||
\usepackage[a4paper, margin=2.2cm, headheight=15pt, footskip=30pt]{geometry}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{float}
|
||||
\usepackage{caption}
|
||||
\usepackage{subcaption}
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage[margin=1in, bottom=1.2in]{geometry}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{titletoc}
|
||||
|
||||
% --- TYPOGRAPHY & TEXT ---
|
||||
\usepackage{lato}
|
||||
\renewcommand*\familydefault{\sfdefault}
|
||||
\usepackage{textcomp}
|
||||
\usepackage{fontawesome5}
|
||||
\usepackage{microtype} % Improves line breaking and spacing
|
||||
|
||||
% Slightly more readable line spacing and allow more flexible breaks
|
||||
\usepackage{setspace}
|
||||
\setstretch{1.05}
|
||||
\sloppy
|
||||
\emergencystretch=2em
|
||||
|
||||
% --- TABLES, LISTS, & BOXES ---
|
||||
\usepackage{booktabs}
|
||||
\usepackage{longtable}
|
||||
\usepackage{tabularx}
|
||||
\usepackage{array}
|
||||
\usepackage{enumitem}
|
||||
\usepackage[skins, breakable, theorems]{tcolorbox}
|
||||
\tcbuselibrary{skins, breakable, shadows} % Load advanced libraries
|
||||
|
||||
% --- TITLES & HYPERLINKS ---
|
||||
\usepackage{graphicx}
|
||||
\usepackage{titlesec}
|
||||
\usepackage{hyperref} % Always load this last
|
||||
|
||||
% --- TIKZ FOR DIAGRAMS (STYLIZED WITH CORPORATE PALETTE) ---
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage{tcolorbox}
|
||||
\usepackage{fontawesome5} % For icons
|
||||
\usepackage{booktabs}
|
||||
\usepackage{tabularx}
|
||||
\usepackage{multirow}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{shapes, arrows.meta, positioning, shadows, calc, decorations.pathreplacing, backgrounds}
|
||||
\usepackage{pgfkeys}
|
||||
\usepackage{float}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{enumitem}
|
||||
|
||||
% =======================================================================================
|
||||
% 2. COLOR & STYLE DEFINITIONS
|
||||
% =======================================================================================
|
||||
\usetikzlibrary{shapes.geometric, arrows, positioning}
|
||||
\tcbuselibrary{skins, breakable}
|
||||
|
||||
% --- CORPORATE COLOR PALETTE ---
|
||||
\definecolor{WarlockRed}{HTML}{C11919}
|
||||
\definecolor{WarlockGold}{HTML}{ECD125}
|
||||
\definecolor{WarlockDark}{HTML}{1B1818} % Updated to match v5.0 Theme
|
||||
\definecolor{WarlockGray}{HTML}{333333}
|
||||
\definecolor{WarlockLightGray}{HTML}{F0F0F0}
|
||||
\definecolor{WarlockWhite}{HTML}{FFFFFF}
|
||||
% =========================================================
|
||||
% WARLOCK STUDIO BRANDING COLORS (From Source Code)
|
||||
% =========================================================
|
||||
\definecolor{WarlockBg}{HTML}{0A0A0A} % Main Background
|
||||
\definecolor{WarlockRed}{HTML}{D41C1C} % Accent Red
|
||||
\definecolor{WarlockGold}{HTML}{FDEF2F} % Accent Gold
|
||||
\definecolor{WarlockDark}{HTML}{303030} % Widget Background
|
||||
\definecolor{WarlockText}{HTML}{FFFFFF} % White Text
|
||||
\definecolor{WarlockGray}{HTML}{B5B4B4} % Secondary Text
|
||||
|
||||
% --- SECTION COLOR PALETTE ---
|
||||
\definecolor{IntroColor}{HTML}{005A9B} % Blue
|
||||
\definecolor{QuickStartColor}{HTML}{00796B} % Green
|
||||
\definecolor{InstallColor}{HTML}{8E44AD} % Purple
|
||||
\definecolor{ModelsColor}{HTML}{D35400} % Orange
|
||||
\definecolor{OptimizeColor}{HTML}{27AE60} % Emerald Green
|
||||
\definecolor{TroubleColor}{HTML}{C0392B} % Red
|
||||
\definecolor{ArchColor}{HTML}{2C3E50} % Dark Blue
|
||||
\definecolor{GlossaryColor}{HTML}{7F8C8D} % Gray
|
||||
\definecolor{SupportColor}{HTML}{34495E} % Dark Gray
|
||||
|
||||
% --- TEXTBOX COLOR PALETTE ---
|
||||
\definecolor{InfoFill}{HTML}{E7F3FE}
|
||||
\definecolor{InfoBorder}{HTML}{005A9B}
|
||||
\definecolor{WarnFill}{HTML}{FFFBE6}
|
||||
\definecolor{WarnBorder}{HTML}{FFBE0B}
|
||||
\definecolor{QuickStartFill}{HTML}{E6FFFA}
|
||||
\definecolor{QuickStartBorder}{HTML}{00796B}
|
||||
% New Palette for NEO Engine
|
||||
\definecolor{NeoFill}{HTML}{F3E5F5}
|
||||
\definecolor{NeoBorder}{HTML}{8E44AD}
|
||||
% Header and Footer
|
||||
\pagestyle{fancy}
|
||||
\fancyhf{}
|
||||
\renewcommand{\headrulewidth}{0pt}
|
||||
\renewcommand{\footrulewidth}{2pt}
|
||||
\renewcommand{\footrule}{\hbox to\headwidth{\color{WarlockRed}\leaders\hrule height \footrulewidth\hfill}}
|
||||
|
||||
% --- DEFAULT TEXT COLOR APPLICATION ---
|
||||
\color{WarlockGray}
|
||||
\fancyhead[R]{\textbf{\textcolor{WarlockDark}{Warlock-Studio v5.1}}}
|
||||
\fancyhead[L]{\textcolor{WarlockGray}{User Manual}}
|
||||
\fancyfoot[C]{\thepage}
|
||||
\fancyfoot[R]{\includegraphics[height=0.8cm]{logo.png}} % Logo at footer
|
||||
|
||||
% =======================================================================================
|
||||
% 3. DOCUMENT ELEMENT CONFIGURATION
|
||||
% =======================================================================================
|
||||
% Section Styling
|
||||
\titleformat{\section}
|
||||
{\color{WarlockRed}\normalfont\Large\bfseries\uppercase}
|
||||
{\thesection}{1em}{}[{\titlerule[1pt]}]
|
||||
|
||||
% --- HYPERLINKS ---
|
||||
\titleformat{\subsection}
|
||||
{\color{WarlockDark}\normalfont\large\bfseries}
|
||||
{\thesubsection}{1em}{}
|
||||
|
||||
% Custom Boxes for Information grouping
|
||||
\newtcolorbox{infobox}[1]{
|
||||
colback=WarlockDark!10!white,
|
||||
colframe=WarlockDark,
|
||||
fonttitle=\bfseries,
|
||||
title=#1,
|
||||
arc=0mm,
|
||||
boxrule=1pt,
|
||||
leftrule=4pt
|
||||
}
|
||||
|
||||
\newtcolorbox{warningbox}[1]{
|
||||
colback=red!5!white,
|
||||
colframe=WarlockRed,
|
||||
fonttitle=\bfseries,
|
||||
title=\faExclamationTriangle\ #1,
|
||||
arc=0mm,
|
||||
boxrule=1pt,
|
||||
leftrule=4pt,
|
||||
coltitle=white
|
||||
}
|
||||
|
||||
\newtcolorbox{tipbox}[1]{
|
||||
colback=WarlockGold!10!white,
|
||||
colframe=orange!80!black,
|
||||
fonttitle=\bfseries,
|
||||
title=\faLightbulb\ #1,
|
||||
arc=0mm,
|
||||
boxrule=1pt,
|
||||
leftrule=4pt,
|
||||
coltitle=black
|
||||
}
|
||||
|
||||
% Hyperlink Setup
|
||||
\hypersetup{
|
||||
colorlinks=true,
|
||||
linkcolor=WarlockRed,
|
||||
filecolor=WarlockRed,
|
||||
urlcolor=WarlockRed,
|
||||
pdftitle={Warlock-Studio v5.0 | Technical Documentation and User Manual},
|
||||
pdfauthor={Iván Eduardo Chavez Ayub}
|
||||
filecolor=magenta,
|
||||
urlcolor=blue,
|
||||
pdftitle={Warlock-Studio Manual},
|
||||
}
|
||||
|
||||
% --- SECTION & SUBSECTION TITLES ---
|
||||
\newcommand{\SectionColor}{WarlockGray} % Default color
|
||||
\newcommand{\setsectioncolor}[1]{\renewcommand{\SectionColor}{#1}}
|
||||
% =========================================================
|
||||
% DOCUMENT CONTENT
|
||||
% =========================================================
|
||||
|
||||
\titleformat{\section}
|
||||
{\normalfont\Large\bfseries}
|
||||
{}
|
||||
{0em}
|
||||
{%
|
||||
\begin{tcolorbox}[
|
||||
enhanced,
|
||||
colback=\SectionColor!90!black,
|
||||
colframe=\SectionColor!90!black,
|
||||
boxrule=0pt,
|
||||
sharp corners,
|
||||
halign=center,
|
||||
valign=center,
|
||||
boxsep=6pt,
|
||||
left=0pt, right=0pt, top=0pt, bottom=0pt
|
||||
]
|
||||
\color{white}\faBookmark\hspace{0.5em}\thesection.\hspace{1em}#1
|
||||
\end{tcolorbox}
|
||||
}
|
||||
\titleformat{\subsection}
|
||||
{\normalfont\large\bfseries\color{\SectionColor!80!black}}
|
||||
{\faCaretRight\ \thesubsection}
|
||||
{1em}
|
||||
{}
|
||||
\titlespacing*{\section}{0pt}{4ex plus 1ex minus .2ex}{3ex plus .2ex}
|
||||
\titlespacing*{\subsection}{0pt}{2.5ex plus 1ex minus .2ex}{1.3ex plus .2ex}
|
||||
|
||||
% --- ENHANCED TEXTBOX DEFINITIONS ---
|
||||
\newtcolorbox{infobox}[2][]{
|
||||
enhanced, breakable,
|
||||
colback=InfoFill, colframe=InfoBorder,
|
||||
fonttitle=\bfseries, coltitle=InfoBorder,
|
||||
title=\faInfoCircle\hspace{0.5em}#2,
|
||||
attach boxed title to top left={yshift=-2mm, xshift=3mm},
|
||||
boxed title style={colback=InfoBorder, sharp corners},
|
||||
coltext=WarlockDark,
|
||||
shadow={2mm}{-1mm}{0mm}{black!20!white},
|
||||
#1
|
||||
}
|
||||
\newtcolorbox{warnbox}[2][]{
|
||||
enhanced, breakable,
|
||||
colback=WarnFill, colframe=WarnBorder,
|
||||
fonttitle=\bfseries, coltitle=WarnBorder!80!black,
|
||||
title=\faExclamationTriangle\hspace{0.5em}#2,
|
||||
attach boxed title to top left={yshift=-2mm, xshift=3mm},
|
||||
boxed title style={colback=WarnBorder, sharp corners},
|
||||
coltext=WarlockDark,
|
||||
shadow={2mm}{-1mm}{0mm}{black!20!white},
|
||||
#1
|
||||
}
|
||||
\newtcolorbox{quickstartbox}[2][]{
|
||||
enhanced, breakable,
|
||||
colback=QuickStartFill, colframe=QuickStartBorder,
|
||||
fonttitle=\bfseries, coltitle=QuickStartBorder!80!black,
|
||||
title=\faRocket\hspace{0.5em}#2,
|
||||
attach boxed title to top left={yshift=-2mm, xshift=3mm},
|
||||
boxed title style={colback=QuickStartBorder, sharp corners},
|
||||
coltext=WarlockDark,
|
||||
shadow={2mm}{-1mm}{0mm}{black!20!white},
|
||||
#1
|
||||
}
|
||||
% New box for NEO Engine / Hardware features
|
||||
\newtcolorbox{neobox}[2][]{
|
||||
enhanced, breakable,
|
||||
colback=NeoFill, colframe=NeoBorder,
|
||||
fonttitle=\bfseries, coltitle=NeoBorder!80!black,
|
||||
title=\faMicrochip\hspace{0.5em}#2,
|
||||
attach boxed title to top left={yshift=-2mm, xshift=3mm},
|
||||
boxed title style={colback=NeoBorder, sharp corners},
|
||||
coltext=WarlockDark,
|
||||
shadow={2mm}{-1mm}{0mm}{black!20!white},
|
||||
#1
|
||||
}
|
||||
|
||||
% --- INLINE CODE COMMAND ---
|
||||
\newcommand{\inlinecode}[1]{\colorbox{WarlockLightGray}{\small\texttt{\detokenize{#1}}}}
|
||||
|
||||
% --- HEADER & FOOTER ---
|
||||
\pagestyle{fancy}
|
||||
\fancyhf{}
|
||||
\fancyhead[L]{\textit{Warlock-Studio v5.0}}
|
||||
\fancyhead[R]{\leftmark}
|
||||
\fancyfoot[L]{\includegraphics[height=0.8cm]{logo.png}}
|
||||
\fancyfoot[C]{\thepage}
|
||||
\fancyfoot[R]{\textcopyright~2025 Warlock-Studio}
|
||||
\renewcommand{\headrulewidth}{0.4pt}
|
||||
\renewcommand{\footrulewidth}{0.4pt}
|
||||
\renewcommand{\sectionmark}[1]{\markboth{\thesection. #1}{}}
|
||||
|
||||
% =======================================================================================
|
||||
% BEGIN DOCUMENT
|
||||
% =======================================================================================
|
||||
\begin{document}
|
||||
|
||||
% --- REDESIGNED TITLE PAGE ---
|
||||
% --- COVER PAGE ---
|
||||
\begin{titlepage}
|
||||
\begin{tcolorbox}[
|
||||
enhanced, sharp corners,
|
||||
colback=WarlockDark, colframe=WarlockGold,
|
||||
boxrule=2pt,
|
||||
height=\textheight,
|
||||
halign=center, valign=center
|
||||
]
|
||||
\centering
|
||||
\includegraphics[width=0.4\textwidth]{logo.png}\par
|
||||
\begin{center}
|
||||
\vspace*{2cm}
|
||||
\includegraphics[width=0.4\textwidth]{logo.png}\\[1cm]
|
||||
|
||||
{\Huge \textbf{WARLOCK-STUDIO}}\\[0.5cm]
|
||||
{\Large \textit{AI Upscaling \& Interpolation Suite}}\\[0.2cm]
|
||||
{\large Version 5.1}
|
||||
|
||||
\vspace{2cm}
|
||||
|
||||
\begin{tcolorbox}[colback=WarlockDark, colframe=WarlockRed, width=0.8\textwidth, arc=2mm]
|
||||
\centering \textcolor{white}{\textbf{\Large USER OPERATING MANUAL}}
|
||||
\end{tcolorbox}
|
||||
|
||||
\vfill
|
||||
\color{WarlockWhite}
|
||||
{\Huge\bfseries\scshape Warlock-Studio\par}
|
||||
\vspace{1.5cm}
|
||||
\color{WarlockGold}
|
||||
\rule{0.6\textwidth}{1pt}\par
|
||||
\vspace{0.4cm}
|
||||
\color{WarlockWhite}
|
||||
{\Large\bfseries Technical Documentation and User Guide\par}
|
||||
\vspace{0.2cm}
|
||||
{\large Software Version: 5.0 (NEO-Refactor)\par}
|
||||
\vspace{0.4cm}
|
||||
\color{WarlockGold}
|
||||
\rule{0.6\textwidth}{1pt}\par
|
||||
\vfill
|
||||
{\large Iván Eduardo Chavez Ayub\par}
|
||||
\href{https://github.com/Ivan-Ayub97}{\texttt{\color{WarlockGold}\faGithub\ @Ivan-Ayub97}}\par
|
||||
\vspace{1.5cm}
|
||||
{\large \today\par}
|
||||
\end{tcolorbox}
|
||||
\thispagestyle{empty}
|
||||
|
||||
\textbf{Developed by Ivan-Ayub97}\\
|
||||
\today
|
||||
|
||||
\end{center}
|
||||
\end{titlepage}
|
||||
|
||||
\newpage
|
||||
\tableofcontents
|
||||
\newpage
|
||||
|
||||
% =======================================================================================
|
||||
% SECTION 1: INTRODUCTION
|
||||
% =======================================================================================
|
||||
\setsectioncolor{IntroColor}
|
||||
\section{Introduction to Warlock-Studio v5.0}
|
||||
Welcome to Warlock-Studio v5.0 — a major evolutionary leap in AI-powered media enhancement.
|
||||
This version introduces a robust \textbf{Modular Architecture} and the new \textbf{NEO Engine}, optimizing
|
||||
stability, hardware diagnostics, and processing efficiency. It provides advanced tools for super-resolution,
|
||||
artifact removal, and frame generation through an intuitive interface that now includes an \textbf{Integrated Console}
|
||||
and native \textbf{Drag \& Drop} support.
|
||||
% ---------------------------------------------------------
|
||||
% SECTION 1: INTRODUCTION
|
||||
% ---------------------------------------------------------
|
||||
\section{Introduction}
|
||||
Warlock-Studio is a comprehensive GUI application designed for AI-driven image and video enhancement. It integrates state-of-the-art neural networks to perform Upscaling, Denoising, Face Restoration, and Frame Interpolation.
|
||||
|
||||
% =======================================================================================
|
||||
% SECTION 2: QUICK START GUIDE
|
||||
% =======================================================================================
|
||||
\setsectioncolor{QuickStartColor}
|
||||
\section{Quick Start Guide}
|
||||
\begin{quickstartbox}{Accelerated Media Enhancement Procedure}
|
||||
Follow these steps to process your media using the new v5.0 workflow.
|
||||
\begin{enumerate}
|
||||
\item \textbf{Load Files (Drag \& Drop):} You can now simply \textbf{drag and drop} your image or video files directly onto the application window. Alternatively, click the \textbf{"Select Files"} button.
|
||||
\item \textbf{AI Model Selection:} In the \textbf{"AI model"} dropdown menu, select an inference model.
|
||||
Built on Python, CustomTkinter, and ONNX Runtime, Warlock-Studio optimizes hardware resources (CPU and GPU) to deliver great results.
|
||||
|
||||
\begin{infobox}{System Requirements}
|
||||
\begin{itemize}
|
||||
\item \textbf{OS:} Windows 10/11 (x64)
|
||||
\item \textbf{RAM:} Minimum 8GB (16GB+ recommended)
|
||||
\item \textbf{GPU:} NVIDIA (CUDA), AMD/Intel (DirectML), or CPU (Slow fallback)
|
||||
\item \textbf{Dependencies:} FFmpeg (included in assets), Visual C++ Redistributable.
|
||||
\end{itemize}
|
||||
\end{infobox}
|
||||
|
||||
% ---------------------------------------------------------
|
||||
% SECTION 2: INTERFACE & USAGE
|
||||
% ---------------------------------------------------------
|
||||
\section{Interface Overview & Usage}
|
||||
The interface is divided into functional blocks designed for a linear workflow: \textit{Load $\rightarrow$ Configure $\rightarrow$ Process}.
|
||||
|
||||
\subsection{1. Input Section}
|
||||
Located on the left side (or top, depending on layout), this area handles file ingestion.
|
||||
\begin{itemize}
|
||||
\item \textbf{Drag \& Drop:} You can drag images or videos directly onto the window.
|
||||
\item \textbf{Manual Select:} Clicking the button opens a file dialog.
|
||||
\item \textbf{File List:} Selected files appear in a scrollable list showing resolution, duration, and calculated output resolution based on current settings.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{2. AI Configuration}
|
||||
This is the core control panel.
|
||||
\begin{description}
|
||||
\item[AI Model:] Selects the neural network architecture (see Chapter 3).
|
||||
\item[AI Multithreading:] Controls how many frames are processed simultaneously.
|
||||
\begin{itemize}
|
||||
\item For photorealistic images, \inlinecode{BSRGANx4} is recommended for texture reconstruction.
|
||||
\item For animation/cartoons, \inlinecode{RealESR_Animex4} preserves sharp edges.
|
||||
\item For video, \inlinecode{RealESR_Gx4} balances speed and quality.
|
||||
\item For increasing framerate, use \inlinecode{RIFE} models (note: Blending controls will hide automatically).
|
||||
\item \textit{Recommendation:} Set to "2 threads" for mid-range GPUs. Use "OFF" (1 thread) for high-resolution upscaling (4K) to save VRAM.
|
||||
\end{itemize}
|
||||
\item \textbf{Verify Hardware (NEO Engine):} Click the \textbf{Gear Icon} (\faCog) to open Preferences. Check the \textbf{Hardware Diagnostics} to see the "Recommended Tiles" and "Safe VRAM Limit" calculated specifically for your PC.
|
||||
\item \textbf{Adjust Settings:} Set the \textbf{"GPU VRAM (GB)"} based on the recommendation. For a quick test, set \textbf{"Input resolution"} to \texttt{75}\%.
|
||||
\item \textbf{Start Processing:} Click \textbf{"Make Magic"}. You can now monitor real-time progress and logs via the new \textbf{Integrated Console} at the bottom of the window.
|
||||
\end{enumerate}
|
||||
\end{quickstartbox}
|
||||
\item[Frame Generation (RIFE):] Only active when RIFE models are selected. Interpolates frames to increase smoothness (e.g., 30fps $\rightarrow$ 60fps).
|
||||
\end{description}
|
||||
|
||||
% =======================================================================================
|
||||
% SECTION 3: INSTALLATION & ARCHITECTURE
|
||||
% =======================================================================================
|
||||
\setsectioncolor{InstallColor}
|
||||
\section{Installation and Modular Architecture}
|
||||
\subsection{\faDownload\ Installation Process \& Path Change}
|
||||
Warlock-Studio uses a self-contained offline installer.
|
||||
\subsection{3. Hardware & Performance}
|
||||
\begin{itemize}
|
||||
\item \textbf{GPU Selection:} Choose specific GPU or "Auto".
|
||||
\item \textbf{VRAM Limiter:} \textbf{Crucial Setting.} This defines the tile size for processing.
|
||||
\begin{itemize}
|
||||
\item \textit{Integrated Graphics:} Set to 2GB or lower.
|
||||
\item \textit{Dedicated GPU (e.g., RTX 3060):} Set to match your card's VRAM (e.g., 6GB-8GB).
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
|
||||
\begin{warnbox}{Critical: Installation Directory Change}
|
||||
In version 5.0, the default installation directory has been migrated from \texttt{Program Files} to:
|
||||
\begin{center}
|
||||
\inlinecode{\%userprofile\%\\Documents\\Warlock-Studio}
|
||||
\end{center}
|
||||
\textbf{Reason:} This change prevents "Permission Denied" errors on Windows systems with strict UAC. It ensures the application has full read/write access to generate the \inlinecode{warlock_config.json}, write real-time logs, and manage video checkpoints without requiring constant Administrator privileges.
|
||||
\end{warnbox}
|
||||
\begin{tipbox}{Tiling Technology}
|
||||
Warlock-Studio uses "Tiling". If an image is too large for VRAM, it splits the image into small squares, processes them, and merges them back. The \textbf{VRAM Limiter} controls the size of these squares.
|
||||
\end{tipbox}
|
||||
|
||||
\begin{enumerate}[leftmargin=*]
|
||||
\item \textbf{Obtaining the Executable:} Download the `Warlock-Studio-Setup.exe` (Full Installer) from the official repositories.
|
||||
\item \textbf{Run the Installer:} Run the setup. It will automatically default to your Documents folder.
|
||||
\item \textbf{Launch:} Open Warlock-Studio via the Desktop shortcut.
|
||||
\end{enumerate}
|
||||
\subsection{4. Resolution Control}
|
||||
\begin{itemize}
|
||||
\item \textbf{Input Resolution \%:} Downscales the image \textit{before} AI processing. Useful for speeding up 4K video processing (e.g., set to 50\%).
|
||||
\item \textbf{Output Resolution \%:} Downscales the image \textit{after} AI processing.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{\faMicrochip\ System Requirements}
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{\textwidth}{lX}
|
||||
\toprule
|
||||
\textbf{Component} & \textbf{Technical Specification} \\
|
||||
\midrule
|
||||
Operating System & Windows 11 or Windows 10 (64-bit architecture required). \\
|
||||
RAM & 8 GB (minimum), 16 GB (recommended). \\
|
||||
Graphics Card (GPU) & \textbf{Mandatory Requirement:} GPU with \textbf{DirectX 12} support. \\
|
||||
& \textbf{NVIDIA:} CUDA support (Maxwell or newer). \\
|
||||
& \textbf{AMD/Intel:} DirectML support. \\
|
||||
& \textbf{4+ GB of VRAM} is recommended. \\
|
||||
Storage & 2 GB of free disk space. SSD strongly recommended for video I/O. \\
|
||||
\bottomrule
|
||||
\end{tabularx}
|
||||
\caption{Requirements for v5.0. The NEO Engine will verify these upon launch.}
|
||||
\subsection{5. Output Settings}
|
||||
\begin{itemize}
|
||||
\item \textbf{Image Ext:} PNG (Lossless), JPG (Fast), BMP/TIFF (Uncompressed).
|
||||
\item \textbf{Video Ext:} MP4, MKV, AVI, MOV.
|
||||
\item \textbf{Video Codec:}
|
||||
\begin{itemize}
|
||||
\item \textbf{x264/x265:} CPU Encoding (High quality, slow).
|
||||
\item \textbf{NVENC:} NVIDIA Hardware (Fast).
|
||||
\item \textbf{AMF:} AMD Hardware.
|
||||
\item \textbf{QSV:} Intel Hardware.
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
|
||||
% ---------------------------------------------------------
|
||||
% SECTION 3: AI MODELS EXPLAINED
|
||||
% ---------------------------------------------------------
|
||||
\newpage
|
||||
\section{AI Models Library}
|
||||
Warlock-Studio includes varied models optimized for specific scenarios. Use this table to choose the right tool.
|
||||
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
\renewcommand{\arraystretch}{1.3}
|
||||
\begin{tabularx}{\textwidth}{|l|l|X|}
|
||||
\hline
|
||||
\rowcolor{WarlockDark} \textcolor{white}{\textbf{Category}} & \textcolor{white}{\textbf{Model Name}} & \textcolor{white}{\textbf{Best Use Case}} \\ \hline
|
||||
\multirow{2}{*}{\textbf{Denoising}} & IRCNN\_Mx1 & Removing grain/noise without changing resolution. Fast. \\
|
||||
& IRCNN\_Lx1 & Heavier denoising for very grainy sources. \\ \hline
|
||||
\multirow{2}{*}{\textbf{Anime / Art}} & RealESR\_Animex4 & \textbf{Best for Cartoons/Anime.} Removes compression artifacts and sharpens lines. \\
|
||||
& RealESR\_Gx4 & General purpose fast upscaling. \\ \hline
|
||||
\multirow{4}{*}{\textbf{Realistic}} & BSRGANx4 & \textbf{Best for Real World video.} Adds texture and realistic details. \\
|
||||
& BSRGANx2 & 2x version of above. Slightly faster. \\
|
||||
& RealESRGANx4 & Good balance between sharpness and texture. \\
|
||||
& RealESRNetx4 & Smoother look, less texture hallucination. \\ \hline
|
||||
\textbf{Faces} & GFPGAN & \textbf{Face Restoration.} Miraculous recovery of blurry/small faces. \\ \hline
|
||||
\textbf{Interpolation} & RIFE / Lite & Increasing Frame Rate (30$\rightarrow$60fps). Creates intermediate frames. \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Warlock-Studio Model Reference Guide}
|
||||
\end{table}
|
||||
|
||||
\subsection{\faPuzzlePiece\ Modular File Architecture (v5.0)}
|
||||
\begin{infobox}{From Monolithic to Modular}
|
||||
Version 5.0 abandons the single-script structure. The application is now composed of specialized modules to improve stability and maintainability.
|
||||
\end{infobox}
|
||||
|
||||
\begin{itemize}[leftmargin=*]
|
||||
\item \textbf{\inlinecode{Warlock-Studio.py} (Core Orchestrator):}
|
||||
Manages the main GUI event loop and spawns multiprocessing tasks for AI inference.
|
||||
\item \textbf{\inlinecode{warlock_preferences.py} (State Manager):}
|
||||
Houses the \textbf{NEO Engine} for hardware telemetry, the \inlinecode{ConfigManager} for JSON persistence, and the OTA Update Manager.
|
||||
\item \textbf{\inlinecode{console.py} (I/O Manager):}
|
||||
Controls the new \textbf{Integrated Console}, redirecting \texttt{stdout} and \texttt{stderr} streams to the GUI for real-time debugging.
|
||||
\item \textbf{\inlinecode{drag_drop.py} (Event Wrapper):}
|
||||
Implements the \inlinecode{DnDCTk} class to handle native OS Drag \& Drop events.
|
||||
\item \textbf{Assets:}
|
||||
Includes \inlinecode{ffmpeg.exe}, \inlinecode{exiftool.exe}, and the AI Models (`.onnx`) in the \texttt{AI-onnx} directory.
|
||||
\subsection*{When NOT to use certain models:}
|
||||
\begin{itemize}
|
||||
\item Do \textbf{not} use \textit{RealESR\_Animex4} on realistic photos; it will make skin look like plastic (oil painting effect).
|
||||
\item Do \textbf{not} use \textit{GFPGAN} on non-human subjects or high-quality faces (it might alter facial features slightly).
|
||||
\end{itemize}
|
||||
|
||||
% ---------------------------------------------------------
|
||||
% SECTION 4: WORKFLOW DIAGRAMS
|
||||
% ---------------------------------------------------------
|
||||
\section{Process Workflows}
|
||||
|
||||
% =======================================================================================
|
||||
% SECTION 4: DETAILED AI MODEL GUIDE
|
||||
% =======================================================================================
|
||||
\setsectioncolor{ModelsColor}
|
||||
\section{Detailed Analysis of Inference Models}
|
||||
\subsection{Video Upscaling Pipeline}
|
||||
Understanding the internal process helps in troubleshooting speed issues.
|
||||
|
||||
\begin{infobox}{Dynamic Interface Adaptation}
|
||||
In v5.0, the interface adapts to your model selection. Selecting a \textbf{RIFE} model will automatically hide "Blending" controls and reveal "Frame Generation" options. Selecting an \textbf{Upscaling} model does the reverse.
|
||||
\end{infobox}
|
||||
\vspace{0.5cm}
|
||||
|
||||
\subsection{\faTable\ Model Comparison Matrix}
|
||||
\begin{longtable}{p{2.8cm} p{1.8cm} p{1.2cm} p{1.5cm} p{7.2cm}}
|
||||
\toprule
|
||||
\textbf{Model} & \textbf{Function} & \textbf{Scale} & \textbf{VRAM} & \textbf{Use Case} \\
|
||||
\midrule
|
||||
\endhead
|
||||
\multicolumn{5}{c}{\textit{\textbf{\faEraser\ Denoising}}} \\
|
||||
\midrule
|
||||
\texttt{IRCNN\_Mx1} & Denoise & x1 & 4.0 & Moderate noise reduction (JPEG artifacts). \\
|
||||
\texttt{IRCNN\_Lx1} & Denoise & x1 & 4.0 & Intensive noise reduction for degraded images. \\
|
||||
\midrule
|
||||
\multicolumn{5}{c}{\textit{\textbf{\faTachometerAlt\ High-Fidelity Upscaling}}} \\
|
||||
\midrule
|
||||
\texttt{BSRGANx4} & Upscale & x4 & 0.6 & Photorealistic texture synthesis. Best for portraits/nature. \\
|
||||
\texttt{RealESRGANx4} & Upscale & x4 & 0.6 & General-purpose robust reconstruction. \\
|
||||
\midrule
|
||||
\multicolumn{5}{c}{\textit{\textbf{\faBolt\ High-Speed Upscaling}}} \\
|
||||
\midrule
|
||||
\texttt{RealESR\_Gx4} & Upscale & x4 & 2.2 & Fastest model. Optimized for video. \\
|
||||
\texttt{RealESR\_Animex4} & Upscale & x4 & 2.2 & Optimized for Anime/Cartoons (clean lines). \\
|
||||
\midrule
|
||||
\multicolumn{5}{c}{\textit{\textbf{\faUserCircle\ Facial Restoration}}} \\
|
||||
\midrule
|
||||
\texttt{GFPGAN} & Restore & x1 & 1.8 & Face reconstruction. v5.0 enforces \textbf{Float32} precision for stability. \\
|
||||
\midrule
|
||||
\multicolumn{5}{c}{\textit{\textbf{\faFilm\ Frame Interpolation (FluidFrames)}}} \\
|
||||
\midrule
|
||||
\texttt{RIFE} & Interpolate & N/A & \textasciitilde{}1.5 & Generates intermediate frames (x2, x4, x8). \\
|
||||
\texttt{RIFE\_Lite} & Interpolate & N/A & \textasciitilde{}1.2 & Faster variant for lower-end GPUs. \\
|
||||
\midrule
|
||||
\bottomrule
|
||||
\caption{Technical guide for AI models. VRAM values are base estimates.}
|
||||
\label{tab:modelos}
|
||||
\end{longtable}
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[node distance=1.5cm]
|
||||
\tikzstyle{startstop} = [rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=WarlockRed!30]
|
||||
\tikzstyle{process} = [rectangle, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=WarlockGold!30]
|
||||
\tikzstyle{decision} = [diamond, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=blue!10]
|
||||
\tikzstyle{arrow} = [thick,->,>=stealth]
|
||||
|
||||
% =======================================================================================
|
||||
% SECTION 5: OPTIMIZATION & NEO ENGINE
|
||||
% =======================================================================================
|
||||
\setsectioncolor{OptimizeColor}
|
||||
\section{Performance Optimization and NEO Engine}
|
||||
\node (in) [startstop] {Input Video};
|
||||
\node (extract) [process, below of=in] {Extract Frames (FFmpeg)};
|
||||
\node (resize1) [process, below of=extract] {Input Resize \%};
|
||||
\node (ai) [process, below of=resize1] {AI Inference (ONNX)};
|
||||
\node (blend) [decision, below of=ai, yshift=-0.5cm] {Blending?};
|
||||
\node (merge) [process, below of=blend, yshift=-0.5cm] {Merge Upscale + Original};
|
||||
\node (encode) [process, below of=merge] {Encode Video (FFmpeg)};
|
||||
\node (out) [startstop, below of=encode] {Output Video};
|
||||
|
||||
\subsection{\faMagic\ The NEO Engine}
|
||||
\begin{neobox}{Automatic Hardware Heuristics}
|
||||
Warlock-Studio v5.0 introduces the \textbf{NEO Engine} (located in \inlinecode{warlock_preferences.py}). This system scans your CPU, RAM, and GPU capabilities in real-time to generate \textbf{Smart Recommendations}.
|
||||
\end{neobox}
|
||||
\draw [arrow] (in) -- (extract);
|
||||
\draw [arrow] (extract) -- (resize1);
|
||||
\draw [arrow] (resize1) -- (ai);
|
||||
\draw [arrow] (ai) -- (blend);
|
||||
\draw [arrow] (blend) -- node[anchor=east] {Yes} (merge);
|
||||
\draw [arrow] (blend.east) -- ++(1,0) |- node[anchor=south] {No} (encode.east);
|
||||
\draw [arrow] (merge) -- (encode);
|
||||
\draw [arrow] (encode) -- (out);
|
||||
|
||||
\begin{itemize}[leftmargin=*, itemsep=2pt]
|
||||
\item \textbf{Safe VRAM Limit:} The engine calculates a safe buffer using the formula: $\max(0.5, \text{Physical VRAM} - 1.5 \text{ GB})$.
|
||||
\item \textbf{Recommended Tiles:} It suggests the optimal \inlinecode{tiles_resolution} to maximize speed while preventing Out-Of-Memory (OOM) crashes.
|
||||
\item \textbf{Thread Concurrency:} It analyzes your CPU topology (physical vs. logical cores) to suggest safe multithreading levels for video processing.
|
||||
\end{itemize}
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
|
||||
\subsection{\faSlidersH\ Critical Parameters}
|
||||
\begin{itemize}[leftmargin=*, itemsep=2pt]
|
||||
\item \textbf{Input Resolution \%:} Setting this to \textbf{75\%} drastically reduces load with minimal quality loss.
|
||||
\item \textbf{AI Multithreading:} (Video only) Processes multiple frames in parallel. Use the NEO Engine's recommendation to avoid system freezing.
|
||||
\item \textbf{Keep Frames:} Enable this (\inlinecode{selected_keep_frames = True}) if you plan to experiment with different video encoding codecs later.
|
||||
\end{itemize}
|
||||
% ---------------------------------------------------------
|
||||
% SECTION 5: TROUBLESHOOTING
|
||||
% ---------------------------------------------------------
|
||||
\newpage
|
||||
\section{Troubleshooting & Error Codes}
|
||||
|
||||
% =======================================================================================
|
||||
% SECTION 6: TROUBLESHOOTING
|
||||
% =======================================================================================
|
||||
\setsectioncolor{TroubleColor}
|
||||
\section{Diagnostics and Troubleshooting}
|
||||
\begin{warnbox}{Integrated Console}
|
||||
Use the new **Integrated Console** at the bottom of the app window to view real-time error logs, warnings, and processing status. You can search, copy, and save these logs.
|
||||
\end{warnbox}
|
||||
The integrated console (bottom of the app) provides real-time logs. Here are common errors and fixes.
|
||||
|
||||
\begin{description}[leftmargin=*, style=nextline, itemsep=0.8em]
|
||||
\item[\faBan\ Error: "FFmpeg encoding failed..." / Fallback Active]
|
||||
\textbf{Diagnosis:} The selected hardware codec (e.g., \inlinecode{hevc_nvenc}) failed due to driver issues or resource locking.
|
||||
\textbf{v5.0 Solution:} The system now features an \textbf{Automatic Fallback}. If the GPU encoder fails, it automatically switches to the CPU-based \inlinecode{libx264} encoder to ensure the video is finished. Check the console for yellow warnings indicating this switch.
|
||||
\subsection{Common Runtime Errors}
|
||||
|
||||
\item[\faMemory\ Error: "Out of memory" / OOM Recovery]
|
||||
\textbf{Diagnosis:} VRAM exhaustion during tiling.
|
||||
\textbf{v5.0 Solution:} The application detects this exception and triggers \textbf{Recursive Dynamic Tiling}. It automatically halves the tile resolution (e.g., 100\% $\to$ 50\%) and retries the frame. You do not need to restart the process manually.
|
||||
|
||||
\item[\faRocket\ Error: "Failed to load model" (ONNX)]
|
||||
\textbf{Diagnosis:} Issue initializing the execution provider.
|
||||
\textbf{Solution:} v5.0 implements a strict priority chain: CUDA $\to$ DirectML $\to$ CPU. Ensure your GPU drivers are up to date. If using an older NVIDIA card, the system may default to DirectML or CPU.
|
||||
|
||||
\item[\faTachometerAlt\ Error: "NaN" (Not a Number)]
|
||||
\textbf{Diagnosis:} GPU Driver Timeout (TDR).
|
||||
\textbf{Solution:} Restart the process without deleting the temp frames folder. The app will resume from the last successful frame.
|
||||
\end{description}
|
||||
|
||||
% =======================================================================================
|
||||
% SECTION 7: ADVANCED TECHNICAL ARCHITECTURE
|
||||
% =======================================================================================
|
||||
\setsectioncolor{ArchColor}
|
||||
\section{Software Architecture Analysis (v5.0)}
|
||||
|
||||
\subsection{\faCogs\ Modular Inference Engine}
|
||||
Warlock-Studio v5.0 utilizes a robust \textbf{ONNX Runtime} backend managed by the \inlinecode{create_onnx_session} factory in the core orchestrator. It enforces strict integer typing for device IDs to ensure compatibility with rigid DirectML backends.
|
||||
|
||||
\subsection{\faSyncAlt\ Lossless Intermediate Pipeline}
|
||||
In v5.0, the video extraction pipeline (\inlinecode{extract_video_frames}) strictly enforces the use of \textbf{.PNG} containers for temporary frames. This eliminates the generation loss previously caused by JPEG artifacts before the image entered the neural network.
|
||||
|
||||
\subsection{\faThLarge\ Architecture Diagram (Modular)}
|
||||
\noindent
|
||||
Updated component-level architecture illustrating the new modular design and the interaction between the GUI, the NEO Engine, and the Core Orchestrator.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\resizebox{\textwidth}{!}{%
|
||||
\begin{tikzpicture}[node distance=12mm, every node/.style={font=\small}]
|
||||
\tikzset{
|
||||
module/.style={rectangle, rounded corners=3pt, draw=WarlockDark!70!black, fill=WarlockDark!6, minimum width=42mm, minimum height=10mm, align=center, drop shadow},
|
||||
core/.style={rectangle, rounded corners=3pt, draw=WarlockGold!80!black, fill=WarlockGold!15, minimum width=42mm, minimum height=10mm, align=center, drop shadow},
|
||||
hw/.style={rectangle, rounded corners=3pt, draw=WarlockGray!80!black, fill=WarlockLightGray, minimum width=42mm, minimum height=10mm, align=center},
|
||||
line/.style={-Latex, thick, color=WarlockGray!90!black}
|
||||
}
|
||||
|
||||
% Nodes
|
||||
\node[module] (gui) {\textbf{GUI Frontend}\\(Main Window +\\Drag\&Drop Wrapper)};
|
||||
\node[module, left=15mm of gui] (prefs) {\textbf{Warlock Prefs}\\(NEO Engine +\\Update Manager)};
|
||||
\node[module, right=15mm of gui] (console) {\textbf{Console Manager}\\(Stream Redirection)};
|
||||
|
||||
\node[core, below=15mm of gui] (orch) {\textbf{Core Orchestrator}\\(Multiprocessing)};
|
||||
|
||||
\node[module, below=15mm of orch] (ai) {\textbf{AI Engine}\\(ONNX Runtime)};
|
||||
\node[module, right=15mm of ai] (io) {\textbf{I/O \& Encoding}\\(FFmpeg / Fallback)};
|
||||
|
||||
\node[hw, below=12mm of ai] (gpu) {\textbf{Hardware}\\(CUDA / DirectML)};
|
||||
\node[hw, below=12mm of io] (disk) {\textbf{Storage}\\(Logs/Config/Frames)};
|
||||
|
||||
% Connections
|
||||
\draw[line] (prefs) -- (gui);
|
||||
\draw[line] (console) -- (gui);
|
||||
\draw[line] (gui) -- (orch);
|
||||
\draw[line] (orch) -- (ai);
|
||||
\draw[line] (orch) -- (io);
|
||||
\draw[line] (ai) -- (gpu);
|
||||
\draw[line] (io) -- (disk);
|
||||
\draw[line, dashed] (prefs) |- (disk);
|
||||
|
||||
\end{tikzpicture}
|
||||
}
|
||||
\caption{Warlock-Studio v5.0 Modular Component Architecture.}
|
||||
\end{figure}
|
||||
|
||||
% =======================================================================================
|
||||
% SECTION 8: GLOSSARY
|
||||
% =======================================================================================
|
||||
\setsectioncolor{GlossaryColor}
|
||||
\section{Glossary}
|
||||
\begin{description}[leftmargin=*, style=nextline, itemsep=0.8em]
|
||||
\item[NEO Engine] The new heuristic subsystem in v5.0 responsible for hardware scanning, diagnostics, and configuration recommendation.
|
||||
\item[Modular Architecture] A software design technique that splits the code into separate, independent modules (`console`, `preferences`, `core`) to improve maintainability.
|
||||
\item[ONNX Runtime] The cross-platform engine used to run the AI models. v5.0 enforces strict device ID typing.
|
||||
\item[OOM Recovery] (Out Of Memory) An automatic mechanism that reduces tile size when VRAM is exhausted to prevent crashes.
|
||||
\item[DirectML] (Direct Machine Learning) API used for GPU acceleration on AMD and Intel cards.
|
||||
\end{description}
|
||||
|
||||
% =======================================================================================
|
||||
% SECTION 9: SUPPORT & CONTRIBUTIONS
|
||||
% =======================================================================================
|
||||
\setsectioncolor{SupportColor}
|
||||
\section{Support and Community}
|
||||
\begin{itemize}[leftmargin=*]
|
||||
\item \textbf{\faBook\ Manual:} Click the \textbf{Book Icon} in the app header to open this PDF document.
|
||||
\item \textbf{\faBug\ Reporting Issues:} Report bugs on GitHub. Please attach the \inlinecode{error_log.txt} file located in your \textbf{Documents} folder.
|
||||
\item \textbf{\faSync\ Updates:} Use the internal \textbf{Update Manager} (Gear Icon $\to$ Check Updates) to download the latest version directly.
|
||||
\item \textbf{\faEnvelope\ Contact:} For non-bug related inquiries: \href{mailto:negroayub97@gmail.com}{\texttt{negroayub97@gmail.com}}.
|
||||
\end{itemize}
|
||||
\vspace{1cm}
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
\textbf{Thank you for using Warlock-Studio v5.0.}
|
||||
\begin{tabularx}{\textwidth}{|l|X|}
|
||||
\hline
|
||||
\rowcolor{WarlockRed} \textcolor{white}{\textbf{Error / Symptom}} & \textcolor{white}{\textbf{Solution}} \\ \hline
|
||||
\textbf{CUDA / Out of Memory} & The AI model requires more VRAM than available. \newline \textbf{Fix:} Lower the "GPU VRAM" setting (e.g., set to 2). Lower "AI Multithreading" to OFF. \\ \hline
|
||||
\textbf{FFmpeg not found} & The application cannot process video/audio. \newline \textbf{Fix:} Ensure \texttt{ffmpeg.exe} is in the \texttt{Assets/} folder. \\ \hline
|
||||
\textbf{Gray/Black Output} & Often caused by incompatible Video Codecs. \newline \textbf{Fix:} Switch output codec to \texttt{x264} (Software) or check GPU driver updates. \\ \hline
|
||||
\textbf{Process Stops Immediately} & File path issue. \newline \textbf{Fix:} Avoid special characters or emojis in filenames/folders. Move files to a simple path like \texttt{C:/Upscale/}. \\ \hline
|
||||
\textbf{DLL Load Failed} & Missing Visual C++ dependencies. \newline \textbf{Fix:} Install latest MSVC Redistributable. \\ \hline
|
||||
\end{tabularx}
|
||||
\end{table}
|
||||
|
||||
\begin{warningbox}{Checkpoint Recovery}
|
||||
If the app crashes during a long video upscale, \textbf{do not delete the temporary folder}. Warlock-Studio will detect the processed frames and resume from where it left off automatically upon restarting the same job.
|
||||
\end{warningbox}
|
||||
|
||||
\subsection{Performance Tuning Tips}
|
||||
\begin{itemize}
|
||||
\item \textbf{Slow Speed?} Ensure "Process Priority" in Preferences is set to "High". Check if you are using CPU instead of GPU (Console will say \texttt{CPUExecutionProvider}).
|
||||
\item \textbf{Low Quality?} Try disabling "Blending" (set to OFF). Increase "Input Resolution \%" to 100.
|
||||
\item \textbf{Glitchy Video?} If using Interpolation (RIFE), scene changes might look weird. This is a limitation of current AI flow generation.
|
||||
\end{itemize}
|
||||
|
||||
% ---------------------------------------------------------
|
||||
% SECTION 6: PREFERENCES
|
||||
% ---------------------------------------------------------
|
||||
\section{Preferences Menu}
|
||||
Accessible via the \faCog\ icon in the top right.
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{App Theme:} Switch between Dark/Light modes.
|
||||
\item \textbf{ONNX Provider:} Force specific backend (CUDA vs DirectML). \textit{Auto} is recommended.
|
||||
\item \textbf{Clean Temp Files:} Removes leftover \texttt{.tmp} files and frame folders from crashed sessions.
|
||||
\item \textbf{Extended Logging:} Enables detailed debug logs for error reporting.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{2cm}
|
||||
\begin{center}
|
||||
\textit{Warlock-Studio is an open-source tool. \\ Thank you for using it.}
|
||||
\end{center}
|
||||
|
||||
% =======================================================================================
|
||||
% END OF DOCUMENT
|
||||
% =======================================================================================
|
||||
\end{document}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<br>
|
||||
|
||||
**Warlock-Studio** is a unified, high-performance platform for **upscaling, restoration, denoising, and frame interpolation**.
|
||||
**Warlock-Studio** is a unified, high-performance platform for **upscaling, restoration, denoising, and frame interpolation**.
|
||||
Inspired by [Djdefrag](https://github.com/Djdefrag) tools such as **QualityScaler** and **FluidFrames**.
|
||||
|
||||
---
|
||||
@@ -21,54 +21,45 @@ Inspired by [Djdefrag](https://github.com/Djdefrag) tools such as **QualityScale
|
||||
## 📥 <span style="color:#FFD700;">Download Installer</span>
|
||||
|
||||
<div align="center">
|
||||
<p style="color:#ccc; font-size:14px; line-height: 1.6;">
|
||||
This installer was built using <b>PyInstaller</b> and <b>Inno Setup</b>.<br>
|
||||
By default, it includes <b>DirectML</b> support to ensure maximum compatibility with any graphics card (NVIDIA/AMD/INTEL).
|
||||
</p>
|
||||
<p style="color:#ccc; font-size:14px; margin-top: 15px;">
|
||||
Select your preferred option to download the latest version (Direct Release/SourceForge):
|
||||
</p>
|
||||
<p style="color:#ccc; font-size:14px; line-height: 1.6;">
|
||||
This installer was built using <b>PyInstaller</b> and <b>Inno Setup</b>.<br>
|
||||
By default, it includes <b>DirectML</b> support to ensure maximum compatibility with any graphics card (NVIDIA/AMD/INTEL).
|
||||
<p style="color:#ccc; font-size:14px; margin-top: 15px;">
|
||||
Select your preferred option to download the latest version (Direct Release/SourceForge):
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<table align="center" style="width:100%; border-collapse:collapse; border:none;">
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center" style="vertical-align:top; width:50%; border:none; padding:20px;">
|
||||
<a href="https://github.com/Ivan-Ayub97/Warlock-Studio/releases/download/v5.0/Warlock-Studio-5.0-Full-Installer.exe" target="_blank">
|
||||
<img src="rsc/GitHub_Logo_WS.png" alt="Download from GitHub" width="300" style="display:block; margin:auto; margin-bottom:15px;" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" style="vertical-align:top; width:50%; border:none; padding:20px;">
|
||||
<a href="https://sourceforge.net/projects/warlock-studio/" target="_blank">
|
||||
<img src="https://sourceforge.net/cdn/syndication/badge_img/3880091/oss-rising-star-black" alt="Warlock-Studio on SourceForge" width="200" style="display:block; margin:auto; margin-bottom:15px; border-radius:5px;" />
|
||||
</a>
|
||||
</tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center" style="vertical-align:top; width:50%; border:none; padding:20px;">
|
||||
<a href="https://github.com/Ivan-Ayub97/Warlock-Studio/releases/download/v5.1/Warlock-Studio-5.1-Full-Installer.exe" target="_blank">
|
||||
<img src="rsc/GitHub_Logo_WS.png" alt="Download from GitHub" width="300" style="display:block; margin:auto; margin-bottom:15px;" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" style="vertical-align:top; width:50%; border:none; padding:20px;">
|
||||
<a href="https://sourceforge.net/projects/warlock-studio/" target="_blank">
|
||||
<img src="https://sourceforge.net/cdn/syndication/badge_img/3880091/oss-rising-star-black" alt="Warlock-Studio on SourceForge" width="200" style="display:block; margin:auto; margin-bottom:15px; border-radius:5px;" />
|
||||
</a>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
---
|
||||
|
||||
## ✨ What is New in v5.0
|
||||
|
||||
The **v5.0** release represents a foundational transformation of the application:
|
||||
|
||||
* **🧩 Modular Architecture:** The core has been re-engineered into specialized components (`core`, `preferences`, `console`, `drag_drop`) for superior stability and fault isolation.
|
||||
* **🧠 NEO Engine:** A new diagnostic subsystem that scans CPU topology, RAM, and GPU VRAM to automatically recommend optimal tiling and thread settings.
|
||||
* **🖥️ Integrated Debug Console:** A real-time GUI terminal that intercepts `stdout` and `stderr` with syntax highlighting, allowing users to diagnose FFmpeg or ONNX issues instantly.
|
||||
* **⚡ Native CUDA & Failover:** The backend now strictly prioritizes **CUDA** (NVIDIA Optimized) > **DirectML** > **CPU**, with corrected integer typing for device IDs.
|
||||
* **💎 Lossless Pipeline:** Deprecated `.jpg` usage in favor of `.png` for intermediate frames to prevent compression artifacts (blurriness).
|
||||
|
||||
---
|
||||
|
||||
## 🖼️ Interface Previews
|
||||
|
||||
<div align="center">
|
||||
<img src="rsc/Capture.png" alt="Main Interface" style="border-radius: 10px; box-shadow: 0px 0px 20px rgba(0,0,0,0.5);">
|
||||
</div>
|
||||
---
|
||||
|
||||
<br>
|
||||
## 🚀 <span style="color:#FFD43B;">Version 5.1 Highlights (Decoupling & Precision)</span>
|
||||
|
||||
Version 5.1 introduces significant structural and algorithmic improvements, transforming the application's stability and file handling efficiency.
|
||||
|
||||
- **Asynchronous Architecture (New `FileQueueManager`):** File I/O operations (metadata reading, thumbnail generation) are now offloaded to background threads. This eliminates UI freezes (ANR) during batch processing and ensures a non-blocking user experience.
|
||||
- **Critical AI Correction:** Implemented **Dynamic Padding** for the RIFE frame interpolation algorithm. This surgically corrects a mathematical deficiency, guaranteeing artifact-free video output regardless of the source video's resolution (eliminates black/green edge artifacts).
|
||||
- **Preferences Redesign:** The Settings panel has been completely re-engineered into a modern **Sidebar Navigation** system, improving categorization and usability.
|
||||
- **Diagnostic Suite:** Added an integrated Real-Time Log Viewer and an automatic **Debug Package Export** tool to streamline error reporting.
|
||||
- **Enhanced Stability:** Introduced **Binary Path Overrides** for FFmpeg/ExifTool, rigorous thread-safe UI updates, and safer process shutdown handling.
|
||||
|
||||
### ⚙️ Preferences
|
||||
[Preferences.webm](https://github.com/user-attachments/assets/933003de-7618-4ed4-8815-077c69bf1ebc)
|
||||
|
||||
---
|
||||
|
||||
@@ -84,25 +75,25 @@ The **v5.0** release represents a foundational transformation of the application
|
||||
|
||||
## ✨ Key Features
|
||||
|
||||
* **AI Upscaling & Restoration** – Utilize **Real-ESRGAN, BSRGAN, RealESRNet, RealESR_Animex4, and IRCNN** models for denoising, super-resolution, and detail recovery.
|
||||
* **Face Restoration (GFPGAN)** – Recover facial details from low-resolution or blurry images and video frames.
|
||||
* **Frame Interpolation (RIFE)** – Smooth motion or generate slow-motion content with **2×, 4×, or 8× interpolation**.
|
||||
* **Advanced Hardware Acceleration** – Intelligent provider selection prioritizes **CUDA**, falls back to **DirectML**, and finally **CPU** for maximum compatibility.
|
||||
* **Batch Processing** – Process multiple media files simultaneously, saving time and effort.
|
||||
* **Custom Workflows** – Fine-grained control over models, resolution, output formats, and quality parameters.
|
||||
* **Open-Source & Extensible** – Fully MIT licensed, for contributors and developers.
|
||||
- **AI Upscaling & Restoration** – Utilize **Real-ESRGAN, BSRGAN, RealESRNet, RealESR_Animex4, and IRCNN** models for denoising, super-resolution, and detail recovery.
|
||||
- **Face Restoration (GFPGAN)** – Recover facial details from low-resolution or blurry images and video frames.
|
||||
- **Frame Interpolation (RIFE)** – Smooth motion or generate slow-motion content with **2×, 4×, or 8× interpolation**.
|
||||
- **Advanced Hardware Acceleration** – Intelligent provider selection prioritizes **CUDA**, falls back to **DirectML**, and finally **CPU** for maximum compatibility.
|
||||
- **Batch Processing** – Process multiple media files simultaneously, saving time and effort.
|
||||
- **Custom Workflows** – Fine-grained control over models, resolution, output formats, and quality parameters.
|
||||
- **Open-Source & Extensible** – Fully MIT licensed, for contributors and developers.
|
||||
|
||||
---
|
||||
|
||||
## 🖥️ System Requirements
|
||||
|
||||
| Component | Minimum Specification | Recommended Specification |
|
||||
| :--- | :--- | :--- |
|
||||
| **OS** | Windows 10 (64-bit) | Windows 11 (64-bit) |
|
||||
| **RAM** | 8 GB | 16 GB+ (Recommended for 4K Video) |
|
||||
| GPU | DirectX 12 Compatible | NVIDIA RTX 2060 / AMD RX 6700 XT | NVIDIA RTX 4070 Ti / AMD RX 7900 XT or better |
|
||||
| **VRAM** | 4 GB | 8 GB+ (NEO Engine auto-tunes limits) |
|
||||
| **Storage** | HDD Space | NVMe SSD (Highly recommended for RIFE) |
|
||||
| Component | Minimum Specification | Recommended Specification |
|
||||
| :---------- | :-------------------- | :------------------------------------- | --------------------------------------------- |
|
||||
| **OS** | Windows 10 (64-bit) | Windows 11 (64-bit) |
|
||||
| **RAM** | 8 GB | 16 GB+ (Recommended for 4K Video) |
|
||||
| GPU | DirectX 12 Compatible | NVIDIA RTX 2060 / AMD RX 6700 XT | NVIDIA RTX 4070 Ti / AMD RX 7900 XT or better |
|
||||
| **VRAM** | 4 GB | 8 GB+ (NEO Engine auto-tunes limits) |
|
||||
| **Storage** | HDD Space | NVMe SSD (Highly recommended for RIFE) |
|
||||
|
||||
---
|
||||
|
||||
@@ -110,9 +101,9 @@ The **v5.0** release represents a foundational transformation of the application
|
||||
|
||||
We welcome contributions from the community:
|
||||
|
||||
1. **Fork** the repository.
|
||||
2. **Create a branch** for your feature or bug fix.
|
||||
3. **Submit a Pull Request** with a detailed description and testing notes.
|
||||
1. **Fork** the repository.
|
||||
2. **Create a branch** for your feature or bug fix.
|
||||
3. **Submit a Pull Request** with a detailed description and testing notes.
|
||||
|
||||
📧 Contact: **[negroayub97@gmail.com](mailto:negroayub97@gmail.com)**
|
||||
|
||||
@@ -125,43 +116,26 @@ We welcome contributions from the community:
|
||||
|
||||
### 📊 Integrated Technologies & Licenses
|
||||
|
||||
| Technology / Model | License | Author / Maintainer | Source |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **Real-ESRGAN** | BSD 3-Clause | Xintao Wang | [GitHub](https://github.com/xinntao/Real-ESRGAN) |
|
||||
| • RealESRGANx4 | BSD 3-Clause | Xintao Wang | Same as above |
|
||||
| • RealESRNetx4 | BSD 3-Clause | Xintao Wang | Same as above |
|
||||
| • RealESR_Gx4 (Custom Variant) | BSD 3-Clause | Xintao / Community | Same as above |
|
||||
| • RealESR_Animex4 (Anime Model) | BSD 3-Clause | Community | Same as above |
|
||||
| **BSRGAN** | Apache 2.0 | Kai Zhang | [GitHub](https://github.com/cszn/BSRGAN) |
|
||||
| • BSRGANx4 | Apache 2.0 | Kai Zhang | Same as above |
|
||||
| • BSRGANx2 | Apache 2.0 | Kai Zhang | Same as above |
|
||||
| **IRCNN** | BSD / Mixed | Kai Zhang | [GitHub](https://github.com/cszn/IRCNN) |
|
||||
| • IRCNN_Mx1 | BSD / Mixed | Kai Zhang | Same as above |
|
||||
| • IRCNN_Lx1 | BSD / Mixed | Kai Zhang | Same as above |
|
||||
| **GFPGAN** | Apache 2.0 | TencentARC | [GitHub](https://github.com/TencentARC/GFPGAN) |
|
||||
| **RIFE** | Apache 2.0 | hzwer | [GitHub](https://github.com/megvii-research/ECCV2022-RIFE) |
|
||||
| **QualityScaler** | MIT | Djdefrag | [GitHub](https://github.com/Djdefrag/QualityScaler) |
|
||||
| **FluidFrames** | MIT | Djdefrag | [GitHub](https://github.com/Djdefrag/FluidFrames) |
|
||||
| **ONNX Runtime** | MIT | Microsoft | [GitHub](https://github.com/microsoft/onnxruntime) |
|
||||
| **FFmpeg** | LGPL / GPL | FFmpeg Team | [Official Site](https://ffmpeg.org) |
|
||||
| **ExifTool** | Artistic | Phil Harvey | [Official Site](https://exiftool.org/) |
|
||||
| **Python** | PSF License | Python Software Foundation | [Official Site](https://www.python.org) |
|
||||
| **PyInstaller** | GPLv2+ | PyInstaller Team | [GitHub](https://github.com/pyinstaller/pyinstaller) |
|
||||
| **Inno Setup** | Custom | Jordan Russell | [Official Site](http://www.jrsoftware.org/isinfo.php) |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
| Technology / Model | License | Author / Maintainer | Source |
|
||||
| :------------------------------ | :----------- | :------------------------- | :--------------------------------------------------------- |
|
||||
| **Real-ESRGAN** | BSD 3-Clause | Xintao Wang | [GitHub](https://github.com/xinntao/Real-ESRGAN) |
|
||||
| • RealESRGANx4 | BSD 3-Clause | Xintao Wang | Same as above |
|
||||
| • RealESRNetx4 | BSD 3-Clause | Xintao Wang | Same as above |
|
||||
| • RealESR_Gx4 (Custom Variant) | BSD 3-Clause | Xintao / Community | Same as above |
|
||||
| • RealESR_Animex4 (Anime Model) | BSD 3-Clause | Community | Same as above |
|
||||
| **BSRGAN** | Apache 2.0 | Kai Zhang | [GitHub](https://github.com/cszn/BSRGAN) |
|
||||
| • BSRGANx4 | Apache 2.0 | Kai Zhang | Same as above |
|
||||
| • BSRGANx2 | Apache 2.0 | Kai Zhang | Same as above |
|
||||
| **IRCNN** | BSD / Mixed | Kai Zhang | [GitHub](https://github.com/cszn/IRCNN) |
|
||||
| • IRCNN_Mx1 | BSD / Mixed | Kai Zhang | Same as above |
|
||||
| • IRCNN_Lx1 | BSD / Mixed | Kai Zhang | Same as above |
|
||||
| **GFPGAN** | Apache 2.0 | TencentARC | [GitHub](https://github.com/TencentARC/GFPGAN) |
|
||||
| **RIFE** | Apache 2.0 | hzwer | [GitHub](https://github.com/megvii-research/ECCV2022-RIFE) |
|
||||
| **QualityScaler** | MIT | Djdefrag | [GitHub](https://github.com/Djdefrag/QualityScaler) |
|
||||
| **FluidFrames** | MIT | Djdefrag | [GitHub](https://github.com/Djdefrag/FluidFrames) |
|
||||
| **ONNX Runtime** | MIT | Microsoft | [GitHub](https://github.com/microsoft/onnxruntime) |
|
||||
| **FFmpeg** | LGPL / GPL | FFmpeg Team | [Official Site](https://ffmpeg.org) |
|
||||
| **ExifTool** | Artistic | Phil Harvey | [Official Site](https://exiftool.org/) |
|
||||
| **Python** | PSF License | Python Software Foundation | [Official Site](https://www.python.org) |
|
||||
| **PyInstaller** | GPLv2+ | PyInstaller Team | [GitHub](https://github.com/pyinstaller/pyinstaller) |
|
||||
| **Inno Setup** | Custom | Jordan Russell | [Official Site](http://www.jrsoftware.org/isinfo.php) |
|
||||
|
||||
@@ -6,6 +6,7 @@ We aim to support the most recent stable release of Warlock-Studio. Security upd
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | --------- |
|
||||
| 5.1.x | ✅ |
|
||||
| 5.0.x | ✅ |
|
||||
| 4.3.x | ✅ |
|
||||
| 4.2.1 | ✅ |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#define AppName "Warlock-Studio"
|
||||
#define AppVersion "5.0"
|
||||
#define AppPublisher "Ivan-Ayub97|Ivanayub1997"
|
||||
#define AppVersion "5.1"
|
||||
#define AppPublisher "Ivan-Ayub97 on GH| Ivanayub1997 on SF"
|
||||
#define AppURL "https://github.com/Ivan-Ayub97/Warlock-Studio"
|
||||
#define AppExeName "Warlock-Studio.exe"
|
||||
|
||||
@@ -15,6 +15,7 @@ DefaultDirName={userdocs}\{#AppName}
|
||||
DefaultGroupName={#AppName}
|
||||
AllowNoIcons=yes
|
||||
PrivilegesRequired=none
|
||||
AppId={{7CC447B5-CDCF-494D-A432-378B744C0EE6}
|
||||
|
||||
; --- Configuración del Instalador ---
|
||||
OutputDir=Output
|
||||
|
||||
+242
-316
@@ -42,10 +42,12 @@ from subprocess import run as subprocess_run
|
||||
from threading import Event, Lock, Thread
|
||||
from time import sleep
|
||||
from timeit import default_timer as timer
|
||||
from tkinter import DISABLED, StringVar
|
||||
from tkinter import DISABLED, StringVar, messagebox
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
||||
from webbrowser import open as open_browser
|
||||
|
||||
import customtkinter as ctk
|
||||
import cv2
|
||||
# ONNX Runtime imports
|
||||
import onnxruntime
|
||||
# GUI imports (CustomTkinter & TkinterDnD)
|
||||
@@ -88,6 +90,7 @@ from numpy import transpose as numpy_transpose
|
||||
from numpy import uint8
|
||||
from numpy import zeros as numpy_zeros
|
||||
from onnxruntime import InferenceSession
|
||||
# Necesitarás PIL para cargar el icono de limpieza que pide el constructor
|
||||
from PIL import Image
|
||||
from PIL.Image import fromarray as pillow_image_fromarray
|
||||
from PIL.Image import open as pillow_image_open
|
||||
@@ -102,6 +105,8 @@ from tkinterdnd2 import DND_ALL, TkinterDnD
|
||||
from console import IntegratedConsole, console
|
||||
# Local imports
|
||||
from drag_drop import DnDCTk, enable_drag_and_drop
|
||||
# Importa la clase de tu archivo (asumiendo que se llama file_queue_manager.py)
|
||||
from file_queue_manager import FileQueueManager
|
||||
from warlock_preferences import PreferencesButton # Importación local
|
||||
|
||||
# Redirigir inmediatamente para capturar logs de importación
|
||||
@@ -123,9 +128,8 @@ def find_by_relative_path(relative_path: str) -> str:
|
||||
return os_path_join(base_path, relative_path)
|
||||
|
||||
|
||||
# Application Info
|
||||
app_name = "Warlock-Studio"
|
||||
version = "5.0"
|
||||
version = "5.1"
|
||||
|
||||
# Supported File Extensions
|
||||
supported_image_extensions = [".jpg", ".jpeg",
|
||||
@@ -138,16 +142,20 @@ supported_file_extensions = supported_image_extensions + supported_video_extensi
|
||||
# THEME & COLORS
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# THEME & COLORS
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Fondo: Negro casi puro, igual que el fondo del banner para máximo contraste
|
||||
background_color = "#1B1818"
|
||||
background_color = "#0A0A0A"
|
||||
# Nombre de la app: Plata metálico, inspirado en el texto "STUDIO"
|
||||
app_name_color = "#FF4848"
|
||||
app_name_color = "#FAF600"
|
||||
# Paneles: Gris oscuro neutro, permite que el rojo y dorado resalten sin competir
|
||||
widget_background_color = "#2A2727"
|
||||
widget_background_color = "#303030"
|
||||
# Texto principal: Blanco puro para legibilidad máxima
|
||||
text_color = "#FFFFFF"
|
||||
# Texto secundario: Dorado pálido/desaturado, para no cansar la vista pero mantener la identidad
|
||||
secondary_text_color = "#CAC9C9"
|
||||
secondary_text_color = "#B5B4B4"
|
||||
# Acento: El amarillo dorado brillante del sombrero y los destellos (Sparkles)
|
||||
accent_color = "#FDEF2F"
|
||||
# Hover de botones: El rojo vibrante del relleno del texto "WARLOCK"
|
||||
@@ -155,13 +163,13 @@ button_hover_color = "#D41C1C"
|
||||
# Bordes: Un dorado oscuro muy sutil, imitando el borde del logo sin ser chillón
|
||||
border_color = "#E2340D"
|
||||
# Botones info/secundarios: El rojo sangre oscuro del fondo del círculo del logo
|
||||
info_button_color = "#212121"
|
||||
info_button_color = "#770000"
|
||||
# Advertencias: Naranja dorado, sacado del sombreado del sombrero
|
||||
warning_color = "#FFA000"
|
||||
# Éxito: Verde brillante, necesario para contraste funcional
|
||||
success_color = "#00E676"
|
||||
# Error: Rojo carmesí intenso, similar al borde de las letras "WARLOCK"
|
||||
error_color = "#B00020"
|
||||
error_color = "#81091F"
|
||||
# Resaltado: Amarillo luz, como el centro de los destellos (estrellas)
|
||||
highlight_color = "#FFFF8D"
|
||||
# Scrollbars: Rojo vino oscuro translúcido, para mantener la temática sin distraer
|
||||
@@ -921,12 +929,12 @@ class AI_upscale:
|
||||
|
||||
return final_image
|
||||
|
||||
# AI INTERPOLATION for frame generation -----------------
|
||||
|
||||
|
||||
class AI_interpolation:
|
||||
|
||||
# CLASS INIT FUNCTIONS
|
||||
# -------------------------------------------------------------------------
|
||||
# CLASS INIT
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -936,7 +944,6 @@ class AI_interpolation:
|
||||
input_resize_factor: int,
|
||||
output_resize_factor: int,
|
||||
):
|
||||
|
||||
# Passed variables
|
||||
self.AI_model_name = AI_model_name
|
||||
self.frame_gen_factor = frame_gen_factor
|
||||
@@ -947,6 +954,10 @@ class AI_interpolation:
|
||||
# Calculated variables
|
||||
self.AI_model_path = find_by_relative_path(
|
||||
f"AI-onnx{os_separator}{self.AI_model_name}_fp32.onnx")
|
||||
|
||||
# RIFE requiere múltiplos de 32 para evitar artefactos
|
||||
self.divisor = 32
|
||||
|
||||
self.inferenceSession = self._load_inferenceSession()
|
||||
|
||||
def _load_inferenceSession(self) -> InferenceSession:
|
||||
@@ -958,18 +969,18 @@ class AI_interpolation:
|
||||
print(f"[AI ERROR] {error_msg}")
|
||||
raise RuntimeError(error_msg)
|
||||
|
||||
# INTERNAL CLASS FUNCTIONS
|
||||
# -------------------------------------------------------------------------
|
||||
# INTERNAL UTILS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def get_image_mode(self, image: numpy_ndarray) -> str:
|
||||
if image is None:
|
||||
raise ValueError("Image is None")
|
||||
shape = image.shape
|
||||
if len(shape) == 2: # Grayscale: 2D array (rows, cols)
|
||||
if len(shape) == 2:
|
||||
return "Grayscale"
|
||||
# RGB: 3D array with 3 channels
|
||||
elif len(shape) == 3 and shape[2] == 3:
|
||||
return "RGB"
|
||||
# RGBA: 3D array with 4 channels
|
||||
elif len(shape) == 3 and shape[2] == 4:
|
||||
return "RGBA"
|
||||
else:
|
||||
@@ -978,16 +989,15 @@ class AI_interpolation:
|
||||
def get_image_resolution(self, image: numpy_ndarray) -> tuple:
|
||||
height = image.shape[0]
|
||||
width = image.shape[1]
|
||||
|
||||
return height, width
|
||||
|
||||
def resize_with_input_factor(self, image: numpy_ndarray) -> numpy_ndarray:
|
||||
|
||||
old_height, old_width = self.get_image_resolution(image)
|
||||
|
||||
new_width = int(old_width * self.input_resize_factor)
|
||||
new_height = int(old_height * self.input_resize_factor)
|
||||
|
||||
# Mantenemos esto simple, el padding real se hace en la inferencia
|
||||
new_width = new_width if new_width % 2 == 0 else new_width + 1
|
||||
new_height = new_height if new_height % 2 == 0 else new_height + 1
|
||||
|
||||
@@ -999,7 +1009,6 @@ class AI_interpolation:
|
||||
return image
|
||||
|
||||
def resize_with_output_factor(self, image: numpy_ndarray) -> numpy_ndarray:
|
||||
|
||||
old_height, old_width = self.get_image_resolution(image)
|
||||
|
||||
new_width = int(old_width * self.output_resize_factor)
|
||||
@@ -1015,7 +1024,42 @@ class AI_interpolation:
|
||||
else:
|
||||
return image
|
||||
|
||||
# AI CLASS FUNCTIONS
|
||||
# -------------------------------------------------------------------------
|
||||
# PADDING & CROPPING (CRITICAL FIX FOR RIFE STRIPES)
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def pad_image_to_divisor(self, image: numpy_ndarray) -> tuple[numpy_ndarray, int, int]:
|
||||
"""
|
||||
Añade bordes negros a la imagen para que sus dimensiones sean múltiplos de self.divisor (32).
|
||||
Retorna la imagen con padding y las dimensiones del padding añadido.
|
||||
"""
|
||||
h, w = image.shape[:2]
|
||||
|
||||
# Calcular cuánto falta para llegar al siguiente múltiplo de 32
|
||||
pad_h = (self.divisor - (h % self.divisor)) % self.divisor
|
||||
pad_w = (self.divisor - (w % self.divisor)) % self.divisor
|
||||
|
||||
if pad_h == 0 and pad_w == 0:
|
||||
return image, 0, 0
|
||||
|
||||
# Aplicar padding (top, bottom, left, right) -> Solo rellenamos abajo y derecha
|
||||
# Usamos cv2.BORDER_REFLECT o BORDER_REPLICATE para reducir artefactos en bordes
|
||||
image_padded = cv2.copyMakeBorder(
|
||||
image, 0, pad_h, 0, pad_w, cv2.BORDER_REFLECT)
|
||||
|
||||
return image_padded, pad_h, pad_w
|
||||
|
||||
def crop_padding(self, image: numpy_ndarray, pad_h: int, pad_w: int) -> numpy_ndarray:
|
||||
"""Recorta la imagen para eliminar el padding añadido previamente."""
|
||||
if pad_h == 0 and pad_w == 0:
|
||||
return image
|
||||
|
||||
h, w = image.shape[:2]
|
||||
return image[:h-pad_h, :w-pad_w]
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# AI CORE FUNCTIONS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def concatenate_images(self, image1: numpy_ndarray, image2: numpy_ndarray) -> numpy_ndarray:
|
||||
# Optimización: Normalizar in-place para reducir uso de memoria
|
||||
@@ -1048,14 +1092,34 @@ class AI_interpolation:
|
||||
case _: return (onnx_output * 255).astype(uint8)
|
||||
|
||||
def AI_interpolation(self, image1: numpy_ndarray, image2: numpy_ndarray) -> numpy_ndarray:
|
||||
image = self.concatenate_images(image1, image2).astype(float32)
|
||||
"""
|
||||
Ejecuta la interpolación asegurando dimensiones correctas.
|
||||
"""
|
||||
# 1. Aplicar Padding a ambas imágenes (Critical Fix)
|
||||
img1_padded, pad_h, pad_w = self.pad_image_to_divisor(image1)
|
||||
# Asumimos que img2 tiene el mismo tamaño que img1
|
||||
img2_padded, _, _ = self.pad_image_to_divisor(image2)
|
||||
|
||||
# 2. Preprocesamiento estándar
|
||||
image = self.concatenate_images(
|
||||
img1_padded, img2_padded).astype(float32)
|
||||
image = self.preprocess_image(image)
|
||||
|
||||
# 3. Inferencia
|
||||
onnx_output = self.onnxruntime_inference(image)
|
||||
|
||||
# 4. Postprocesamiento
|
||||
onnx_output = self.postprocess_output(onnx_output)
|
||||
output_image = self.de_normalize_image(onnx_output, 255)
|
||||
output_image_padded = self.de_normalize_image(onnx_output, 255)
|
||||
|
||||
# 5. Eliminar Padding (Critical Fix)
|
||||
output_image = self.crop_padding(output_image_padded, pad_h, pad_w)
|
||||
|
||||
return output_image
|
||||
|
||||
# EXTERNAL FUNCTION
|
||||
# -------------------------------------------------------------------------
|
||||
# ORCHESTRATION
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def AI_orchestration(self, image1: numpy_ndarray, image2: numpy_ndarray) -> List[numpy_ndarray]:
|
||||
"""Generate interpolated frames between two input images."""
|
||||
@@ -1723,230 +1787,6 @@ class MessageBox(CTkToplevel):
|
||||
self.placeInfoMessageOkButton()
|
||||
|
||||
|
||||
class FileWidget(CTkScrollableFrame):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
master,
|
||||
selected_file_list,
|
||||
upscale_factor=1,
|
||||
input_resize_factor=0,
|
||||
output_resize_factor=0,
|
||||
**kwargs
|
||||
) -> None:
|
||||
|
||||
super().__init__(master, **kwargs)
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
|
||||
self.file_list = selected_file_list
|
||||
self.upscale_factor = upscale_factor
|
||||
self.input_resize_factor = input_resize_factor
|
||||
self.output_resize_factor = output_resize_factor
|
||||
|
||||
self.index_row = 1
|
||||
self.ui_components = []
|
||||
self._create_widgets()
|
||||
|
||||
def _destroy_(self) -> None:
|
||||
self.file_list = []
|
||||
self.destroy()
|
||||
place_loadFile_section()
|
||||
|
||||
def _create_widgets(self) -> None:
|
||||
self.add_clean_button()
|
||||
for file_path in self.file_list:
|
||||
file_name_label, file_info_label = self.add_file_information(
|
||||
file_path)
|
||||
self.ui_components.append(file_name_label)
|
||||
self.ui_components.append(file_info_label)
|
||||
|
||||
def add_file_information(self, file_path) -> tuple:
|
||||
infos, icon = self.extract_file_info(file_path)
|
||||
|
||||
# File name
|
||||
file_name_label = CTkLabel(
|
||||
self,
|
||||
text=os_path_basename(file_path),
|
||||
font=bold14,
|
||||
text_color=accent_color, # Usar color amarillo para nombres de archivo
|
||||
compound="left",
|
||||
anchor="w",
|
||||
padx=10,
|
||||
pady=5,
|
||||
justify="left",
|
||||
)
|
||||
file_name_label.grid(
|
||||
row=self.index_row,
|
||||
column=0,
|
||||
pady=(0, 2),
|
||||
padx=(3, 3),
|
||||
sticky="w"
|
||||
)
|
||||
|
||||
# File infos and icon
|
||||
file_info_label = CTkLabel(
|
||||
self,
|
||||
text=infos,
|
||||
image=icon,
|
||||
font=bold12,
|
||||
text_color=secondary_text_color, # Usar color de texto secundario para info
|
||||
compound="left",
|
||||
anchor="w",
|
||||
padx=10,
|
||||
pady=5,
|
||||
justify="left",
|
||||
)
|
||||
file_info_label.grid(
|
||||
row=self.index_row + 1,
|
||||
column=0,
|
||||
pady=(0, 15),
|
||||
padx=(3, 3),
|
||||
sticky="w"
|
||||
)
|
||||
|
||||
self.index_row += 2
|
||||
|
||||
return file_name_label, file_info_label
|
||||
|
||||
def add_clean_button(self) -> None:
|
||||
|
||||
button = CTkButton(
|
||||
master=self,
|
||||
command=self._destroy_,
|
||||
text="CLEAN",
|
||||
image=clear_icon,
|
||||
width=90,
|
||||
height=28,
|
||||
font=bold11,
|
||||
border_width=1,
|
||||
corner_radius=1,
|
||||
fg_color=widget_background_color,
|
||||
text_color=text_color,
|
||||
border_color=accent_color,
|
||||
hover_color=button_hover_color
|
||||
)
|
||||
|
||||
button.grid(row=0, column=2, pady=(7, 7), padx=(0, 7))
|
||||
|
||||
@cache
|
||||
def extract_file_icon(self, file_path) -> CTkImage:
|
||||
max_size = 60
|
||||
|
||||
if check_if_file_is_video(file_path):
|
||||
video_cap = opencv_VideoCapture(file_path)
|
||||
_, frame = video_cap.read()
|
||||
if frame is not None:
|
||||
source_icon = opencv_cvtColor(frame, COLOR_BGR2RGB)
|
||||
else:
|
||||
# Fallback para videos problemáticos
|
||||
source_icon = numpy_zeros((60, 60, 3), dtype=uint8)
|
||||
video_cap.release()
|
||||
else:
|
||||
source_icon = opencv_cvtColor(image_read(file_path), COLOR_BGR2RGB)
|
||||
|
||||
# Optimización: Usar memoria contigua para mejor rendimiento
|
||||
source_icon = numpy_ascontiguousarray(source_icon)
|
||||
|
||||
ratio = min(
|
||||
max_size / source_icon.shape[0], max_size / source_icon.shape[1])
|
||||
new_width = int(source_icon.shape[1] * ratio)
|
||||
new_height = int(source_icon.shape[0] * ratio)
|
||||
source_icon = opencv_resize(
|
||||
source_icon, (new_width, new_height), interpolation=INTER_AREA)
|
||||
|
||||
# Convertir a PIL y luego a CTkImage sin usar mode=
|
||||
pil_img = pillow_image_fromarray(source_icon)
|
||||
pil_img = pil_img.convert("RGB") # conversión explícita
|
||||
ctk_icon = CTkImage(pil_img, size=(new_width, new_height))
|
||||
|
||||
return ctk_icon
|
||||
|
||||
def extract_file_info(self, file_path) -> tuple:
|
||||
|
||||
if check_if_file_is_video(file_path):
|
||||
cap = opencv_VideoCapture(file_path)
|
||||
width = round(cap.get(CAP_PROP_FRAME_WIDTH))
|
||||
height = round(cap.get(CAP_PROP_FRAME_HEIGHT))
|
||||
num_frames = int(cap.get(CAP_PROP_FRAME_COUNT))
|
||||
frame_rate = cap.get(CAP_PROP_FPS)
|
||||
duration = num_frames/frame_rate
|
||||
minutes = int(duration/60)
|
||||
seconds = duration % 60
|
||||
cap.release()
|
||||
|
||||
file_icon = self.extract_file_icon(file_path)
|
||||
file_infos = f"{minutes}m:{round(seconds)}s • {num_frames}frames • {width}x{height} \n"
|
||||
|
||||
if self.input_resize_factor != 0 and self.output_resize_factor != 0 and self.upscale_factor != 0:
|
||||
input_resized_height = int(
|
||||
height * (self.input_resize_factor/100))
|
||||
input_resized_width = int(
|
||||
width * (self.input_resize_factor/100))
|
||||
|
||||
upscaled_height = int(
|
||||
input_resized_height * self.upscale_factor)
|
||||
upscaled_width = int(input_resized_width * self.upscale_factor)
|
||||
|
||||
output_resized_height = int(
|
||||
upscaled_height * (self.output_resize_factor/100))
|
||||
output_resized_width = int(
|
||||
upscaled_width * (self.output_resize_factor/100))
|
||||
|
||||
file_infos += (
|
||||
f"AI input ({self.input_resize_factor}%) ➜ {input_resized_width}x{input_resized_height} \n"
|
||||
f"AI output (x{self.upscale_factor}) ➜ {upscaled_width}x{upscaled_height} \n"
|
||||
f"Video output ({self.output_resize_factor}%) ➜ {output_resized_width}x{output_resized_height}"
|
||||
)
|
||||
|
||||
else:
|
||||
height, width = get_image_resolution(image_read(file_path))
|
||||
file_icon = self.extract_file_icon(file_path)
|
||||
|
||||
file_infos = f"{width}x{height}\n"
|
||||
|
||||
if self.input_resize_factor != 0 and self.output_resize_factor != 0 and self.upscale_factor != 0:
|
||||
input_resized_height = int(
|
||||
height * (self.input_resize_factor/100))
|
||||
input_resized_width = int(
|
||||
width * (self.input_resize_factor/100))
|
||||
|
||||
upscaled_height = int(
|
||||
input_resized_height * self.upscale_factor)
|
||||
upscaled_width = int(input_resized_width * self.upscale_factor)
|
||||
|
||||
output_resized_height = int(
|
||||
upscaled_height * (self.output_resize_factor/100))
|
||||
output_resized_width = int(
|
||||
upscaled_width * (self.output_resize_factor/100))
|
||||
|
||||
file_infos += (
|
||||
f"AI input ({self.input_resize_factor}%) ➜ {input_resized_width}x{input_resized_height} \n"
|
||||
f"AI output (x{self.upscale_factor}) ➜ {upscaled_width}x{upscaled_height} \n"
|
||||
f"Image output ({self.output_resize_factor}%) ➜ {output_resized_width}x{output_resized_height}"
|
||||
)
|
||||
|
||||
return file_infos, file_icon
|
||||
|
||||
# EXTERNAL FUNCTIONS
|
||||
|
||||
def clean_file_list(self) -> None:
|
||||
self.index_row = 1
|
||||
for ui_component in self.ui_components:
|
||||
ui_component.grid_forget()
|
||||
|
||||
def get_selected_file_list(self) -> list:
|
||||
return self.file_list
|
||||
|
||||
def set_upscale_factor(self, upscale_factor) -> None:
|
||||
self.upscale_factor = upscale_factor
|
||||
|
||||
def set_input_resize_factor(self, input_resize_factor) -> None:
|
||||
self.input_resize_factor = input_resize_factor
|
||||
|
||||
def set_output_resize_factor(self, output_resize_factor) -> None:
|
||||
self.output_resize_factor = output_resize_factor
|
||||
|
||||
|
||||
def get_values_for_file_widget() -> tuple:
|
||||
# Upscale factor
|
||||
upscale_factor = get_upscale_factor()
|
||||
@@ -1969,18 +1809,21 @@ def get_values_for_file_widget() -> tuple:
|
||||
|
||||
|
||||
def update_file_widget(a, b, c) -> None:
|
||||
try:
|
||||
selected_file_list = file_widget.get_selected_file_list()
|
||||
except Exception:
|
||||
# Si el widget no existe o no tiene archivos, no hacemos nada crítico,
|
||||
# pero actualizamos los valores internos para cuando lleguen archivos.
|
||||
if not file_widget:
|
||||
return
|
||||
|
||||
upscale_factor, input_resize_factor, output_resize_factor = get_values_for_file_widget()
|
||||
|
||||
file_widget.clean_file_list()
|
||||
# Pasar valores al manager
|
||||
file_widget.set_upscale_factor(upscale_factor)
|
||||
file_widget.set_input_resize_factor(input_resize_factor)
|
||||
file_widget.set_output_resize_factor(output_resize_factor)
|
||||
file_widget._create_widgets()
|
||||
|
||||
# Regenerar textos de info en la lista si es necesario
|
||||
if file_widget.queue_items:
|
||||
file_widget.regenerate_all_info()
|
||||
|
||||
|
||||
def create_option_background():
|
||||
@@ -3934,6 +3777,11 @@ def upscale_button_command() -> None:
|
||||
global process_upscale_orchestrator
|
||||
global stop_thread_flag
|
||||
|
||||
# --- AGREGAR CONFIRMACIÓN ---
|
||||
if not messagebox.askyesno("Start Processing", "Do you want to start the AI processing?"):
|
||||
return
|
||||
# ----------------------------
|
||||
|
||||
# Fix 2.2: Clear stop_thread_flag at the beginning of each execution
|
||||
stop_thread_flag.clear()
|
||||
|
||||
@@ -4112,32 +3960,39 @@ def fluidframes_video_interpolate(
|
||||
write_process_status(
|
||||
process_status_q, f"{file_number}. Extracting video frames")
|
||||
|
||||
# --- CAMBIO CRÍTICO: Forzar .png para extracción temporal ---
|
||||
# Forzar .png para extracción temporal
|
||||
temp_extraction_ext = ".png"
|
||||
|
||||
extracted_frames_paths = extract_video_frames(
|
||||
process_status_q, file_number, target_directory, AI_instance, video_path, cpu_number, temp_extraction_ext)
|
||||
|
||||
# Step 3. Prepare output/gen frame names (asegurar que usan png)
|
||||
# Step 3. Prepare output/gen frame names
|
||||
total_frames_paths = prepare_output_video_frame_filenames(
|
||||
extracted_frames_paths, selected_AI_model, frame_gen_factor, temp_extraction_ext)
|
||||
|
||||
# Step 4. Interpolated frames generation
|
||||
write_process_status(
|
||||
process_status_q, f"{file_number}. Video frame generation")
|
||||
process_status_q, f"{file_number}. Video frame generation initializing...")
|
||||
|
||||
# --- LOGICA DE PROGRESO AÑADIDA ---
|
||||
global global_processing_times_list
|
||||
global_processing_times_list = []
|
||||
|
||||
for frame_index in range(len(extracted_frames_paths)-1):
|
||||
total_pairs = len(extracted_frames_paths) - 1
|
||||
|
||||
for frame_index in range(total_pairs):
|
||||
frame_1_path = extracted_frames_paths[frame_index]
|
||||
frame_2_path = extracted_frames_paths[frame_index+1]
|
||||
|
||||
# Medir tiempo de carga e inferencia
|
||||
start_timer = timer()
|
||||
|
||||
frame_1 = image_read(frame_1_path)
|
||||
frame_2 = image_read(frame_2_path)
|
||||
|
||||
start_timer = timer()
|
||||
generated_frames = AI_instance.AI_orchestration(frame_1, frame_2)
|
||||
|
||||
# Save generated frames (usando la misma extensión temporal .png)
|
||||
# Save generated frames
|
||||
generated_frames_paths = prepare_generated_frames_paths(
|
||||
os_path_splitext(frame_1_path)[0], selected_AI_model, temp_extraction_ext, frame_gen_factor)
|
||||
|
||||
@@ -4145,13 +4000,30 @@ def fluidframes_video_interpolate(
|
||||
image_write(generated_frames_paths[i], gen_frame)
|
||||
|
||||
end_timer = timer()
|
||||
global_processing_times_list.append(end_timer - start_timer)
|
||||
|
||||
# --- CÁLCULO DE TIEMPO Y ACTUALIZACIÓN DE ESTADO ---
|
||||
step_time = end_timer - start_timer
|
||||
global_processing_times_list.append(step_time)
|
||||
|
||||
# Limitamos el tamaño de la lista de tiempos para mantener el promedio reciente
|
||||
if len(global_processing_times_list) > 100:
|
||||
global_processing_times_list.pop(0)
|
||||
|
||||
# Actualizar la interfaz cada 1% o cada frame si son pocos (evita saturar la GUI)
|
||||
if total_pairs > 0 and (frame_index % max(1, int(total_pairs / 100)) == 0 or frame_index == total_pairs - 1):
|
||||
avg_time = numpy_mean(global_processing_times_list)
|
||||
remaining_frames = total_pairs - (frame_index + 1)
|
||||
time_left = calculate_time_to_complete_video(
|
||||
avg_time, remaining_frames)
|
||||
percent_complete = ((frame_index + 1) / total_pairs) * 100
|
||||
|
||||
status_msg = f"{file_number}. Interpolating frames: {percent_complete:.1f}% completed ({time_left})"
|
||||
write_process_status(process_status_q, status_msg)
|
||||
|
||||
# Step 6. Video encoding
|
||||
write_process_status(
|
||||
process_status_q, f"{file_number}. Encoding frame-generated video")
|
||||
|
||||
# --- CAMBIO CRÍTICO: Calcular multiplicador de FPS para FFmpeg ---
|
||||
fps_multiplier = 1 if slowmotion else frame_gen_factor
|
||||
|
||||
video_encoding(
|
||||
@@ -4736,6 +4608,18 @@ def user_input_checks() -> bool:
|
||||
global input_resize_factor
|
||||
global output_resize_factor
|
||||
|
||||
# Enhanced file validation
|
||||
try:
|
||||
# Esto llama al método del nuevo FileQueueManager
|
||||
selected_file_list = file_widget.get_selected_file_list()
|
||||
except Exception:
|
||||
info_message.set("Please select a file")
|
||||
return False
|
||||
|
||||
if not selected_file_list or len(selected_file_list) <= 0:
|
||||
info_message.set("Please select a file")
|
||||
return False
|
||||
|
||||
# Enhanced file validation
|
||||
try:
|
||||
selected_file_list = file_widget.get_selected_file_list()
|
||||
@@ -4853,48 +4737,37 @@ def open_files_action(files=None):
|
||||
|
||||
info_message.set("Processing files...")
|
||||
|
||||
# --- CORRECCIÓN AQUÍ ---
|
||||
if files:
|
||||
# Caso A: Viene de Drag & Drop
|
||||
# El módulo drag_drop.py YA nos envía la lista limpia (es una tupla),
|
||||
# así que solo la convertimos a lista y listo.
|
||||
# Caso A: Drag & Drop
|
||||
uploaded_files_list = list(files)
|
||||
else:
|
||||
# Caso B: Viene del Botón (files es None)
|
||||
# Abrimos el explorador de archivos manualmente
|
||||
# Caso B: Botón manual
|
||||
info_message.set("Selecting files")
|
||||
uploaded_files_list = list(filedialog.askopenfilenames())
|
||||
# -----------------------
|
||||
|
||||
uploaded_files_counter = len(uploaded_files_list)
|
||||
if not uploaded_files_list:
|
||||
return
|
||||
|
||||
# Filtrar archivos
|
||||
supported_files_list = check_supported_selected_files(uploaded_files_list)
|
||||
supported_files_counter = len(supported_files_list)
|
||||
|
||||
print("> Uploaded files: " + str(uploaded_files_counter) +
|
||||
" => Supported files: " + str(supported_files_counter))
|
||||
|
||||
if supported_files_counter > 0:
|
||||
|
||||
if supported_files_list:
|
||||
# 1. Configurar los factores actuales en el widget antes de añadir
|
||||
upscale_factor, input_resize_factor, output_resize_factor = get_values_for_file_widget()
|
||||
file_widget.set_upscale_factor(upscale_factor)
|
||||
file_widget.set_input_resize_factor(input_resize_factor)
|
||||
file_widget.set_output_resize_factor(output_resize_factor)
|
||||
|
||||
global file_widget
|
||||
file_widget = FileWidget(
|
||||
master=window,
|
||||
selected_file_list=supported_files_list,
|
||||
upscale_factor=upscale_factor,
|
||||
input_resize_factor=input_resize_factor,
|
||||
output_resize_factor=output_resize_factor,
|
||||
fg_color=background_color,
|
||||
bg_color=background_color
|
||||
)
|
||||
file_widget.place(relx=0.0, rely=0.0, relwidth=0.5, relheight=1.0)
|
||||
info_message.set("Ready to be being enchanted!")
|
||||
# 2. Añadir archivos (la carga pesada ocurre en segundo plano en el nuevo módulo)
|
||||
file_widget.add_files(supported_files_list)
|
||||
|
||||
# 3. Cambiar vista
|
||||
show_file_manager()
|
||||
|
||||
info_message.set("Ready to be enchanted!")
|
||||
print(f"> Added {len(supported_files_list)} files to queue.")
|
||||
else:
|
||||
if uploaded_files_counter > 0:
|
||||
info_message.set("Not supported files :(")
|
||||
else:
|
||||
info_message.set("No files selected")
|
||||
info_message.set("No supported files selected")
|
||||
|
||||
|
||||
def open_output_path_action():
|
||||
@@ -5035,18 +4908,41 @@ def place_dynamic_rife_interpolator():
|
||||
# END FLUIDFRAMES
|
||||
|
||||
|
||||
# Variables globales para manejar las vistas
|
||||
drop_zone_frame = None
|
||||
file_widget = None # Esta será la instancia de FileQueueManager
|
||||
|
||||
|
||||
def show_drop_zone():
|
||||
"""Oculta la lista de archivos y muestra la zona de carga."""
|
||||
if file_widget:
|
||||
file_widget.place_forget()
|
||||
if drop_zone_frame:
|
||||
drop_zone_frame.place(relx=0.0, rely=0.0, relwidth=0.5, relheight=1.0)
|
||||
info_message.set("No files selected")
|
||||
|
||||
|
||||
def show_file_manager():
|
||||
"""Oculta la zona de carga y muestra la lista de archivos."""
|
||||
if drop_zone_frame:
|
||||
drop_zone_frame.place_forget()
|
||||
if file_widget:
|
||||
file_widget.place(relx=0.0, rely=0.0, relwidth=0.5, relheight=1.0)
|
||||
|
||||
|
||||
def place_loadFile_section():
|
||||
# Crear el frame de fondo para la sección de carga
|
||||
background = CTkFrame(
|
||||
global drop_zone_frame, file_widget
|
||||
|
||||
# --- 1. Crear el Frame de la Drop Zone (Inicialmente Visible) ---
|
||||
drop_zone_frame = CTkFrame(
|
||||
master=window, fg_color=background_color, corner_radius=1)
|
||||
|
||||
# Texto informativo sobre formatos soportados
|
||||
text_drop = (" SUPPORTED FILES \n\n "
|
||||
+ "IMAGES • jpg, jpeg, png, bmp, tiff, tif, webp \n "
|
||||
+ "VIDEOS • mp4, avi, mkv, mov, wmv, flv, webm ")
|
||||
|
||||
input_file_text = CTkLabel(
|
||||
master=window,
|
||||
master=drop_zone_frame,
|
||||
text=text_drop,
|
||||
fg_color=widget_background_color,
|
||||
bg_color=background_color,
|
||||
@@ -5058,10 +4954,9 @@ def place_loadFile_section():
|
||||
corner_radius=10
|
||||
)
|
||||
|
||||
# Botón para seleccionar archivos manualmente
|
||||
input_file_button = CTkButton(
|
||||
master=window,
|
||||
command=open_files_action,
|
||||
master=drop_zone_frame,
|
||||
command=open_files_action, # Llama a la función modificada abajo
|
||||
text="Select Files or Drag & Drop",
|
||||
width=150,
|
||||
height=30,
|
||||
@@ -5074,20 +4969,27 @@ def place_loadFile_section():
|
||||
hover_color=button_hover_color
|
||||
)
|
||||
|
||||
# Colocar elementos en la interfaz
|
||||
background.place(relx=0.0, rely=0.0, relwidth=0.5, relheight=1.0)
|
||||
input_file_text.place(relx=0.25, rely=0.4, anchor="center")
|
||||
input_file_button.place(relx=0.25, rely=0.5, anchor="center")
|
||||
# Colocar elementos dentro del frame de Drop Zone
|
||||
input_file_text.place(relx=0.5, rely=0.4, anchor="center")
|
||||
input_file_button.place(relx=0.5, rely=0.5, anchor="center")
|
||||
|
||||
# --- CORRECCIÓN DRAG & DROP ---
|
||||
# Registramos 'background', 'input_file_button' y 'input_file_text'
|
||||
# para maximizar el área de detección de archivos.
|
||||
enable_drag_and_drop(
|
||||
window,
|
||||
[background, input_file_button, input_file_text],
|
||||
open_files_action
|
||||
# Mostrar Drop Zone por defecto
|
||||
drop_zone_frame.place(relx=0.0, rely=0.0, relwidth=0.5, relheight=1.0)
|
||||
|
||||
# --- 2. Instanciar FileQueueManager (Inicialmente Oculto) ---
|
||||
# Usamos show_drop_zone como callback para cuando el usuario limpie la lista
|
||||
file_widget = FileQueueManager(
|
||||
master=window,
|
||||
clear_icon=clear_icon,
|
||||
on_queue_empty_callback=show_drop_zone,
|
||||
width=300, # <-- Esto es un kwargs
|
||||
)
|
||||
|
||||
# Habilitar Drag & Drop en AMBOS componentes (Drop Zone y File Manager)
|
||||
# Esto permite arrastrar archivos incluso si ya hay una lista visible
|
||||
enable_drag_and_drop(window, [
|
||||
drop_zone_frame, input_file_button, input_file_text, file_widget], open_files_action)
|
||||
|
||||
|
||||
def place_app_name():
|
||||
background = CTkFrame(
|
||||
@@ -5684,11 +5586,18 @@ def place_upscale_button():
|
||||
# ==== MAIN APPLICATION SECTION ====
|
||||
|
||||
def on_app_close() -> None:
|
||||
# Clean up logger
|
||||
logging.shutdown()
|
||||
window.grab_release()
|
||||
window.destroy()
|
||||
# 1. Confirmación de salida
|
||||
if not messagebox.askyesno("Exit Warlock-Studio", "Are you sure you want to close the application?"):
|
||||
return
|
||||
|
||||
# 2. CAPTURAR ESTADO DE LA VENTANA (ANTES DE DESTRUIRLA)
|
||||
# Soluciona el error: application has been destroyed
|
||||
try:
|
||||
is_topmost = window.attributes("-topmost")
|
||||
except Exception:
|
||||
is_topmost = False
|
||||
|
||||
# 3. Recopilar variables globales para guardar preferencias
|
||||
global selected_AI_model
|
||||
global selected_AI_multithreading
|
||||
global selected_gpu
|
||||
@@ -5714,6 +5623,7 @@ def on_app_close() -> None:
|
||||
else:
|
||||
AI_multithreading_to_save = f"{selected_AI_multithreading} threads"
|
||||
|
||||
# 4. Construir diccionario de preferencias
|
||||
user_preference = {
|
||||
"default_AI_model": AI_model_to_save,
|
||||
"default_AI_multithreading": AI_multithreading_to_save,
|
||||
@@ -5727,12 +5637,28 @@ def on_app_close() -> None:
|
||||
"default_input_resize_factor": str(selected_input_resize_factor.get()),
|
||||
"default_output_resize_factor": str(selected_output_resize_factor.get()),
|
||||
"default_VRAM_limiter": str(selected_VRAM_limiter.get()),
|
||||
# Usamos la variable capturada al inicio
|
||||
"keep_window_on_top": is_topmost
|
||||
}
|
||||
user_preference_json = json_dumps(user_preference)
|
||||
with open(USER_PREFERENCE_PATH, "w") as preference_file:
|
||||
preference_file.write(user_preference_json)
|
||||
|
||||
# 5. Guardar JSON en disco
|
||||
try:
|
||||
user_preference_json = json_dumps(user_preference)
|
||||
with open(USER_PREFERENCE_PATH, "w") as preference_file:
|
||||
preference_file.write(user_preference_json)
|
||||
except Exception as e:
|
||||
print(f"Error saving preferences: {e}")
|
||||
|
||||
# 6. Limpieza de procesos y logs
|
||||
stop_upscale_process()
|
||||
logging.shutdown()
|
||||
|
||||
# 7. DESTRUIR LA VENTANA (AL FINAL)
|
||||
try:
|
||||
window.grab_release()
|
||||
window.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
class App():
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ block_cipher = None
|
||||
|
||||
a = Analysis(
|
||||
# 1. Aquí agregamos los dos archivos nuevos a la lista de scripts
|
||||
['Warlock-Studio.py', 'drag_drop.py', 'console.py', 'warlock_preferences.py'],
|
||||
['Warlock-Studio.py', 'drag_drop.py', 'console.py', 'warlock_preferences.py', 'file_queue_manager.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import json
|
||||
import sys
|
||||
import threading
|
||||
import tkinter as tk
|
||||
|
||||
@@ -0,0 +1,401 @@
|
||||
import logging
|
||||
import os
|
||||
import queue
|
||||
import threading
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
import customtkinter as ctk
|
||||
import cv2
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
|
||||
# --- CONFIGURACIÓN Y ESTILOS ---
|
||||
class Theme:
|
||||
BG_COLOR = "#101010" # Fondo general un poco más oscuro
|
||||
ITEM_BG = "#3A3A3A" # Fondo de cada tarjeta
|
||||
TEXT_MAIN = "#FFFFFF"
|
||||
TEXT_SEC = "#FDEF2F"
|
||||
ACCENT = "#F7F7F7" # Dorado original
|
||||
ERROR = "#CF6679" # Rojo suave para errores
|
||||
BTN_HOVER_DANGER = "#B00020"
|
||||
BTN_HOVER_NORMAL = "#4A4A4A"
|
||||
BORDER_COLOR = "#555555"
|
||||
|
||||
FONT_MAIN = ("Roboto Medium", 13)
|
||||
FONT_SUB = ("Roboto", 11)
|
||||
FONT_MONO = ("Consolas", 10)
|
||||
|
||||
|
||||
# Configuración de logging para debug
|
||||
logging.basicConfig(level=logging.ERROR,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
|
||||
|
||||
class QueueItem:
|
||||
"""Clase de datos para manejar el estado de cada archivo individualmente."""
|
||||
|
||||
def __init__(self, path: str):
|
||||
self.path = path
|
||||
self.name = os.path.basename(path)
|
||||
self.info_text = "Cargando info..."
|
||||
self.thumbnail: Optional[ctk.CTkImage] = None
|
||||
self.is_loaded = False
|
||||
self.has_error = False
|
||||
self.id = id(self) # Identificador único para referenciar widgets
|
||||
|
||||
|
||||
class FileQueueManager(ctk.CTkScrollableFrame):
|
||||
def __init__(self, master, clear_icon=None, on_queue_empty_callback=None, **kwargs):
|
||||
super().__init__(master, fg_color=Theme.BG_COLOR, **kwargs)
|
||||
|
||||
self.on_queue_empty_callback = on_queue_empty_callback
|
||||
self.clear_icon = clear_icon
|
||||
|
||||
# Estado interno
|
||||
self.queue_items: List[QueueItem] = []
|
||||
# Mapa para acceder a widgets por ID de item
|
||||
self._widget_refs: Dict[int, dict] = {}
|
||||
|
||||
# Factores de redimensionado
|
||||
self.upscale_factor = 1
|
||||
self.input_resize_factor = 0
|
||||
self.output_resize_factor = 0
|
||||
|
||||
# Sistema de hilos para no congelar la GUI
|
||||
self.executor = ThreadPoolExecutor(max_workers=2)
|
||||
self.msg_queue = queue.Queue()
|
||||
|
||||
# Grid layout básico
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
|
||||
# Iniciar loop de verificación de mensajes (para actualizaciones desde hilos)
|
||||
self._check_queue()
|
||||
|
||||
def _check_queue(self):
|
||||
"""Revisa la cola de mensajes para actualizar la UI desde el hilo principal."""
|
||||
try:
|
||||
while True:
|
||||
task_type, item_id, data = self.msg_queue.get_nowait()
|
||||
if task_type == "UPDATE_ITEM":
|
||||
self._update_item_ui(item_id, data)
|
||||
except queue.Empty:
|
||||
pass
|
||||
finally:
|
||||
self.after(100, self._check_queue)
|
||||
|
||||
def add_files(self, file_paths: List[str]):
|
||||
"""Agrega archivos y lanza la carga en segundo plano."""
|
||||
added_any = False
|
||||
existing_paths = {item.path for item in self.queue_items}
|
||||
|
||||
for path in file_paths:
|
||||
norm_path = os.path.normpath(path)
|
||||
if norm_path not in existing_paths and os.path.exists(path):
|
||||
new_item = QueueItem(norm_path)
|
||||
self.queue_items.append(new_item)
|
||||
added_any = True
|
||||
|
||||
# Renderizar placeholder inmediatamente
|
||||
self._render_item(new_item, index=len(self.queue_items)-1)
|
||||
|
||||
# Lanzar tarea pesada en background
|
||||
self.executor.submit(self._worker_load_info, new_item)
|
||||
|
||||
if added_any:
|
||||
self._update_layout_indices()
|
||||
|
||||
def _worker_load_info(self, item: QueueItem):
|
||||
"""Método que corre en otro hilo (Thread) para procesar OpenCV."""
|
||||
try:
|
||||
info_text, pil_img = self._extract_file_data(item.path)
|
||||
|
||||
# Crear CTkImage debe hacerse preferiblemente al volver al main,
|
||||
# pero PIL Image es seguro pasarlo.
|
||||
item.info_text = info_text
|
||||
item.is_loaded = True
|
||||
|
||||
# Enviamos resultados al hilo principal
|
||||
self.msg_queue.put(
|
||||
("UPDATE_ITEM", item.id, {"info": info_text, "img": pil_img}))
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Error procesando {item.path}: {e}")
|
||||
item.has_error = True
|
||||
item.info_text = "Error al leer archivo"
|
||||
self.msg_queue.put(("UPDATE_ITEM", item.id, {"error": True}))
|
||||
|
||||
def _update_item_ui(self, item_id, data):
|
||||
"""Actualiza un widget específico una vez que el hilo terminó."""
|
||||
widgets = self._widget_refs.get(item_id)
|
||||
if not widgets:
|
||||
return
|
||||
|
||||
if "error" in data:
|
||||
widgets['lbl_info'].configure(
|
||||
text="⚠️ Archivo corrupto o ilegible", text_color=Theme.ERROR)
|
||||
return
|
||||
|
||||
# Actualizar texto
|
||||
widgets['lbl_info'].configure(text=data["info"])
|
||||
|
||||
# Actualizar imagen si existe
|
||||
if data["img"]:
|
||||
ctk_img = ctk.CTkImage(data["img"], size=data["img"].size)
|
||||
# Guardamos referencia en el objeto item para que no se pierda
|
||||
item = next((x for x in self.queue_items if x.id == item_id), None)
|
||||
if item:
|
||||
item.thumbnail = ctk_img
|
||||
widgets['lbl_icon'].configure(
|
||||
image=ctk_img, text="") # Quitar texto placeholder
|
||||
|
||||
def _render_item(self, item: QueueItem, index: int):
|
||||
"""Dibuja una tarjeta para el archivo."""
|
||||
row_idx = index + 1 # +1 para dejar espacio al botón Clean arriba si fuera necesario
|
||||
|
||||
# Frame contenedor (Tarjeta)
|
||||
card = ctk.CTkFrame(self, fg_color=Theme.ITEM_BG, corner_radius=8,
|
||||
border_width=1, border_color=Theme.BORDER_COLOR)
|
||||
card.grid(row=row_idx, column=0, sticky="ew", padx=10, pady=5)
|
||||
card.grid_columnconfigure(1, weight=1)
|
||||
|
||||
# 1. Icono / Thumbnail
|
||||
lbl_icon = ctk.CTkLabel(card, text="⏳", width=64,
|
||||
height=64, fg_color="#222", corner_radius=6)
|
||||
lbl_icon.grid(row=0, column=0, rowspan=2, padx=8, pady=8)
|
||||
|
||||
# Si ya teníamos la imagen (ej: reordenando lista), la ponemos directo
|
||||
if item.thumbnail:
|
||||
lbl_icon.configure(image=item.thumbnail, text="")
|
||||
|
||||
# 2. Información
|
||||
lbl_name = ctk.CTkLabel(
|
||||
card, text=item.name, font=Theme.FONT_MAIN, text_color=Theme.ACCENT, anchor="w")
|
||||
lbl_name.grid(row=0, column=1, sticky="w", padx=5, pady=(8, 0))
|
||||
|
||||
lbl_info = ctk.CTkLabel(card, text=item.info_text, font=Theme.FONT_MONO,
|
||||
text_color=Theme.TEXT_SEC, justify="left", anchor="w")
|
||||
lbl_info.grid(row=1, column=1, sticky="w", padx=5, pady=(0, 8))
|
||||
|
||||
# 3. Controles (Frame derecho)
|
||||
ctrl_frame = ctk.CTkFrame(card, fg_color="transparent")
|
||||
ctrl_frame.grid(row=0, column=2, rowspan=2, padx=8, sticky="e")
|
||||
|
||||
# Botón Subir
|
||||
btn_up = ctk.CTkButton(ctrl_frame, text="▲", width=28, height=28,
|
||||
fg_color="transparent", border_width=1, border_color=Theme.TEXT_SEC,
|
||||
hover_color=Theme.BTN_HOVER_NORMAL, text_color=Theme.TEXT_MAIN,
|
||||
font=("Arial", 12),
|
||||
command=lambda: self.move_up(item))
|
||||
btn_up.pack(side="left", padx=2)
|
||||
|
||||
# Botón Eliminar
|
||||
btn_del = ctk.CTkButton(ctrl_frame, text="✕", width=28, height=28,
|
||||
fg_color="transparent", border_width=1, border_color=Theme.ERROR,
|
||||
text_color=Theme.ERROR, hover_color=Theme.BTN_HOVER_DANGER,
|
||||
font=("Arial", 12, "bold"),
|
||||
command=lambda: self.remove_item(item))
|
||||
btn_del.pack(side="left", padx=2)
|
||||
|
||||
# Guardar referencias para actualizaciones asíncronas
|
||||
self._widget_refs[item.id] = {
|
||||
"card": card,
|
||||
"lbl_info": lbl_info,
|
||||
"lbl_icon": lbl_icon,
|
||||
"btn_up": btn_up # Guardamos por si queremos deshabilitar el primero
|
||||
}
|
||||
|
||||
# Renderizar encabezado si es el primer elemento
|
||||
if index == 0:
|
||||
self._render_header()
|
||||
|
||||
def _render_header(self):
|
||||
"""Dibuja el botón de limpiar todo si hay elementos."""
|
||||
# Limpiar header anterior si existe
|
||||
for w in self.grid_slaves(row=0):
|
||||
w.destroy()
|
||||
|
||||
if self.queue_items:
|
||||
header_frame = ctk.CTkFrame(self, fg_color="transparent")
|
||||
header_frame.grid(row=0, column=0, sticky="ew",
|
||||
padx=10, pady=(5, 0))
|
||||
|
||||
ctk.CTkLabel(header_frame, text=f"Queue: {len(self.queue_items)} Files",
|
||||
font=Theme.FONT_SUB, text_color=Theme.TEXT_SEC).pack(side="left")
|
||||
|
||||
ctk.CTkButton(header_frame, text="CLEAN ALL", image=self.clear_icon,
|
||||
font=Theme.FONT_SUB, height=24, width=100,
|
||||
fg_color="transparent", border_width=1, border_color=Theme.ACCENT, text_color=Theme.ACCENT,
|
||||
hover_color=Theme.BTN_HOVER_NORMAL,
|
||||
command=self.clean_file_list).pack(side="right")
|
||||
|
||||
def _update_layout_indices(self):
|
||||
"""Re-dibuja toda la lista. Útil para reordenar o borrar."""
|
||||
# Nota: En una app muy grande esto sería ineficiente, pero para <100 archivos está bien
|
||||
# destruir y recrear widgets garantiza orden visual correcto.
|
||||
|
||||
# Limpiar UI actual
|
||||
for widget in self.winfo_children():
|
||||
widget.destroy()
|
||||
|
||||
self._widget_refs.clear()
|
||||
|
||||
# Redibujar
|
||||
if self.queue_items:
|
||||
self._render_header()
|
||||
for i, item in enumerate(self.queue_items):
|
||||
self._render_item(item, i)
|
||||
else:
|
||||
# Lista vacía
|
||||
if self.on_queue_empty_callback:
|
||||
self.on_queue_empty_callback()
|
||||
|
||||
# --- LÓGICA DE DATOS ---
|
||||
|
||||
def move_up(self, item: QueueItem):
|
||||
try:
|
||||
idx = self.queue_items.index(item)
|
||||
if idx > 0:
|
||||
self.queue_items[idx], self.queue_items[idx -
|
||||
1] = self.queue_items[idx - 1], self.queue_items[idx]
|
||||
self._update_layout_indices()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def remove_item(self, item: QueueItem):
|
||||
if item in self.queue_items:
|
||||
self.queue_items.remove(item)
|
||||
# Eliminar referencias para liberar memoria
|
||||
if item.id in self._widget_refs:
|
||||
del self._widget_refs[item.id]
|
||||
self._update_layout_indices()
|
||||
|
||||
def clean_file_list(self):
|
||||
self.queue_items.clear()
|
||||
self._widget_refs.clear()
|
||||
self._update_layout_indices()
|
||||
|
||||
def get_selected_file_list(self) -> List[str]:
|
||||
return [item.path for item in self.queue_items if not item.has_error]
|
||||
|
||||
def regenerate_all_info(self):
|
||||
"""Recalcula el texto de redimensionado sin recargar imágenes."""
|
||||
for item in self.queue_items:
|
||||
if not item.has_error and item.is_loaded:
|
||||
# Recalculamos solo el texto basado en lo que ya sabemos (o recargamos dims rápidas)
|
||||
# Para optimizar, asumimos que podemos volver a lanzar el worker o
|
||||
# simplemente recalcular si guardáramos width/height en el objeto.
|
||||
# Por simplicidad y robustez, relanzamos el worker ligero.
|
||||
self.executor.submit(self._worker_load_info, item)
|
||||
|
||||
# --- SETTERS ---
|
||||
def set_upscale_factor(self, f):
|
||||
self.upscale_factor = f
|
||||
|
||||
def set_input_resize_factor(self, f):
|
||||
self.input_resize_factor = f
|
||||
|
||||
def set_output_resize_factor(self, f):
|
||||
self.output_resize_factor = f
|
||||
|
||||
# --- UTILIDADES ESTÁTICAS (Lógica pura) ---
|
||||
|
||||
def _extract_file_data(self, file_path) -> Tuple[str, Optional[Image.Image]]:
|
||||
"""Extrae info y genera thumbnail PIL (Seguro para Threads)."""
|
||||
info_str = "Info no disponible"
|
||||
pil_image = None
|
||||
|
||||
try:
|
||||
exts_video = ['.mp4', '.avi', '.mkv',
|
||||
'.mov', '.wmv', '.flv', '.webm']
|
||||
is_video = any(file_path.lower().endswith(ext)
|
||||
for ext in exts_video)
|
||||
|
||||
width, height = 0, 0
|
||||
|
||||
if is_video:
|
||||
cap = cv2.VideoCapture(file_path)
|
||||
if cap.isOpened():
|
||||
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
||||
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
||||
frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
||||
fps = cap.get(cv2.CAP_PROP_FPS)
|
||||
|
||||
# Leer frame central para thumbnail
|
||||
try:
|
||||
if frames > 100:
|
||||
cap.set(cv2.CAP_PROP_POS_FRAMES, 50)
|
||||
ret, frame = cap.read()
|
||||
if ret:
|
||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
pil_image = self._process_thumbnail(frame)
|
||||
except:
|
||||
pass # Fallo silencioso solo en thumbnail
|
||||
|
||||
dur = frames/fps if fps > 0 else 0
|
||||
m, s = divmod(int(dur), 60)
|
||||
info_str = f"Video: {m}m:{s:02d}s • {frames} frames • {width}x{height}\n"
|
||||
cap.release()
|
||||
else:
|
||||
# Imagen
|
||||
# cv2.imdecode es mejor para rutas con caracteres especiales en Windows
|
||||
img_array = np.fromfile(file_path, np.uint8)
|
||||
img = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
|
||||
|
||||
if img is not None:
|
||||
height, width = img.shape[:2]
|
||||
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
||||
pil_image = self._process_thumbnail(img)
|
||||
info_str = f"Image: {width}x{height}\n"
|
||||
|
||||
# Añadir datos de redimensionado calculado
|
||||
if width > 0 and height > 0:
|
||||
info_str += self._calculate_resize_text(width, height)
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Error interno extract: {e}")
|
||||
raise e
|
||||
|
||||
return info_str, pil_image
|
||||
|
||||
def _process_thumbnail(self, img_array) -> Image.Image:
|
||||
"""Redimensiona y recorta imagen para thumbnail."""
|
||||
h, w = img_array.shape[:2]
|
||||
target_size = 64
|
||||
|
||||
# Mantener aspect ratio dentro de 64x64
|
||||
scale = target_size / max(h, w)
|
||||
new_w, new_h = int(w * scale), int(h * scale)
|
||||
|
||||
resized = cv2.resize(img_array, (new_w, new_h),
|
||||
interpolation=cv2.INTER_AREA)
|
||||
return Image.fromarray(resized)
|
||||
|
||||
def _calculate_resize_text(self, w, h) -> str:
|
||||
"""Lógica pura de cálculo de dimensiones."""
|
||||
if self.upscale_factor <= 0:
|
||||
return ""
|
||||
|
||||
iw = int(w * (self.input_resize_factor/100)
|
||||
) if self.input_resize_factor else w
|
||||
ih = int(h * (self.input_resize_factor/100)
|
||||
) if self.input_resize_factor else h
|
||||
|
||||
uw, uh = int(iw * self.upscale_factor), int(ih * self.upscale_factor)
|
||||
|
||||
ow = int(uw * (self.output_resize_factor/100)
|
||||
) if self.output_resize_factor else uw
|
||||
oh = int(uh * (self.output_resize_factor/100)
|
||||
) if self.output_resize_factor else uh
|
||||
|
||||
txt = ""
|
||||
if self.input_resize_factor:
|
||||
txt += f"Input AI ({int(self.input_resize_factor)}%) ➜ {iw}x{ih}\n"
|
||||
|
||||
txt += f"Output AI (x{self.upscale_factor}) ➜ {uw}x{uh}"
|
||||
|
||||
if self.output_resize_factor:
|
||||
txt += f"\nFinal Output ({int(self.output_resize_factor)}%) ➜ {ow}x{oh}"
|
||||
|
||||
return txt
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 49 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 38 KiB |
+715
-625
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user