Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei-g99 committed Oct 16, 2024
1 parent 167d4eb commit fcff3f0
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 0 deletions.
Binary file added icon.ico
Binary file not shown.
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ffmpeg-python==0.2.0
pycryptodomex==3.21.0
requests==2.32.3
yt-dlp==2024.10.7
218 changes: 218 additions & 0 deletions run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import tkinter as tk
from tkinter import filedialog
from tkinter import font
from tkinter import ttk
import re
from tkinter import messagebox
from tubecut.commands import _download_video, _trim_video

# Create the main window
root = tk.Tk()
root.title("TubeCut")
# Get screen width and height
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()

# Set the window size proportional to the screen size (e.g., 30% width and 15% height)
window_width = int(screen_width * 0.4)
window_height = int(screen_height * 0.3)

# Set the geometry of the window using the calculated width and height
root.geometry(f"{window_width}x{window_height}")

# Create a font for scaling and bold button text
label_font = font.Font(size=12) # Larger font for labels and entries
entry_font = font.Font(size=14) # Larger font for entry fields
button_font = font.Font(size=12) # Larger font and bold for buttons
bold_button_font = font.Font(size=12, weight="bold") # Larger font and bold for buttons

# Customize the style of the notebook tabs and buttons
style = ttk.Style()
style.configure("TNotebook.Tab", font=("Arial", 12), background="#D3D3D3") # Darker tab background
style.map("TNotebook.Tab", background=[("selected", "#A9A9A9")]) # Even darker when selected

download_url = tk.StringVar()
download_output_dir_path = tk.StringVar()
download_output_filename = tk.StringVar()

cut_file_path = tk.StringVar()
cut_output_filename = tk.StringVar()
cut_output_dir_path = tk.StringVar()
start_time = tk.StringVar()
end_time = tk.StringVar()

download_format_var = tk.StringVar()
cut_format_var = tk.StringVar()


formats = [
"mp4",
"mkv",
"webm",
"mp3",
"mp4a",
"opus"
]

def on_download():
try:
format = download_format_var.get()
if format == formats[0] or format == formats[1] or format == formats[2]:
audio_only = False
elif format == formats[3] or format == formats[4] or format == formats[5]:
audio_only = True

_download_video(url=download_url.get(), output_dir=download_output_dir_path.get(), filename=download_output_filename.get(), format=download_format_var.get(), audio_only=audio_only)
messagebox.showinfo("Success", "Video downloaded successfully!")
except Exception as e:
messagebox.showerror("Error", f"Failed to download video: {str(e)}")

def on_trim():
try:
_trim_video(file_path=cut_file_path.get(), output_dir=cut_output_dir_path.get(), start_time=start_time.get(), end_time=end_time.get(), output_filename=cut_output_filename.get())
messagebox.showinfo("Success", "Video trimmed successfully!")
except Exception as e:
messagebox.showerror("Error", f"Failed to trim video: {str(e)}")

# Function to handle directory selection (empty handler)
def on_directory_select():
dir_path = filedialog.askdirectory()
if dir_path:
dir_path_entry.delete(0, tk.END) # Clear current entry
dir_path_entry.insert(0, dir_path)
print(f"Directory selected: {dir_path}")

def on_cut_output_dir_select():
dir_path = filedialog.askdirectory()
if dir_path:
cut_output_dir_entry.delete(0, tk.END) # Clear current entry
cut_output_dir_entry.insert(0, dir_path)
print(f"Directory selected: {dir_path}")

# Function to handle directory selection for cutting
def on_cut_file_select():
file_path = filedialog.askopenfilename(
title="Select a File",
filetypes=[("Video Files", "*.mp4 *.avi *.mkv *.mov *.flv *.wmv *.webm")]
)
if file_path:
cut_file_path_entry.delete(0, tk.END) # Clear the entry field
cut_file_path_entry.insert(0, file_path) # Insert the selected file path
print(f"File selected: {file_path}") # Output the selected file path to console

def on_cut_output_file_select():
file_path = filedialog.askopenfilename(
title="Select a File",
filetypes=[("Video Files", "*.mp4 *.avi *.mkv *.mov *.flv *.wmv *.webm")]
)
if file_path:
cut_output_dir_entry.delete(0, tk.END) # Clear the entry field
cut_output_dir_entry.insert(0, file_path) # Insert the selected file path
print(f"File selected: {file_path}") # Output the selected file path to console


# Create a Notebook (for tabs)
notebook = ttk.Notebook(root)
notebook.pack(pady=10, padx=10, expand=True, fill="both")

# Create frames for the two tabs
download_frame = tk.Frame(notebook, width=700, height=250)
cut_frame = tk.Frame(notebook, width=700, height=250)

# Add the tabs to the notebook
notebook.add(download_frame, text="YT Download")
notebook.add(cut_frame, text="Cut")

# --- Download Tab UI ---
# URL Entry Field for Download tab
url_label = tk.Label(download_frame, text="Enter URL:", font=label_font)
url_label.grid(row=0, column=0, padx=10, pady=10, sticky="e")

url_entry = tk.Entry(download_frame, font=entry_font, textvariable=download_url)
url_entry.grid(row=0, column=1, padx=10, pady=10, sticky="ew", columnspan=6)

# Create a dropdown (Combobox) for format selection in download_frame
format_combobox = ttk.Combobox(download_frame, textvariable=download_format_var, values=formats, state="readonly", font=entry_font)
format_combobox.set("Select a format") # Set the default text
format_combobox.grid(row=3, column=4, padx=10, pady=10, sticky="ew") # Place in the grid of download_frame


url_button = tk.Button(download_frame, text="Download", command=on_download, font=bold_button_font)
url_button.grid(row=3, column=2, padx=10, pady=10, sticky="ew")

# Directory Path Entry Field for Download tab
dir_path_label = tk.Label(download_frame, text="Select output directory:", font=label_font)
dir_path_label.grid(row=1, column=0, padx=10, pady=10, sticky="e")

dir_path_entry = tk.Entry(download_frame, font=entry_font, textvariable=download_output_dir_path)
dir_path_entry.grid(row=1, column=1, padx=10, pady=10, sticky="ew", columnspan=6)

# Directory Path Entry Field for Download tab
filename_label = tk.Label(download_frame, text="Insert output file name:", font=label_font)
filename_label.grid(row=2, column=0, padx=10, pady=10, sticky="e")

filename_entry = tk.Entry(download_frame, font=entry_font, textvariable=download_output_filename)
filename_entry.grid(row=2, column=1, padx=10, pady=10, sticky="ew", columnspan=6)

dir_path_button = tk.Button(download_frame, text="Browse", command=on_directory_select, font=button_font)
dir_path_button.grid(row=1, column=7, padx=10, pady=10, sticky="ew")


# --- Cut Tab UI ---
# File Selection for Cut tab
cut_file_path_label = tk.Label(cut_frame, text="Select file to cut:", font=label_font)
cut_file_path_label.grid(row=0, column=0, padx=10, pady=10, sticky="e")

cut_file_path_entry = tk.Entry(cut_frame, font=entry_font, textvariable=cut_file_path)
cut_file_path_entry.grid(row=0, column=1, padx=10, pady=10, sticky="ew", columnspan=4)

cut_file_path_button = tk.Button(cut_frame, text="Browse", command=on_cut_file_select, font=button_font)
cut_file_path_button.grid(row=0, column=6, padx=10, pady=10, sticky="ew")

# Labels and entries for start and end time in HH:MM:SS format
start_time_label = tk.Label(cut_frame, text="Start Time (HH:MM:SS):", font=label_font)
start_time_label.grid(row=3, column=0, padx=10, pady=10, sticky="e")

start_time_entry = tk.Entry(cut_frame, font=entry_font, width=10, textvariable=start_time)
start_time_entry.grid(row=3, column=1, padx=10, pady=10, sticky="ew")

start_time_label = tk.Label(cut_frame, text="Empty for first frame", font=label_font)
start_time_label.grid(row=3, column=3, padx=1, pady=1, sticky="e")

end_time_label = tk.Label(cut_frame, text="End Time (HH:MM:SS):", font=label_font)
end_time_label.grid(row=4, column=0, padx=10, pady=10, sticky="e")

end_time_entry = tk.Entry(cut_frame, font=entry_font, width=10, textvariable=end_time)
end_time_entry.grid(row=4, column=1, padx=10, pady=10, sticky="ew")

start_time_label = tk.Label(cut_frame, text="Empty for last frame", font=label_font)
start_time_label.grid(row=4, column=3, padx=1, pady=1, sticky="e")

# Directory Path Entry Field for Download tab
filename_cut_label = tk.Label(cut_frame, text="Insert output file name:", font=label_font)
filename_cut_label.grid(row=1, column=0, padx=10, pady=10, sticky="e")

