Created
January 21, 2024 06:04
-
-
Save graylan0/072610edae183f973ff08e4f7ca83389 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import concurrent.futures | |
from tkinter import * | |
from tkinter import filedialog, messagebox | |
from pytube import YouTube | |
import threading | |
import json | |
import logging | |
import re | |
from subprocess import call | |
queue = [] | |
download_count = 0 | |
max_downloads = 25 | |
download_thread = None | |
downloaded_videos = set() | |
status_labels = [] | |
logging.basicConfig(filename='app.log', filemode='w', format='%(asctime)s - %(message)s', level=logging.INFO) | |
def convert_to_mp3_ffmpeg(video_path, target_path): | |
command = ["ffmpeg", "-i", video_path, target_path] | |
call(command) | |
logging.info(f"Converted video to MP3 at {target_path}") | |
def update_status(status_label, message): | |
status_label.config(text=message) | |
root.update_idletasks() | |
def download_video(url, path, status_label): | |
global download_count | |
try: | |
update_status(status_label, "Downloading...") | |
yt = YouTube(url) | |
video = yt.streams.filter(only_audio=True).first() | |
video_path = video.download(output_path=path) | |
target_path = os.path.join(path, yt.title + '.mp3') | |
convert_to_mp3_ffmpeg(video_path, target_path) | |
os.remove(video_path) | |
logging.info(f"Downloaded and converted video to MP3 at {target_path}") | |
video_id = extract_video_id(url) | |
downloaded_videos.add(video_id) | |
download_count += 1 | |
update_status(status_label, "Download Complete") | |
except Exception as e: | |
logging.error(f"Error downloading {url}: {e}") | |
update_status(status_label, "Download Failed") | |
def process_url(url_suffix, path): | |
base_url = "https://www.youtube.com" | |
full_url = base_url + url_suffix | |
queue.append((full_url, path)) | |
def start_downloads(): | |
global download_thread | |
while queue: | |
url, path = queue.pop(0) | |
status_label = status_labels[download_count % len(status_labels)] | |
download_video(url, path, status_label) | |
download_thread = None | |
def search_related_videos(): | |
for video_id in downloaded_videos: | |
search_results = YoutubeSearch(video_id, max_results=5).to_dict() | |
for result in search_results: | |
print(f"Related video: {result['title']} - URL: https://www.youtube.com{result['url_suffix']}") | |
def submit_download(event=None): | |
global download_thread | |
url = url_entry.get() | |
path = path_entry.get() | |
process_url(url, path) | |
url_entry.delete(0, END) | |
if not download_thread: | |
download_thread = threading.Thread(target=start_downloads) | |
download_thread.start() | |
with open('config.json', 'w') as f: | |
json.dump({'path': path}, f) | |
def extract_video_id(url): | |
video_id_match = re.search(r"(?<=v=)[^&#]+", url) | |
return video_id_match.group() if video_id_match else None | |
def load_path(): | |
if not os.path.exists('config.json'): | |
with open('config.json', 'w') as f: | |
json.dump({}, f) | |
with open('config.json', 'r') as f: | |
config = json.load(f) | |
return config.get('path', '') | |
def set_max_downloads(val): | |
global max_downloads | |
max_downloads = int(val) | |
def choose_path(): | |
path = filedialog.askdirectory() | |
path_entry.delete(0, END) | |
path_entry.insert(0, path) | |
root = Tk() | |
root.geometry("1280x720") | |
bg_color = '#000000' | |
text_color = '#FFFFFF' | |
button_color = '#2D2D2D' | |
highlight_color = '#505050' | |
root.configure(background=bg_color) | |
url_label = Label(root, text="Enter URL:", bg=bg_color, fg=text_color) | |
url_label.pack() | |
url_entry = Entry(root, bg=bg_color, fg=text_color) | |
url_entry.bind('<Return>', submit_download) | |
url_entry.pack() | |
path_label = Label(root, text="Enter Path:", bg=bg_color, fg=text_color) | |
path_label.pack() | |
path_entry = Entry(root, bg=bg_color, fg=text_color) | |
path_entry.insert(0, load_path()) | |
path_entry.pack() | |
choose_path_button = Button(root, text="Choose Path", command=choose_path, bg=button_color, activebackground=highlight_color) | |
choose_path_button.pack() | |
submit_button = Button(root, text="Download", command=submit_download, bg=button_color, activebackground=highlight_color) | |
submit_button.pack() | |
search_button = Button(root, text="Search from Past Downloads", command=search_related_videos, bg=button_color, activebackground=highlight_color) | |
search_button.pack() | |
max_downloads_slider = Scale(root, from_=5, to=25, orient=HORIZONTAL, label='Max Downloads', command=set_max_downloads) | |
max_downloads_slider.set(25) | |
max_downloads_slider.pack() | |
# Status labels for visual feedback | |
for i in range(3): | |
status_label = Label(root, text="Waiting...", bg=bg_color, fg=text_color) | |
status_label.pack() | |
status_labels.append(status_label) | |
root.mainloop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment