MySafeCode commited on
Commit
4d325e4
·
verified ·
1 Parent(s): 1410447

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +22 -206
app.py CHANGED
@@ -1,217 +1,33 @@
1
  import gradio as gr
2
- from yt_dlp import YoutubeDL
3
  import tempfile
4
  import os
5
- import shutil
6
 
7
- def download_snippet(url, duration_sec):
8
- # Create temporary directory for better file management
9
- temp_dir = tempfile.mkdtemp()
10
-
11
- # Generate a more descriptive filename
12
- try:
13
- with YoutubeDL({"quiet": True, "no_warnings": True}) as ydl:
14
- info = ydl.extract_info(url, download=False)
15
- # Create a safe filename from title
16
- safe_title = "".join(c for c in info.get('title', 'audio') if c.isalnum() or c in (' ', '-', '_')).rstrip()
17
- filename = f"{safe_title}_{duration_sec}s.mp3"
18
- except:
19
- filename = f"soundcloud_snippet_{duration_sec}s.mp3"
20
-
21
- output_path = os.path.join(temp_dir, filename)
22
 
23
  ydl_opts = {
24
- "format": "bestaudio/best",
25
- "outtmpl": output_path,
26
- "external_downloader": "ffmpeg",
27
- "external_downloader_args": ["-t", str(int(duration_sec))],
28
- "quiet": True,
29
- "no_warnings": True,
30
- "postprocessors": [{
31
- "key": "FFmpegExtractAudio",
32
- "preferredcodec": "mp3",
33
- "preferredquality": "192",
34
- }],
35
  }
36
-
37
- try:
38
- with YoutubeDL(ydl_opts) as ydl:
39
- ydl.download([url])
40
-
41
- # Verify file was created and has content
42
- if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
43
- return output_path, filename
44
- else:
45
- raise Exception("Download failed - empty file")
46
-
47
- except Exception as e:
48
- # Clean up on error
49
- if os.path.exists(temp_dir):
50
- shutil.rmtree(temp_dir, ignore_errors=True)
51
- raise gr.Error(f"Download failed: {str(e)}")
52
-
53
- def cleanup_temp_files(filepath):
54
- """Clean up temporary files after download"""
55
- if filepath and os.path.exists(os.path.dirname(filepath)):
56
- temp_dir = os.path.dirname(filepath)
57
- try:
58
- shutil.rmtree(temp_dir, ignore_errors=True)
59
- except:
60
- pass
61
-
62
- with gr.Blocks(title="SoundCloud Snippet Generator", theme=gr.themes.Soft()) as demo:
63
- gr.Markdown("""
64
- # 🎵 SoundCloud Snippet Generator
65
- Download only the first *N seconds* of any SoundCloud track.
66
- """)
67
-
68
- with gr.Row():
69
- with gr.Column(scale=3):
70
- url = gr.Textbox(
71
- label="SoundCloud URL",
72
- placeholder="https://soundcloud.com/...",
73
- value="https://soundcloud.com/antonio-antetomaso/mutiny-on-the-bounty-closing-titles-cover"
74
- )
75
-
76
- with gr.Row():
77
- duration = gr.Slider(
78
- minimum=1,
79
- maximum=300,
80
- value=30,
81
- step=1,
82
- label="Snippet length (seconds)"
83
- )
84
- duration_text = gr.Number(
85
- value=30,
86
- label="Seconds",
87
- precision=0,
88
- minimum=1,
89
- maximum=300
90
- )
91
-
92
- gr.Markdown("### Output")
93
- filename_display = gr.Textbox(
94
- label="Download as",
95
- interactive=False
96
- )
97
-
98
- download_btn = gr.DownloadButton(
99
- "Download MP3 File",
100
- visible=False
101
- )
102
-
103
- generate_btn = gr.Button(
104
- "Generate Snippet",
105
- variant="primary",
106
- size="lg"
107
- )
108
-
109
- status = gr.Textbox(
110
- label="Status",
111
- interactive=False,
112
- visible=False
113
- )
114
-
115
- with gr.Column(scale=2):
116
- audio_player = gr.Audio(
117
- label="Preview",
118
- type="filepath",
119
- interactive=False
120
- )
121
-
122
- # Link slider and number input
123
- duration.change(lambda x: x, inputs=[duration], outputs=[duration_text])
124
- duration_text.change(lambda x: x, inputs=[duration_text], outputs=[duration])
125
-
126
- # Store filename for download
127
- file_path_store = gr.State()
128
- file_name_store = gr.State()
129
-
130
- def process_and_preview(url, duration_sec):
131
- """Process the download and update UI"""
132
- if not url or not url.strip():
133
- raise gr.Error("Please enter a SoundCloud URL")
134
-
135
- # Clear previous
136
- yield "", None, None, "⏳ Downloading...", gr.DownloadButton(visible=False), gr.Textbox(visible=True)
137
-
138
- try:
139
- filepath, filename = download_snippet(url, duration_sec)
140
-
141
- yield (
142
- filename, # filename_display
143
- filepath, # file_path_store
144
- filename, # file_name_store
145
- "✅ Ready to download!", # status
146
- gr.DownloadButton(visible=True), # download_btn
147
- gr.Textbox(visible=True), # status visible
148
- )
149
-
150
- # Return audio preview
151
- return filepath
152
-
153
- except Exception as e:
154
- raise gr.Error(f"Error: {str(e)}")
155
-
156
- # Generate button click
157
- generate_btn.click(
158
- fn=process_and_preview,
159
- inputs=[url, duration],
160
- outputs=[
161
- filename_display,
162
- file_path_store,
163
- file_name_store,
164
- status,
165
- download_btn,
166
- status
167
- ]
168
- ).then(
169
- fn=lambda x: x,
170
- inputs=[file_path_store],
171
- outputs=[audio_player]
172
- )
173
-
174
- # Setup download button
175
- download_btn.click(
176
- fn=lambda filepath, filename: (filepath, filename) if filepath else None,
177
- inputs=[file_path_store, file_name_store],
178
- outputs=None
179
- )
180
 