filename_cut_entry = tk.Entry(cut_frame, font=entry_font, textvariable=cut_output_filename)
filename_cut_entry.grid(row=1, column=1, padx=10, pady=10, sticky="ew", columnspan=5)

# Directory Path Entry Field for Download tab
cut_output_dir_label = tk.Label(cut_frame, text="Select output directory:", font=label_font)
cut_output_dir_label.grid(row=2, column=0, padx=10, pady=10, sticky="e")

cut_output_dir_entry = tk.Entry(cut_frame, font=entry_font, textvariable=cut_output_dir_path)
cut_output_dir_entry.grid(row=2, column=1, padx=10, pady=10, sticky="ew", columnspan=5)

cut_output_dir_button = tk.Button(cut_frame, text="Browse", command=on_cut_output_dir_select, font=button_font)
cut_output_dir_button.grid(row=2, column=6, padx=10, pady=10, sticky="ew")

# Submit button for trimming video
submit_button = tk.Button(cut_frame, text="Trim Video", font=bold_button_font, command=on_trim)
submit_button.grid(row=5, column=1, padx=10, pady=20, sticky="ew")

# Create a dropdown (Combobox) for format selection in download_frame
format_combobox_cut = ttk.Combobox(cut_frame, textvariable=cut_format_var, values=formats, state="readonly", font=entry_font)
format_combobox_cut.set("Select output file format") # Set the default text
format_combobox_cut.grid(row=5, column=4, padx=10, pady=10, sticky="ew") # Place in the grid of download_frame

# Start the Tkinter event loop
root.mainloop()
Empty file added tubecut/__init__.py
Empty file.
82 changes: 82 additions & 0 deletions tubecut/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import subprocess
import os
from pathlib import Path
import yt_dlp
import ffmpeg

def _download_video(url, output_dir, filename, format="mp4", audio_only=False):
# Adjust the format options based on whether it's video or audio
if audio_only:
# If audio_only is True, extract audio and save as MP3 (or another format)
ydl_opts = {
'format': 'bestaudio/best', # Download best audio
'outtmpl': f'{output_dir}/{filename}.%(ext)s', # Use extension of the extracted audio
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': format, # Convert to the desired audio format (e.g., 'mp3', 'm4a', 'opus')
'preferredquality': '192', # Audio quality (e.g., 192 kbps)
}],
}
else:
# If downloading video, select the best video and audio and merge into a single file
ydl_opts = {
'format': f'bestvideo[ext={format}]+bestaudio[ext=m4a]/best[ext={format}]', # Download best video with chosen format
'outtmpl': f'{output_dir}/{filename}.%(ext)s', # Output filename
'postprocessors': [{
'key': 'FFmpegVideoConvertor',
'preferedformat': format, # Convert to the desired video format if needed
}],
}

# Perform the download
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
print(f"Download complete: {filename}.{format}")

def _trim_video(file_path, output_dir, start_time, end_time, output_filename):
if (start_time == "") and (end_time == ""):
raise Exception('Start Time and End Time cannot be both empty.')

# Ensure the output directory exists
if not os.path.exists(output_dir):
os.makedirs(output_dir)

# Construct the full output file path and infer the output format
output_file = os.path.join(output_dir, output_filename)

# Get the output format from the file extension (e.g., mp4, mp3, etc.)
output_format = output_filename.split('.')[-1] # Extract file extension (e.g., 'mp4', 'mp3')

# Trim the input file based on start_time and end_time
input_args = {}
if start_time != "":
input_args['ss'] = start_time
if end_time != "":
input_args['to'] = end_time

# ffmpeg trimming with input arguments and specifying output format
ffmpeg.input(file_path, **input_args).output(output_file, format=output_format).run()

print(f"Trimmed video/audio saved to: {output_file}")

# def _trim_video(file_path, output_dir, start_time, end_time, output_filename):

# if (start_time == "") and (end_time == ""):
# raise Exception('Start Time and End Time cannot be both empty.')

# # Ensure the output directory exists
# if not os.path.exists(output_dir):
# os.makedirs(output_dir)

# # Construct the full output file path
# output_file = os.path.join(output_dir, f'{output_filename}.mp4')


# if (start_time == ""):
# ffmpeg.input(file_path, to=end_time).output(output_file).run()
# elif (end_time == ""):
# ffmpeg.input(file_path, ss=start_time).output(output_file).run()
# else:
# ffmpeg.input(file_path, ss=start_time, to=end_time).output(output_file).run()


0 comments on commit fcff3f0

Please sign in to comment.