Skip to content

Instantly share code, notes, and snippets.

@graylan0
Created January 21, 2024 06:04
Show Gist options
  • Save graylan0/072610edae183f973ff08e4f7ca83389 to your computer and use it in GitHub Desktop.
Save graylan0/072610edae183f973ff08e4f7ca83389 to your computer and use it in GitHub Desktop.
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