Nymbo commited on
Commit
f49eaee
·
verified ·
1 Parent(s): fadefaf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +375 -167
app.py CHANGED
@@ -1,181 +1,389 @@
1
  import gradio as gr
2
- import yt_dlp
3
- import os
4
 
5
- def run_yt_dlp_command(command):
 
 
 
6
  try:
7
- yt_dlp.main(command.split())
8
- return "Download completed successfully!"
 
 
 
 
 
 
9
  except Exception as e:
10
- return f"An error occurred: {str(e)}"
11
 
12
- def list_formats(url):
13
- return run_yt_dlp_command(f"yt-dlp -F {url}")
 
 
 
14
 
15
- def download_mp3_max_quality(url):
16
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --postprocessor-args \"-b:a 320k\" -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- def basic_high_quality_mp3(url):
19
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
- def download_custom_bitrate(url, bitrate):
22
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format mp3 --postprocessor-args \"-b:a {bitrate}k\" -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
23
-
24
- def download_with_metadata(url):
25
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --embed-metadata -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
26
-
27
- def download_playlist(url):
28
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o \"P:/Local Music/%(playlist_title)s/%(title)s.%(ext)s\" {url}")
29
-
30
- def download_playlist_range(url, range):
31
- return run_yt_dlp_command(f"yt-dlp --playlist-items {range} -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o \"P:/Local Music/%(playlist_title)s/%(title)s.%(ext)s\" {url}")
32
-
33
- def download_hq_soundcloud(url):
34
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o \"P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s\" {url}")
35
-
36
- def embed_album_art(url):
37
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format mp3 --embed-thumbnail --audio-quality 0 -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
38
-
39
- def download_opus(url):
40
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format opus -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
41
-
42
- def skip_downloaded_files(url):
43
- return run_yt_dlp_command(f"yt-dlp --download-archive \"P:/Local Music/downloaded.txt\" -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
44
-
45
- def download_multiple_files(urls):
46
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --add-metadata --embed-thumbnail --write-description --postprocessor-args \"-b:a 320k\" -o \"P:/Local Music/%(title)s.%(ext)s\" {' '.join(urls.split(','))}")
47
-
48
- def download_with_chapters(url):
49
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --split-chapters -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
50
-
51
- def extract_portion(url, start, end):
52
- return run_yt_dlp_command(f"yt-dlp -f bestvideo+bestaudio --external-downloader ffmpeg --external-downloader-args \"ffmpeg_i:-ss {start} -to {end}\" -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
53
-
54
- def update_metadata(url):
55
- return run_yt_dlp_command(f"yt-dlp --download-archive \"P:/Local Music/downloaded.txt\" --skip-download --embed-metadata --embed-thumbnail --write-description {url}")
56
-
57
- def auto_rename_duplicates(url):
58
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --force-overwrites -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
59
-
60
- def download_from_url_list(file_path):
61
- return run_yt_dlp_command(f"yt-dlp -a \"{file_path}\" -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o \"P:/Local Music/%(title)s.%(ext)s\"")
62
-
63
- def limit_download_speed(url, speed):
64
- return run_yt_dlp_command(f"yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --rate-limit {speed} -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
65
-
66
- def download_youtube_transcript(url, format):
67
- if format == "text":
68
- return run_yt_dlp_command(f"yt-dlp --write-auto-subs --sub-lang en --skip-download -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
69
- elif format == "markdown":
70
- return run_yt_dlp_command(f"yt-dlp --write-auto-subs --sub-lang en --skip-download --convert-subs srt -o \"P:/Local Music/%(title)s.md\" {url}")
71
-
72
- def download_video_info(url):
73
- return run_yt_dlp_command(f"yt-dlp --write-info-json --skip-download -o \"P:/Local Music/%(title)s.json\" {url}")
74
-
75
- def download_age_restricted_content(url, username, password):
76
- return run_yt_dlp_command(f"yt-dlp --username \"{username}\" --password \"{password}\" -f bestvideo+bestaudio -o \"P:/Local Music/%(title)s.%(ext)s\" {url}")
77
-
78
- # Define the Gradio interface
79
  with gr.Blocks() as demo:
80
- gr.Markdown("# YT-DLP Download Interface")
 
 
 
 
 
 
81
 
82
  with gr.Tab("General Commands"):
83
- with gr.Row():
84
- url_general = gr.Textbox(label="Video URL")
85
- btn_list_formats = gr.Button("List Formats")
86
- btn_list_formats.click(list_formats, inputs=url_general, outputs="text_box_output")
87
-
88
- with gr.Row():
89
- btn_mp3_max_quality = gr.Button("Download MP3 Max Quality")
90
- btn_mp3_max_quality.click(download_mp3_max_quality, inputs=url_general, outputs="text_box_output")
91
-
92
- with gr.Row():
93
- btn_basic_mp3 = gr.Button("Basic High-Quality MP3")
94
- btn_basic_mp3.click(basic_high_quality_mp3, inputs=url_general, outputs="text_box_output")
95
-
96
- with gr.Row():
97
- bitrate = gr.Textbox(label="Custom Bitrate (e.g., 192)")
98
- btn_custom_bitrate = gr.Button("Download Custom Bitrate")
99
- btn_custom_bitrate.click(download_custom_bitrate, inputs=[url_general, bitrate], outputs="text_box_output")
100
-
101
- with gr.Row():
102
- btn_metadata = gr.Button("Download with Metadata")
103
- btn_metadata.click(download_with_metadata, inputs=url_general, outputs="text_box_output")
104
-
105
- with gr.Row():
106
- btn_playlist = gr.Button("Download Playlist")
107
- btn_playlist.click(download_playlist, inputs=url_general, outputs="text_box_output")
108
-
109
- with gr.Row():
110
- playlist_range = gr.Textbox(label="Playlist Range (e.g., 1-5)")
111
- btn_playlist_range = gr.Button("Download Playlist Range")
112
- btn_playlist_range.click(download_playlist_range, inputs=[url_general, playlist_range], outputs="text_box_output")
113
-
114
- with gr.Row():
115
- btn_hq_soundcloud = gr.Button("Download HQ from SoundCloud")
116
- btn_hq_soundcloud.click(download_hq_soundcloud, inputs=url_general, outputs="text_box_output")
117
-
118
- with gr.Row():
119
- btn_album_art = gr.Button("Embed Album Art")
120
- btn_album_art.click(embed_album_art, inputs=url_general, outputs="text_box_output")
121
-
122
- with gr.Row():
123
- btn_opus = gr.Button("Download Opus")
124
- btn_opus.click(download_opus, inputs=url_general, outputs="text_box_output")
125
-
126
- with gr.Row():
127
- btn_skip_downloaded = gr.Button("Skip Downloaded Files")
128
- btn_skip_downloaded.click(skip_downloaded_files, inputs=url_general, outputs="text_box_output")
129
-
130
- with gr.Row():
131
- urls = gr.Textbox(label="Multiple URLs (comma-separated)")
132
- btn_multiple_files = gr.Button("Download Multiple Files")
133
- btn_multiple_files.click(download_multiple_files, inputs=urls, outputs="text_box_output")
134
-
135
- with gr.Row():
136
- btn_chapters = gr.Button("Download with Chapters")
137
- btn_chapters.click(download_with_chapters, inputs=url_general, outputs="text_box_output")
138
-
139
- with gr.Row():
140
- start_time = gr.Textbox(label="Start Time (e.g., 00:01:00)")
141
- end_time = gr.Textbox(label="End Time (e.g., 00:05:00)")
142
- btn_extract_portion = gr.Button("Extract Portion")
143
- btn_extract_portion.click(extract_portion, inputs=[url_general, start_time, end_time], outputs="text_box_output")
144
-
145
- with gr.Row():
146
- btn_update_metadata = gr.Button("Update Metadata")
147
- btn_update_metadata.click(update_metadata, inputs=url_general, outputs="text_box_output")
148
-
149
- with gr.Row():
150
- btn_auto_rename = gr.Button("Auto-Rename Duplicates")
151
- btn_auto_rename.click(auto_rename_duplicates, inputs=url_general, outputs="text_box_output")
152
-
153
- with gr.Row():
154
- url_list = gr.Textbox(label="URL List File Path")
155
- btn_url_list = gr.Button("Download from URL List")
156
- btn_url_list.click(download_from_url_list, inputs=url_list, outputs="text_box_output")
157
-
158
- with gr.Row():
159
- speed_limit = gr.Textbox(label="Download Speed (e.g., 1M)")
160
- btn_limit_speed = gr.Button("Limit Download Speed")
161
- btn_limit_speed.click(limit_download_speed, inputs=[url_general, speed_limit], outputs="text_box_output")
162
-
163
- with gr.Row():
164
- transcript_format = gr.Dropdown(["text", "markdown"], label="Transcript Format")
165
- btn_transcript = gr.Button("Download Transcript")
166
- btn_transcript.click(download_youtube_transcript, inputs=[url_general, transcript_format], outputs="text_box_output")
167
-
168
- with gr.Row():
169
- btn_video_info = gr.Button("Download Video Info")
170
- btn_video_info.click(download_video_info, inputs=url_general, outputs="text_box_output")
171
-
172
- with gr.Row():
173
- youtube_username = gr.Textbox(label="YouTube Username")
174
- youtube_password = gr.Textbox(label="YouTube Password", type="password")
175
- btn_age_restricted = gr.Button("Download Age-Restricted Content")
176
- btn_age_restricted.click(download_age_restricted_content, inputs=[url_general, youtube_username, youtube_password], outputs="text_box_output")
177
 
178
- text_box_output = gr.Textbox(label="Output")
 
 
 
 
 
179
 
180
- # Launch the Gradio app
181
  demo.launch()
 
1
  import gradio as gr
2
+ import subprocess
3
+ import shlex
4
 
5
+ def run_command(command):
6
+ """
7
+ Executes a shell command and returns its output.
8
+ """
9
  try:
10
+ # Use shlex to split the command for better security
11
+ result = subprocess.run(shlex.split(command), capture_output=True, text=True)
12
+ if result.stdout:
13
+ return result.stdout
14
+ elif result.stderr:
15
+ return result.stderr
16
+ else:
17
+ return "No output received."
18
  except Exception as e:
19
+ return str(e)
20
 
21
+ def escape_quotes(text):
22
+ """
23
+ Escapes double quotes in user input to prevent command injection.
24
+ """
25
+ return text.replace('"', '\\"')
26
 
27
+ # Define the commands
28
+ general_commands = [
29
+ {
30
+ "title": "List Available Formats",
31
+ "inputs": [
32
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here")
33
+ ],
34
+ "command": lambda url: f'yt-dlp -F "{escape_quotes(url)}"'
35
+ },
36
+ {
37
+ "title": "Download MP3 at Max Quality",
38
+ "inputs": [
39
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
40
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
41
+ ],
42
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --postprocessor-args "-b:a 320k" -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
43
+ },
44
+ {
45
+ "title": "Basic High-Quality MP3 Download",
46
+ "inputs": [
47
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
48
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
49
+ ],
50
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
51
+ },
52
+ {
53
+ "title": "Download Custom Bitrate",
54
+ "inputs": [
55
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
56
+ gr.Textbox(label="Bitrate", placeholder='192k', value='192k'),
57
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
58
+ ],
59
+ "command": lambda url, bitrate, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --postprocessor-args "-b:a {escape_quotes(bitrate)}" -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
60
+ },
61
+ {
62
+ "title": "Download and Add Metadata Tags",
63
+ "inputs": [
64
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
65
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
66
+ ],
67
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --embed-metadata -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
68
+ },
69
+ {
70
+ "title": "Download Entire Playlist",
71
+ "inputs": [
72
+ gr.Textbox(label="Playlist URL", placeholder="Enter the playlist URL here"),
73
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(playlist_title)s/%(title)s.%(ext)s', value='P:/Local Music/%(playlist_title)s/%(title)s.%(ext)s')
74
+ ],
75
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
76
+ },
77
+ {
78
+ "title": "Download Playlist (Specific Range)",
79
+ "inputs": [
80
+ gr.Textbox(label="Playlist URL", placeholder="Enter the playlist URL here"),
81
+ gr.Textbox(label="Playlist Items", placeholder='e.g., 1-5', value='1-5'),
82
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(playlist_title)s/%(title)s.%(ext)s', value='P:/Local Music/%(playlist_title)s/%(title)s.%(ext)s')
83
+ ],
84
+ "command": lambda url, items, path: f'yt-dlp --playlist-items {escape_quotes(items)} -f bestaudio --extract-audio --audio-format mp3 -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
85
+ },
86
+ {
87
+ "title": "Embed Album Art Automatically",
88
+ "inputs": [
89
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
90
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
91
+ ],
92
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --embed-thumbnail --audio-quality 0 -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
93
+ },
94
+ {
95
+ "title": "Download Specific Formats (Opus)",
96
+ "inputs": [
97
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
98
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
99
+ ],
100
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format opus -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
101
+ },
102
+ {
103
+ "title": "Skip Already Downloaded Files",
104
+ "inputs": [
105
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
106
+ gr.Textbox(label="Download Archive Path", placeholder='P:/Local Music/downloaded.txt', value='P:/Local Music/downloaded.txt'),
107
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
108
+ ],
109
+ "command": lambda url, archive, path: f'yt-dlp --download-archive "{escape_quotes(archive)}" -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
110
+ },
111
+ {
112
+ "title": "Download Multiple Individual Files",
113
+ "inputs": [
114
+ gr.Textbox(label="Video URLs", placeholder='Enter multiple URLs separated by spaces', lines=2),
115
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
116
+ ],
117
+ "command": lambda urls, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --add-metadata --embed-thumbnail --write-description --postprocessor-args "-b:a 320k" -o "{escape_quotes(path)}" {" ".join([f\'"{escape_quotes(url)}"\' for url in urls.split()])}'
118
+ },
119
+ {
120
+ "title": "Download and Automatically Split by Chapters",
121
+ "inputs": [
122
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
123
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
124
+ ],
125
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --split-chapters -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
126
+ },
127
+ {
128
+ "title": "Extract Only a Portion of a Video (by Time)",
129
+ "inputs": [
130
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
131
+ gr.Textbox(label="Start Time", placeholder='00:01:00', value='00:01:00'),
132
+ gr.Textbox(label="End Time", placeholder='00:05:00', value='00:05:00'),
133
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
134
+ ],
135
+ "command": lambda url, start, end, path: f'yt-dlp -f bestvideo+bestaudio --external-downloader ffmpeg --external-downloader-args "ffmpeg_i:-ss {escape_quotes(start)} -to {escape_quotes(end)}" -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
136
+ },
137
+ {
138
+ "title": "Update Metadata of Existing Files",
139
+ "inputs": [
140
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
141
+ gr.Textbox(label="Download Archive Path", placeholder='P:/Local Music/downloaded.txt', value='P:/Local Music/downloaded.txt')
142
+ ],
143
+ "command": lambda url, archive: f'yt-dlp --download-archive "{escape_quotes(archive)}" --skip-download --embed-metadata --embed-thumbnail --write-description "{escape_quotes(url)}"'
144
+ },
145
+ {
146
+ "title": "Auto-Rename Duplicate Files",
147
+ "inputs": [
148
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
149
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
150
+ ],
151
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --force-overwrites -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
152
+ },
153
+ {
154
+ "title": "Download from a URL List File",
155
+ "inputs": [
156
+ gr.Textbox(label="URL List File Path", placeholder='P:/Local Music/urls.txt', value='P:/Local Music/urls.txt'),
157
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
158
+ ],
159
+ "command": lambda list_file, path: f'yt-dlp -a "{escape_quotes(list_file)}" -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o "{escape_quotes(path)}"'
160
+ },
161
+ {
162
+ "title": "Download and Limit Download Speed",
163
+ "inputs": [
164
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
165
+ gr.Textbox(label="Rate Limit", placeholder='1M', value='1M'),
166
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
167
+ ],
168
+ "command": lambda url, rate, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --rate-limit {escape_quotes(rate)} -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
169
+ },
170
+ {
171
+ "title": "Download YouTube Transcript as Text",
172
+ "inputs": [
173
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
174
+ gr.Textbox(label="Subtitle Language", placeholder='en', value='en'),
175
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
176
+ ],
177
+ "command": lambda url, lang, path: f'yt-dlp --write-auto-subs --sub-lang {escape_quotes(lang)} --skip-download -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
178
+ },
179
+ {
180
+ "title": "Download YouTube Transcript as Markdown",
181
+ "inputs": [
182
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
183
+ gr.Textbox(label="Subtitle Language", placeholder='en', value='en'),
184
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.md', value='P:/Local Music/%(title)s.md')
185
+ ],
186
+ "command": lambda url, lang, path: f'yt-dlp --write-auto-subs --sub-lang {escape_quotes(lang)} --skip-download --convert-subs srt -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
187
+ },
188
+ {
189
+ "title": "Download Video Info and Save as JSON",
190
+ "inputs": [
191
+ gr.Textbox(label="Video URL", placeholder="Enter the video URL here"),
192
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.json', value='P:/Local Music/%(title)s.json')
193
+ ],
194
+ "command": lambda url, path: f'yt-dlp --write-info-json --skip-download -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
195
+ },
196
+ {
197
+ "title": "Download from YouTube Age-Restricted Content",
198
+ "inputs": [
199
+ gr.Textbox(label="Age-Restricted Video URL", placeholder="Enter the video URL here"),
200
+ gr.Textbox(label="YouTube Email", placeholder="Enter your YouTube email"),
201
+ gr.Password(label="YouTube Password", placeholder="Enter your YouTube password"),
202
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/%(title)s.%(ext)s', value='P:/Local Music/%(title)s.%(ext)s')
203
+ ],
204
+ "command": lambda url, email, password, path: f'yt-dlp --username "{escape_quotes(email)}" --password "{escape_quotes(password)}" -f bestvideo+bestaudio -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
205
+ },
206
+ ]
207
 
208
+ soundcloud_commands = [
209
+ {
210
+ "title": "List Available Formats",
211
+ "inputs": [
212
+ gr.Textbox(label="SoundCloud URL", placeholder="Enter the SoundCloud URL here")
213
+ ],
214
+ "command": lambda url: f'yt-dlp -F "{escape_quotes(url)}"'
215
+ },
216
+ {
217
+ "title": "Download High-Quality MP3 from SoundCloud",
218
+ "inputs": [
219
+ gr.Textbox(label="SoundCloud Track URL", placeholder="Enter the SoundCloud track URL here"),
220
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s')
221
+ ],
222
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
223
+ },
224
+ {
225
+ "title": "Download HQ with Metadata from SoundCloud",
226
+ "inputs": [
227
+ gr.Textbox(label="SoundCloud Track URL", placeholder="Enter the SoundCloud track URL here"),
228
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s')
229
+ ],
230
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --embed-metadata -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
231
+ },
232
+ {
233
+ "title": "Download Entire Playlist from SoundCloud",
234
+ "inputs": [
235
+ gr.Textbox(label="SoundCloud Playlist URL", placeholder="Enter the SoundCloud playlist URL here"),
236
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(playlist_title)s/%(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(playlist_title)s/%(title)s.%(ext)s')
237
+ ],
238
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
239
+ },
240
+ {
241
+ "title": "Download Entire Playlist from SoundCloud with Metadata",
242
+ "inputs": [
243
+ gr.Textbox(label="SoundCloud Playlist URL", placeholder="Enter the SoundCloud playlist URL here"),
244
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(playlist_title)s/%(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(playlist_title)s/%(title)s.%(ext)s')
245
+ ],
246
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --embed-metadata --add-metadata --embed-thumbnail -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
247
+ },
248
+ {
249
+ "title": "Download Multiple Playlists with Metadata",
250
+ "inputs": [
251
+ gr.Textbox(label="SoundCloud Playlist URLs", placeholder='Enter multiple playlist URLs separated by spaces', lines=2),
252
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(playlist_title)s/%(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(playlist_title)s/%(title)s.%(ext)s')
253
+ ],
254
+ "command": lambda urls, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --embed-metadata --add-metadata --embed-thumbnail -o "{escape_quotes(path)}" {" ".join([f\'"{escape_quotes(url)}"\' for url in urls.split()])}'
255
+ },
256
+ {
257
+ "title": "Download Playlist with Specific Range",
258
+ "inputs": [
259
+ gr.Textbox(label="SoundCloud Playlist URL", placeholder="Enter the SoundCloud playlist URL here"),
260
+ gr.Textbox(label="Playlist Items", placeholder='e.g., 1-5', value='1-5'),
261
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(playlist_title)s/%(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(playlist_title)s/%(title)s.%(ext)s')
262
+ ],
263
+ "command": lambda url, items, path: f'yt-dlp --playlist-items {escape_quotes(items)} -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
264
+ },
265
+ {
266
+ "title": "Download and Embed Album Art",
267
+ "inputs": [
268
+ gr.Textbox(label="SoundCloud Track URL", placeholder="Enter the SoundCloud track URL here"),
269
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s')
270
+ ],
271
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --embed-thumbnail -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
272
+ },
273
+ {
274
+ "title": "Skip Downloading Already Downloaded SoundCloud Files",
275
+ "inputs": [
276
+ gr.Textbox(label="SoundCloud Track URL", placeholder="Enter the SoundCloud track URL here"),
277
+ gr.Textbox(label="Download Archive Path", placeholder='P:/Local Music/downloaded_soundcloud.txt', value='P:/Local Music/downloaded_soundcloud.txt'),
278
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s')
279
+ ],
280
+ "command": lambda url, archive, path: f'yt-dlp --download-archive "{escape_quotes(archive)}" -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
281
+ },
282
+ {
283
+ "title": "Download Multiple Tracks from SoundCloud",
284
+ "inputs": [
285
+ gr.Textbox(label="SoundCloud Track URLs", placeholder='Enter multiple track URLs separated by spaces', lines=2),
286
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s')
287
+ ],
288
+ "command": lambda urls, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o "{escape_quotes(path)}" {" ".join([f\'"{escape_quotes(url)}"\' for url in urls.split()])}'
289
+ },
290
+ {
291
+ "title": "Limit Download Speed for SoundCloud",
292
+ "inputs": [
293
+ gr.Textbox(label="SoundCloud Track URL", placeholder="Enter the SoundCloud track URL here"),
294
+ gr.Textbox(label="Rate Limit", placeholder='1M', value='1M'),
295
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s')
296
+ ],
297
+ "command": lambda url, rate, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --rate-limit {escape_quotes(rate)} -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
298
+ },
299
+ {
300
+ "title": "Download from SoundCloud and Split by Chapters (if available)",
301
+ "inputs": [
302
+ gr.Textbox(label="SoundCloud Track URL", placeholder="Enter the SoundCloud track URL here"),
303
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s')
304
+ ],
305
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --split-chapters -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
306
+ },
307
+ {
308
+ "title": "Download SoundCloud Track and Extract a Specific Portion",
309
+ "inputs": [
310
+ gr.Textbox(label="SoundCloud Track URL", placeholder="Enter the SoundCloud track URL here"),
311
+ gr.Textbox(label="Start Time", placeholder='00:01:00', value='00:01:00'),
312
+ gr.Textbox(label="End Time", placeholder='00:05:00', value='00:05:00'),
313
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s')
314
+ ],
315
+ "command": lambda url, start, end, path: f'yt-dlp -f bestaudio --external-downloader ffmpeg --external-downloader-args "ffmpeg_i:-ss {escape_quotes(start)} -to {escape_quotes(end)}" -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
316
+ },
317
+ {
318
+ "title": "Update Metadata of Existing SoundCloud Downloads",
319
+ "inputs": [
320
+ gr.Textbox(label="SoundCloud Track URL", placeholder="Enter the SoundCloud track URL here"),
321
+ gr.Textbox(label="Download Archive Path", placeholder='P:/Local Music/downloaded_soundcloud.txt', value='P:/Local Music/downloaded_soundcloud.txt')
322
+ ],
323
+ "command": lambda url, archive: f'yt-dlp --download-archive "{escape_quotes(archive)}" --skip-download --embed-metadata --embed-thumbnail "{escape_quotes(url)}"'
324
+ },
325
+ {
326
+ "title": "Auto-Rename Duplicate SoundCloud Files",
327
+ "inputs": [
328
+ gr.Textbox(label="SoundCloud Track URL", placeholder="Enter the SoundCloud track URL here"),
329
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s')
330
+ ],
331
+ "command": lambda url, path: f'yt-dlp -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 --force-overwrites -o "{escape_quotes(path)}" "{escape_quotes(url)}"'
332
+ },
333
+ {
334
+ "title": "Download from SoundCloud URL List File",
335
+ "inputs": [
336
+ gr.Textbox(label="SoundCloud URL List File Path", placeholder='P:/Local Music/soundcloud_urls.txt', value='P:/Local Music/soundcloud_urls.txt'),
337
+ gr.Textbox(label="Output Path", placeholder='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s', value='P:/Local Music/SoundCloud/%(uploader)s - %(title)s.%(ext)s')
338
+ ],
339
+ "command": lambda list_file, path: f'yt-dlp -a "{escape_quotes(list_file)}" -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o "{escape_quotes(path)}"'
340
+ },
341
+ ]
342
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  with gr.Blocks() as demo:
344
+ gr.Markdown("# YT-DLP GUI using Gradio 🚀")
345
+ gr.Markdown(
346
+ """
347
+ This application provides a user-friendly interface to execute various `yt-dlp` commands.
348
+ Select a command from the **General Commands** or **SoundCloud Commands** tabs and provide the necessary inputs.
349
+ """
350
+ )
351
 
352
  with gr.Tab("General Commands"):
353
+ for cmd in general_commands:
354
+ with gr.Accordion(cmd["title"], open=False):
355
+ input_components = cmd["inputs"]
356
+ output = gr.Textbox(label="Command Output", lines=10)
357
+ execute_button = gr.Button("Execute")
358
+
359
+ execute_button.click(
360
+ run_command,
361
+ inputs=[inp for inp in input_components],
362
+ outputs=output,
363
+ _js=None,
364
+ fn=lambda *args, cmd=cmd: cmd["command"](*args)
365
+ )
366
+
367
+ with gr.Tab("SoundCloud Commands"):
368
+ for cmd in soundcloud_commands:
369
+ with gr.Accordion(cmd["title"], open=False):
370
+ input_components = cmd["inputs"]
371
+ output = gr.Textbox(label="Command Output", lines=10)
372
+ execute_button = gr.Button("Execute")
373
+
374
+ execute_button.click(
375
+ run_command,
376
+ inputs=[inp for inp in input_components],
377
+ outputs=output,
378
+ _js=None,
379
+ fn=lambda *args, cmd=cmd: cmd["command"](*args)
380
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
 
382
+ gr.Markdown(
383
+ """
384
+ ---
385
+ **Disclaimer:** Use this tool responsibly. Ensure you have the right to download and convert content. Respect copyright laws and platform terms of service.
386
+ """
387
+ )
388
 
 
389
  demo.launch()