import gradio as gr from yt_dlp import YoutubeDL import tempfile import os import subprocess def download_snippet(url, duration_sec): """Download and trim audio snippet""" # Create temp directory temp_dir = tempfile.mkdtemp() try: # First, download the full track (or best we can get) ydl_opts = { 'format': 'bestaudio/best', 'outtmpl': os.path.join(temp_dir, 'full_audio.%(ext)s'), 'quiet': True, 'no_warnings': True, 'noplaylist': True, } with YoutubeDL(ydl_opts) as ydl: # Get info for filename info = ydl.extract_info(url, download=False) title = info.get('title', 'soundcloud_track') safe_title = "".join(c for c in title if c.isalnum() or c in (' ', '-', '_')).rstrip() # Download ydl.download([url]) # Find the downloaded file downloaded_files = [f for f in os.listdir(temp_dir) if f.startswith('full_audio')] if not downloaded_files: raise Exception("No file was downloaded") input_file = os.path.join(temp_dir, downloaded_files[0]) # Check if file exists and has content if not os.path.exists(input_file) or os.path.getsize(input_file) == 0: raise Exception("Downloaded file is empty") # Create output filename output_file = os.path.join(temp_dir, f"{safe_title}_{duration_sec}s.mp3") # Use ffmpeg to trim (this is the key fix!) cmd = [ 'ffmpeg', '-i', input_file, # Input file '-t', str(duration_sec), # Duration to keep '-acodec', 'libmp3lame', # MP3 codec '-q:a', '2', # Good quality '-y', # Overwrite output output_file ] # Run ffmpeg result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: raise Exception(f"FFmpeg error: {result.stderr}") # Check if output was created if not os.path.exists(output_file) or os.path.getsize(output_file) == 0: raise Exception("Trimmed file is empty") return output_file, f"{safe_title}_{duration_sec}s.mp3" except Exception as e: # Clean up on error if os.path.exists(temp_dir): import shutil shutil.rmtree(temp_dir, ignore_errors=True) raise e # Simple Gradio interface with gr.Blocks(title="SoundCloud Snippet", theme=gr.themes.Soft()) as demo: gr.Markdown(""" # 🎵 SoundCloud Snippet Downloader Download the first N seconds of any public SoundCloud track """) with gr.Row(): url = gr.Textbox( label="SoundCloud URL", placeholder="https://soundcloud.com/artist/track-name", value="https://soundcloud.com/emma-eline-pihlstr-m/have-yourself-a-merry-little-christmas", lines=2 ) with gr.Row(): duration = gr.Slider( minimum=5, maximum=400, value=30, step=5, label="Duration (seconds)" ) with gr.Row(): download_btn = gr.Button("Download Snippet", variant="primary") with gr.Row(): audio_player = gr.Audio(label="Preview", type="filepath") download_file = gr.DownloadButton("Save MP3", visible=False) # Store file path file_path = gr.State() def process_download(url, duration): if not url or 'soundcloud.com' not in url.lower(): raise gr.Error("Please enter a valid SoundCloud URL") try: filepath, filename = download_snippet(url, duration) return { audio_player: filepath, download_file: gr.DownloadButton(visible=True), file_path: filepath } except Exception as e: raise gr.Error(f"Download failed: {str(e)}") download_btn.click( process_download, inputs=[url, duration], outputs=[audio_player, download_file, file_path] ) download_file.click( lambda x: x if x and os.path.exists(x) else None, inputs=[file_path], outputs=None ) if __name__ == "__main__": demo.launch()