181
- # Cleanup on new generation
182
- url.change(
183
- fn=lambda: (
184
- "", # Clear filename
185
- None, # Clear file_path_store
186
- None, # Clear file_name_store
187
- "", # Clear status
188
- gr.DownloadButton(visible=False), # Hide download
189
- gr.Textbox(visible=False), # Hide status box
190
- None # Clear audio player
191
- ),
192
- outputs=[
193
- filename_display,
194
- file_path_store,
195
- file_name_store,
196
- status,
197
- download_btn,
198
- status,
199
- audio_player
200
- ]
201
- )
202
 
203
- # Add footer with info
204
- gr.Markdown("""
205
- ---
206
- **Note:** Downloads are limited to 5 minutes (300 seconds) maximum.
207
- Files are temporarily stored and will be cleaned up after download.
208
- """)
209
 
210
- if __name__ == "__main__":
211
- demo.launch(
212
- server_name="0.0.0.0",
213
- server_port=7860,
214
- share=False,
215
- show_error=True
216
- )
 
 
 
217
 
 
 
1
  import gradio as gr
2
+ import yt_dlp
3
  import tempfile
4
  import os
 
5
 
6
+ def simple_download(url, duration):
7
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.mp3') as f:
8
+ output = f.name
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  ydl_opts = {
11
+ 'format': 'bestaudio',
12
+ 'outtmpl': output,
13
+ 'quiet': True,
14
+ 'postprocessor_args': ['-t', str(min(duration, 120))],
 
 
 
 
 
 
 
15
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
18
+ ydl.download([url])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ return output
 
 
 
 
 
21
 
22
+ iface = gr.Interface(
23
+ fn=simple_download,
24
+ inputs=[
25
+ gr.Textbox(label="SoundCloud URL"),
26
+ gr.Slider(5, 120, 30, label="Duration (seconds)")
27
+ ],
28
+ outputs=gr.Audio(type="filepath", label="Download"),
29
+ title="SoundCloud Snippet Downloader",
30
+ description="Download short snippets from SoundCloud (max 120 seconds)"
31
+ )
32
 
33
+ iface.launch()