-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOptiFetch_2026.py
More file actions
300 lines (250 loc) · 9.58 KB
/
OptiFetch_2026.py
File metadata and controls
300 lines (250 loc) · 9.58 KB
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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
import yt_dlp
import os
import json
import shutil
# Configuration file for storing permanent settings
CONFIG_FILE = "youtube_downloader_config.json"
DEFAULT_SAVE_PATH = os.path.expanduser("~/Downloads")
# Find ffmpeg path
def find_ffmpeg():
"""Find ffmpeg executable in system PATH"""
ffmpeg_path = shutil.which('ffmpeg')
if ffmpeg_path:
print(f"✓ ffmpeg found at: {ffmpeg_path}")
else:
print("⚠️ WARNING: ffmpeg not found in PATH!")
print(" Please install ffmpeg or add it to your system PATH")
return ffmpeg_path
# Default configuration
DEFAULT_CONFIG = {
"save_path": DEFAULT_SAVE_PATH,
"resolution": "best",
"format": "mp4"
}
# Current session settings (can be overridden temporarily)
current_settings = {}
# ==================== Configuration Management ====================
def load_config():
"""Load permanent configuration from file"""
if os.path.exists(CONFIG_FILE):
try:
with open(CONFIG_FILE, 'r') as f:
return json.load(f)
except:
return DEFAULT_CONFIG.copy()
return DEFAULT_CONFIG.copy()
def save_config(config):
"""Save permanent configuration to file"""
with open(CONFIG_FILE, 'w') as f:
json.dump(config, f, indent=4)
print("✓ Configuration saved permanently!")
def get_current_settings():
"""Get current settings (temporary overrides permanent)"""
config = load_config()
# Merge permanent config with temporary session overrides
config.update(current_settings)
return config
# ==================== User Interface ====================
def display_main_menu():
"""Display main menu options"""
print("\n" + "="*50)
print(" OptiFetch 2026 - YouTube Downloader")
print("="*50)
print("1. Download Video")
print("2. View Current Settings")
print("3. Change Settings (Temporary)")
print("4. Change Settings (Permanent)")
print("5. Reset to Default Settings")
print("6. Exit")
print("Side Note: The default save path is C:\\Users\\<Username>\\Downloads.")
print("="*50)
def display_settings(settings):
"""Display current settings"""
print("\n" + "-"*50)
print(" CURRENT SETTINGS")
print("-"*50)
print(f"Save Path: {settings['save_path']}")
print(f"Resolution: {settings['resolution']}")
print(f"Format: {settings['format']}")
print("-"*50)
def change_resolution():
"""Allow user to select resolution"""
print("\nResolution Options:")
resolutions = {
'1': ('best', 'Best Quality (auto-select)'),
'2': ('1080', '1080p (Full HD)'),
'3': ('720', '720p (HD)'),
'4': ('480', '480p (SD)'),
'5': ('360', '360p (Low)'),
}
for key, (res_code, res_name) in resolutions.items():
print(f" {key}. {res_name}")
choice = input("Select resolution (1-5): ").strip()
if choice in resolutions:
return resolutions[choice][0]
else:
print("Invalid choice. Using 'best' quality.")
return 'best'
def change_format():
"""Allow user to select output format"""
print("\nFormat Options:")
formats = {
'1': ('mp4', 'MP4 (Most Compatible)'),
'2': ('mkv', 'MKV (Higher Quality)'),
'3': ('webm', 'WEBM (Web Format)'),
}
for key, (fmt, fmt_name) in formats.items():
print(f" {key}. {fmt_name}")
choice = input("Select format (1-3): ").strip()
if choice in formats:
return formats[choice][0]
else:
print("Invalid choice. Using 'mp4'.")
return 'mp4'
def change_save_path():
"""Allow user to specify save path"""
print("\nCurrent save path:", DEFAULT_SAVE_PATH)
path = input("Enter new save path (or press Enter to keep current): ").strip()
if not path:
return None
if not os.path.exists(path):
create = input(f"Path doesn't exist. Create it? (y/n): ").strip().lower()
if create == 'y':
try:
os.makedirs(path)
return path
except Exception as e:
print(f"Error creating path: {e}")
return None
else:
return None
return path
def temporary_settings_menu():
"""Menu for temporary (session-only) settings changes"""
global current_settings
print("\n" + "="*50)
print(" TEMPORARY SETTINGS (This Session Only)")
print("="*50)
while True:
settings = get_current_settings()
print(f"\n1. Resolution: {settings['resolution']}")
print(f"2. Format: {settings['format']}")
print(f"3. Save Path: {settings['save_path']}")
print("4. Back to Main Menu")
choice = input("\nSelect option to change (1-4): ").strip()
if choice == '1':
current_settings['resolution'] = change_resolution()
elif choice == '2':
current_settings['format'] = change_format()
elif choice == '3':
path = change_save_path()
if path:
current_settings['save_path'] = path
elif choice == '4':
break
else:
print("Invalid choice!")
def permanent_settings_menu():
"""Menu for permanent settings changes"""
config = load_config()
print("\n" + "="*50)
print(" PERMANENT SETTINGS (Saved for Future Use)")
print("="*50)
while True:
print(f"\n1. Resolution: {config['resolution']}")
print(f"2. Format: {config['format']}")
print(f"3. Save Path: {config['save_path']}")
print("4. Back to Main Menu")
choice = input("\nSelect option to change (1-4): ").strip()
if choice == '1':
config['resolution'] = change_resolution()
save_config(config)
elif choice == '2':
config['format'] = change_format()
save_config(config)
elif choice == '3':
path = change_save_path()
if path:
config['save_path'] = path
save_config(config)
elif choice == '4':
break
else:
print("Invalid choice!")
# ==================== Download Functions ====================
def build_format_option(resolution, format_type):
"""Build yt-dlp format string based on resolution and format"""
if resolution == 'best':
return f'bestvideo[ext={format_type}]+bestaudio[ext=m4a]/best[ext={format_type}]/best'
else:
return f'bestvideo[height<={resolution}][ext={format_type}]+bestaudio/best[height<={resolution}]/best'
def my_hook(d):
"""Progress hook function"""
if d['status'] == 'finished':
print('\n✓ Done downloading!')
def download_video(url):
"""Download video with current settings"""
settings = get_current_settings()
# Check for ffmpeg
ffmpeg_path = find_ffmpeg()
if not ffmpeg_path:
print("\n❌ Error: ffmpeg is required to merge video and audio.")
print(" Please install ffmpeg:")
print(" - winget install ffmpeg")
print(" - or download from: https://ffmpeg.org/download.html")
return
# Ensure save path exists
if not os.path.exists(settings['save_path']):
os.makedirs(settings['save_path'])
output_template = os.path.join(settings['save_path'], '%(title)s.%(ext)s')
ydl_opts = {
'format': build_format_option(settings['resolution'], settings['format']),
'outtmpl': output_template,
'merge_output_format': settings['format'],
'ffmpeg_location': ffmpeg_path,
'noplaylist': True,
'progress_hooks': [my_hook],
}
print(f"\n📥 Downloading with settings:")
print(f" Resolution: {settings['resolution']}")
print(f" Format: {settings['format']}")
print(f" Save Path: {settings['save_path']}\n")
try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
except Exception as e:
print(f"Error downloading: {e}")
# ==================== Main Program ====================
def main():
"""Main program loop"""
print(" (By Utilizing This Software, You Agree To The Terms And Conditions. \n https://github.com/yosuf-e/OptiFetch/blob/main/README.md)")
print("\n🎥 Welcome to OptiFetch!")
while True:
display_main_menu()
choice = input("Select option (1-6): ").strip()
if choice == '1':
url = input("\nEnter YouTube URL: ").strip()
if url:
download_video(url)
else:
print("Invalid URL!")
elif choice == '2':
settings = get_current_settings()
display_settings(settings)
elif choice == '3':
temporary_settings_menu()
elif choice == '4':
permanent_settings_menu()
elif choice == '5':
confirm = input("\nReset to default settings? (y/n): ").strip().lower()
if confirm == 'y':
save_config(DEFAULT_CONFIG.copy())
current_settings.clear()
print("✓ Reset to defaults!")
elif choice == '6':
print("\nGoodbye! 👋")
break
else:
print("Invalid choice! Please try again.")
if __name__ == "__main__":
main()