File size: 4,476 Bytes
26b7f05
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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()