Feat: Migrate GUI to customtkinter and update README.md
This commit is contained in:
@@ -23,6 +23,10 @@ Develop a user-friendly, standalone Python tool to convert video files into form
|
||||
|
||||
### Future Considerations
|
||||
|
||||
* **Twitch Integration Strategy:**
|
||||
* **URL Support:** Extend the URL handling to explicitly support Twitch video, single clip, and clip collection URLs.
|
||||
* **Single Video/Clip Downloads:** Leverage `yt-dlp`'s existing capabilities to download single Twitch videos and clips. This should work with the current implementation.
|
||||
* **Clip Collection Downloads (Batch Processing):** For Twitch clip collection URLs, `yt-dlp` will download all clips in the collection. This will require implementing batch processing capabilities (which is already a future consideration) to handle multiple downloaded files. The application will need to iterate through each downloaded clip and convert it individually.
|
||||
* **Batch Processing:** Allow conversion of multiple files or URLs in a single run.
|
||||
* **Configuration File:** Implement a configuration file (e.g., YAML, JSON) for persistent settings.
|
||||
* **Progress Bar:** Integrate a progress bar for both download and conversion processes.
|
||||
@@ -33,4 +37,9 @@ Develop a user-friendly, standalone Python tool to convert video files into form
|
||||
### Known Issues / Limitations
|
||||
|
||||
* DaVinci Resolve Free on Linux has limitations with certain audio codecs (e.g., AAC) and 4K output/encoding (requires Studio version).
|
||||
* `ffmpeg-full` AUR package is required for `dnxhd` support on Arch-based systems.
|
||||
* `ffmpeg-full` AUR package is required for `dnxhd` support on Arch-based systems.
|
||||
|
||||
### Large scale implementations
|
||||
Since one of the limitations of this project is the requirement of ffmpeg-full for encoding videos for Davinci Resolve use we should investigate the proposition of implementing the necessary ffmpeg-full into the project release file.
|
||||
I do not know, currently if this is viable or even possible. But I think that a fully precompiled program with built in encoders and tools would be more attractive to most users.
|
||||
We should also see if there are other tools that would be considered natural for this project.
|
||||
|
||||
@@ -19,6 +19,12 @@ For a detailed breakdown of the project's goals, technical specifications, and d
|
||||
|
||||
For instructions on how to use the application, please refer to the [HOW-TO.md](HOW-TO.md) file.
|
||||
|
||||
## GUI
|
||||
|
||||
The application's graphical user interface has been updated to use `customtkinter` as of November 2, 2025. This provides a modern and customizable look and feel.
|
||||
|
||||
<!-- Screenshot of the GUI will be placed here -->
|
||||
|
||||
## Setup Notes for Arch Linux / CachyOS
|
||||
|
||||
When installing `ffmpeg-full` (required for DNxHR/HD codec support), users might encounter a dependency conflict with `obs-studio-browser`. `obs-studio-browser` typically requires `ffmpeg-obs`, which is incompatible with `ffmpeg-full`.
|
||||
|
||||
47
gui.py
47
gui.py
@@ -1,6 +1,6 @@
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog, messagebox, ttk
|
||||
import customtkinter
|
||||
from tkinter import filedialog, messagebox # Keep these for standard dialogs
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
@@ -15,58 +15,61 @@ class VideoConverterGUI:
|
||||
self.master = master
|
||||
master.title("Video Converter")
|
||||
|
||||
self.label = tk.Label(master, text="Select video file or enter URL:")
|
||||
customtkinter.set_appearance_mode("System") # Modes: "System" (default), "Dark", "Light"
|
||||
customtkinter.set_default_color_theme("blue") # Themes: "blue" (default), "green", "dark-blue")
|
||||
|
||||
self.label = customtkinter.CTkLabel(master, text="Select video file or enter URL:")
|
||||
self.label.pack()
|
||||
|
||||
self.filepath_label = tk.Label(master, text="")
|
||||
self.filepath_label = customtkinter.CTkLabel(master, text="")
|
||||
self.filepath_label.pack()
|
||||
|
||||
self.browse_button = tk.Button(master, text="Browse", command=self.browse_file)
|
||||
self.browse_button = customtkinter.CTkButton(master, text="Browse", command=self.browse_file)
|
||||
self.browse_button.pack()
|
||||
|
||||
self.url_label = tk.Label(master, text="URL:")
|
||||
self.url_label = customtkinter.CTkLabel(master, text="URL:")
|
||||
self.url_label.pack()
|
||||
|
||||
self.url_entry = tk.Entry(master, width=50)
|
||||
self.url_entry = customtkinter.CTkEntry(master, width=50)
|
||||
self.url_entry.pack()
|
||||
|
||||
self.quality_label = tk.Label(master, text="Quality:")
|
||||
self.quality_label = customtkinter.CTkLabel(master, text="Quality:")
|
||||
self.quality_label.pack()
|
||||
|
||||
self.quality_var = tk.StringVar(master)
|
||||
self.quality_var = customtkinter.StringVar(master)
|
||||
self.quality_var.set("medium") # default value
|
||||
self.quality_menu = tk.OptionMenu(master, self.quality_var, "low", "medium", "high", "archive")
|
||||
self.quality_menu = customtkinter.CTkOptionMenu(master, variable=self.quality_var, values=["low", "medium", "high", "archive"])
|
||||
self.quality_menu.pack()
|
||||
|
||||
self.cookies_label = tk.Label(master, text="Cookies from Browser:")
|
||||
self.cookies_label = customtkinter.CTkLabel(master, text="Cookies from Browser:")
|
||||
self.cookies_label.pack()
|
||||
|
||||
self.cookies_var = tk.StringVar(master)
|
||||
self.cookies_var = customtkinter.StringVar(master)
|
||||
self.cookies_var.set("none") # default value
|
||||
self.cookies_menu = tk.OptionMenu(master, self.cookies_var, "none", "brave", "chrome", "chromium", "edge", "firefox", "opera", "safari", "vivaldi", "whale")
|
||||
self.cookies_menu = customtkinter.CTkOptionMenu(master, variable=self.cookies_var, values=["none", "brave", "chrome", "chromium", "edge", "firefox", "opera", "safari", "vivaldi", "whale"])
|
||||
self.cookies_menu.pack()
|
||||
|
||||
|
||||
self.output_dir_label = tk.Label(master, text="Output Directory:")
|
||||
self.output_dir_label = customtkinter.CTkLabel(master, text="Output Directory:")
|
||||
self.output_dir_label.pack()
|
||||
|
||||
self.output_dir_button = tk.Button(master, text="Select Directory", command=self.select_output_dir)
|
||||
self.output_dir_button = customtkinter.CTkButton(master, text="Select Directory", command=self.select_output_dir)
|
||||
self.output_dir_button.pack()
|
||||
|
||||
self.output_dir_path_label = tk.Label(master, text="")
|
||||
self.output_dir_path_label = customtkinter.CTkLabel(master, text="")
|
||||
self.output_dir_path_label.pack()
|
||||
|
||||
self.convert_button = tk.Button(master, text="Convert", command=self.convert)
|
||||
self.convert_button = customtkinter.CTkButton(master, text="Convert", command=self.convert)
|
||||
self.convert_button.pack()
|
||||
|
||||
self.cancel_button = tk.Button(master, text="Cancel", command=self.cancel_conversion, state=tk.DISABLED)
|
||||
self.cancel_button = customtkinter.CTkButton(master, text="Cancel", command=self.cancel_conversion, state=customtkinter.DISABLED)
|
||||
self.cancel_button.pack()
|
||||
|
||||
self.status_var = tk.StringVar()
|
||||
self.status_label = tk.Label(master, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
|
||||
self.status_var = customtkinter.StringVar()
|
||||
self.status_label = customtkinter.CTkLabel(master, textvariable=self.status_var)
|
||||
self.status_label.pack(side=tk.BOTTOM, fill=tk.X)
|
||||
|
||||
self.progress = ttk.Progressbar(master, orient=tk.HORIZONTAL, length=100, mode='determinate')
|
||||
self.progress = customtkinter.CTkProgressBar(master, orientation="horizontal")
|
||||
self.progress.pack(side=tk.BOTTOM, fill=tk.X)
|
||||
|
||||
def browse_file(self):
|
||||
@@ -177,6 +180,6 @@ class VideoConverterGUI:
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = tk.Tk()
|
||||
root = customtkinter.CTk()
|
||||
gui = VideoConverterGUI(root)
|
||||
root.mainloop()
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
yt-dlp
|
||||
yt-dlp
|
||||
customtkinter
|
||||
Reference in New Issue
Block a user