-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathyoutube.com.py
executable file
·242 lines (197 loc) · 9.54 KB
/
youtube.com.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#!/usr/bin/env python3
import subprocess
import os
import time
import sys
import multiprocessing
try:
from colorama import Fore, init
import pyfiglet
FANCY_AVAILABLE = True
# Initialize Colorama
init(autoreset=True)
except ImportError:
FANCY_AVAILABLE = False
# Script version and author info
__version__ = "1.0.2"
__author__ = "EIRSVi"
# Number of parallel downloads for playlists
# Default to number of CPU cores or 4, whichever is lower
MAX_PARALLEL_DOWNLOADS = min(multiprocessing.cpu_count(), 4)
def print_text(text, color=None, center=False):
"""Utility function to print text with optional color and centering."""
terminal_width = os.get_terminal_size().columns
if center:
text = text.center(terminal_width)
if FANCY_AVAILABLE and color:
print(f"{color}{text}")
elif color and color.startswith("\033"):
print(f"{color}{text}\033[0m")
else:
print(text)
def print_logo():
"""Print the logo based on available dependencies."""
if FANCY_AVAILABLE:
# Generate ASCII art for the logo with a modern font
logo = pyfiglet.figlet_format("SRIEVi", font="slant")
# Center the logo in the terminal
terminal_width = os.get_terminal_size().columns
centered_logo = "\n".join(line.center(terminal_width) for line in logo.splitlines())
# Colors for the gradient effect
colors = [Fore.LIGHTCYAN_EX, Fore.CYAN, Fore.MAGENTA, Fore.LIGHTMAGENTA_EX, Fore.LIGHTGREEN_EX, Fore.LIGHTBLUE_EX]
# Apply a glowing effect to each character in the logo
print("\n") # Add spacing before the logo
for i, char in enumerate(centered_logo):
if char.strip(): # Apply color only to non-space characters
print(colors[i % len(colors)] + char, end='', flush=True)
time.sleep(0.01) # Slight delay to create a glowing effect
else:
print(char, end='', flush=True)
print("\n") # New line after the logo
else:
# Minimal logo with ANSI colors
print_text("YouTube Downloader", "\033[38;5;39m", center=True)
print_text("@EIRSVi | @kmjBuCa", "\033[38;5;50m", center=True)
def print_welcome():
"""Display welcome message and tool information."""
# Print the logo
print_logo()
if FANCY_AVAILABLE:
print_text("Welcome to the YouTube Downloader! \n", Fore.LIGHTBLUE_EX, center=True)
print_text("Support us @eirsvi", Fore.LIGHTGREEN_EX, center=True)
print_text("GitHub | X | YouTube \n", Fore.LIGHTRED_EX, center=True)
else:
print_text("\nNote:", "\033[38;5;39m")
print_text("##### Single videos", "\033[38;5;50m")
print_text("##### YouTube playlists", "\033[38;5;50m")
print("\nVideos are saved in MP4 format in ~/Videos.")
print("Audio is saved in MP3 format in ~/Music.\n")
def check_dependencies():
"""Check if yt-dlp is installed."""
try:
subprocess.run(['yt-dlp', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
return True
except (subprocess.CalledProcessError, FileNotFoundError):
color = Fore.LIGHTRED_EX if FANCY_AVAILABLE else "\033[38;5;196m"
print_text("Error: yt-dlp not found. Please install it with 'pip install yt-dlp'", color)
return False
def download_content(url, download_type, is_playlist=False):
"""Unified function to download YouTube content (video or audio, single or playlist)."""
# Define the base directory and format based on download type
if download_type in ['v', 'video']:
base_dir = os.path.expanduser('~/Videos')
format_option = "mp4"
content_type = "video"
else:
base_dir = os.path.expanduser('~/Music')
format_option = "mp3"
content_type = "audio"
# Make sure the directory exists
if not os.path.exists(base_dir):
os.makedirs(base_dir)
# Set up color for messages
info_color = Fore.LIGHTCYAN_EX if FANCY_AVAILABLE else "\033[38;5;39m"
success_color = Fore.LIGHTGREEN_EX if FANCY_AVAILABLE else "\033[38;5;50m"
error_color = Fore.LIGHTRED_EX if FANCY_AVAILABLE else "\033[38;5;196m"
# Print download start message
playlist_text = "playlist " if is_playlist else ""
print_text(f"Downloading {playlist_text}{content_type} to: {base_dir}", info_color)
try:
# Handle playlist vs single video differently
if is_playlist:
# Get the playlist title
print_text("Getting playlist information...", Fore.YELLOW if FANCY_AVAILABLE else "\033[38;5;226m")
playlist_title = subprocess.run(['yt-dlp', '--print', '%(playlist_title)s', url],
capture_output=True, text=True).stdout.strip()
# Create a folder with the playlist title
playlist_folder = os.path.join(base_dir, playlist_title)
os.makedirs(playlist_folder, exist_ok=True)
# Generate the output file name
output_file = os.path.join(playlist_folder, f'%(title)s.{format_option}')
# Build the command with optimized settings for playlists
command = ['yt-dlp', '-o', output_file]
if download_type in ['v', 'video']:
command.extend(['--format', 'mp4'])
else:
command.extend(['-x', '--audio-format', 'mp3'])
# Add optimization flags for playlists
command.extend([
'--concurrent-fragments', str(MAX_PARALLEL_DOWNLOADS),
'-N', str(MAX_PARALLEL_DOWNLOADS),
'--no-check-certificate',
'--geo-bypass',
'--ignore-errors',
'--no-overwrites',
'--no-post-overwrites'
])
# Add the URL
command.append(url)
print_text(f"Starting download with {MAX_PARALLEL_DOWNLOADS} parallel processes...", info_color)
# Run the command
subprocess.run(command, check=True)
# Success message
print_text("Playlist download completed successfully!", success_color)
print_text(f"Playlist saved in: {playlist_folder}", success_color)
else:
# For single video/audio, no folder is created
output_file = os.path.join(base_dir, f'%(title)s.{format_option}')
# Build the command for single video/audio
if download_type in ['v', 'video']:
command = ['yt-dlp', '-o', output_file, '--format', 'mp4', url]
else:
command = ['yt-dlp', '-o', output_file, '-x', '--audio-format', 'mp3', url]
# Run the command
subprocess.run(command, check=True)
# Success message
print_text("Download completed successfully!", success_color)
print_text(f"File saved in: {base_dir}", success_color)
except subprocess.CalledProcessError as e:
print_text(f"Error downloading content: {e}", error_color)
def main():
"""Main function to run the YouTube downloader."""
# Check if yt-dlp is installed
if not check_dependencies():
return
# Display welcome message
print_welcome()
# Set up colors
prompt_color = Fore.LIGHTCYAN_EX if FANCY_AVAILABLE else "\033[38;5;39m"
option_color = Fore.LIGHTYELLOW_EX if FANCY_AVAILABLE else "\033[38;5;226m"
error_color = Fore.LIGHTRED_EX if FANCY_AVAILABLE else "\033[38;5;196m"
# Prompt user to select download type
print_text("Select download type:", option_color)
print_text("1. Single video", option_color)
print_text("2. Playlist (Optimized for speed)", option_color)
choice = input(f"{prompt_color}Enter your choice (1/2): {'' if not FANCY_AVAILABLE else Fore.RESET}")
# Validate choice
if choice not in ['1', '2']:
print_text("Invalid choice. Please enter 1 or 2.", error_color)
return
# Prompt for URL
url = input(f"{prompt_color}Enter the YouTube URL: {'' if not FANCY_AVAILABLE else Fore.RESET}")
# Prompt for download format (video or audio)
format_choice = input(f"{prompt_color}Download as (v)ideo or (a)udio? (v/a): {'' if not FANCY_AVAILABLE else Fore.RESET}").strip().lower()
# Validate format choice
if format_choice not in ['v', 'a', 'video', 'audio']:
print_text("Invalid choice. Please enter 'v' for video or 'a' for audio.", error_color)
return
# Process the download based on user choices
is_playlist = (choice == '2')
# For playlists, allow user to set parallel downloads
if is_playlist:
global MAX_PARALLEL_DOWNLOADS
try:
custom_parallel = input(f"{prompt_color}Number of parallel downloads (default: {MAX_PARALLEL_DOWNLOADS}, press Enter to use default): {'' if not FANCY_AVAILABLE else Fore.RESET}")
if custom_parallel.strip():
MAX_PARALLEL_DOWNLOADS = max(1, min(8, int(custom_parallel)))
except ValueError:
print_text(f"Using default parallel downloads: {MAX_PARALLEL_DOWNLOADS}", option_color)
# Download the content
download_content(url, format_choice, is_playlist)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
color = Fore.LIGHTRED_EX if FANCY_AVAILABLE else "\033[38;5;196m"
print_text("\nDownload canceled by user.", color)
sys.exit(0)