File size: 6,040 Bytes
3c15f87
6f318d3
 
 
 
 
50dc6d8
 
 
 
1c9e038
50dc6d8
6f318d3
 
50dc6d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1c9e038
 
 
 
 
 
 
 
50dc6d8
1c9e038
50dc6d8
1c9e038
50dc6d8
1c9e038
 
 
 
 
 
 
 
 
 
 
50dc6d8
6f318d3
 
50dc6d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1c9e038
 
 
50dc6d8
1c9e038
50dc6d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1c9e038
50dc6d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3c15f87
 
 
 
 
 
 
 
 
 
6f318d3
50dc6d8
3c15f87
50dc6d8
6f318d3
3c15f87
 
6f318d3
3c15f87
 
6f318d3
50dc6d8
6f318d3
a383192
50dc6d8
3c15f87
50dc6d8
3c15f87
 
50dc6d8
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
import gradio as gr
import requests
from pydub import AudioSegment
import shazamio
import os
import time
import tempfile
from pathlib import Path
import sys
import asyncio

# Replace with your actual client ID and client secret
client_id = os.environ.get('SOUNDCLOUD_CLIENT_ID')
client_secret = os.environ.get('SOUNDCLOUD_CLIENT_SECRET')
token = os.environ.get('TOKEN')

def get_soundcloud_access_token(client_id, client_secret):
    try:
        auth_string = f'{client_id}:{client_secret}'
        auth_headers = {
            'Authorization': 'Basic ' + base64.b64encode(auth_string.encode()).decode()
        }
        data = {
            'grant_type': 'client_credentials'
        }
        response = requests.post('https://api.soundcloud.com/oauth2/token', headers=auth_headers, data=data)
        if response.status_code == 200:
            token_data = response.json()
            return token_data['access_token']
        else:
            raise Exception(f"Failed to obtain access token: {response.text}")
    except Exception as e:
        return f"Error obtaining access token: {str(e)}"

def download_audio(streaming_url, output_path, headers):
    try:
        response = requests.get(streaming_url, headers=headers, stream=True)
        with open(output_path, 'wb') as f:
            for chunk in response.iter_content(chunk_size=8192):
                f.write(chunk)
    except Exception as e:
        raise Exception(f"Error downloading audio: {str(e)}")

async def identify_track(shazam, audio_chunk, temp_dir):
    try:
        temp_file = os.path.join(temp_dir, 'temp_chunk.wav')
        audio_chunk.export(temp_file, format='wav')
        result = await shazam.recognize_file(temp_file)
        if result and 'track' in result:
            track_data = result['track']
            return {
                'title': track_data['title'],
                'subtitle': track_data['subtitle']
            }
        else:
            return None
    except Exception as e:
        return f"Error identifying track: {str(e)}"

async def process_dj_set(track_url, progress=gr.Progress()):
    temp_dir = "/tmp"
    output_path = os.path.join(temp_dir, 'track.wav')
    tracklist_path = os.path.join(temp_dir, 'tracklist.txt')
    status_messages = []

    # Check environment variables
    if not client_id or not client_secret or not token:
        return "", "", "Environment variables not set."

    # Get access token
    access_token = get_soundcloud_access_token(client_id, client_secret)
    if isinstance(access_token, str) and access_token.startswith("Error"):
        return "", "", access_token

    headers = {
        'Authorization': f'Bearer {access_token}'
    }

    # Resolve track URL
    try:
        resolve_response = requests.get(f'https://api.soundcloud.com/resolve.json?url={track_url}', headers=headers)
        if resolve_response.status_code != 200:
            return "", "", f"Failed to resolve track URL: {resolve_response.text}"
        track_data = resolve_response.json()
        streaming_url = track_data['stream_url']
        status_messages.append("Track URL resolved successfully.")
    except Exception as e:
        return "", "", f"Error resolving track URL: {str(e)}"

    # Download audio
    try:
        download_audio(streaming_url, output_path, headers)
        status_messages.append("Audio downloaded successfully.")
    except Exception as e:
        return "", "", f"Error downloading audio: {str(e)}"

    # Load audio
    try:
        audio = AudioSegment.from_wav(output_path)
        status_messages.append("Audio loaded successfully.")
    except Exception as e:
        return "", "", f"Error loading audio: {str(e)}"

    # Split audio into chunks
    chunk_duration = 30000  # 30 seconds
    overlap = 10000  # 10 seconds
    chunks = []
    start = 0
    while start + chunk_duration < len(audio):
        end = start + chunk_duration
        chunk = audio[start:end]
        chunks.append((start, chunk))
        start += chunk_duration - overlap

    # Initialize Shazam
    shazam = shazamio.Shazam()

    # Identify tracks
    tracklist = []
    for start_time, chunk in chunks:
        progress(0.1)
        track_info = await identify_track(shazam, chunk, temp_dir)
        if isinstance(track_info, dict):
            timestamp = time.strftime("%M:%S", time.gmtime(start_time / 1000))
            tracklist.append(f"{timestamp} - {track_info['title']} by {track_info['subtitle']}")
        elif isinstance(track_info, str):
            status_messages.append(track_info)

    # Prepare tracklist output
    tracklist_output = "\n".join(tracklist)
    with open(tracklist_path, 'w') as f:
        f.write(tracklist_output)

    # Clean up temporary directory
    import shutil
    shutil.rmtree(temp_dir)

    # Prepare status message
    status_message = "\n".join(status_messages)
    if not tracklist:
        status_message += "\nNo tracks identified."

    return tracklist_output, tracklist_path, status_message

css = """
#col-container {
    margin: 0 auto;
    max-width: 640px;
}
"""

with gr.Blocks(css=css) as demo:
    with gr.Column(elem_id="col-container"):
        gr.Markdown("# SoundCloud DJ Set Track Identifier")
        status_text = gr.Markdown(elem_id="status_text")
        with gr.Row():
            track_url = gr.Text(
                label="SoundCloud DJ Set URL",
                show_label=False,
                max_lines=1,
                placeholder="Enter SoundCloud DJ set URL",
                container=False,
            )
            run_button = gr.Button("Process", scale=0, variant="primary")
        result = gr.Textbox(label="Tracklist", show_label=False)
        with gr.Accordion("Download Tracklist", open=False):
            download_button = gr.File(label="Download")
        gr.Examples(examples=["https://soundcloud.com/your-track-url"], inputs=[track_url])

    run_button.click(process_dj_set, inputs=track_url, outputs=[result, download_button, status_text])

if __name__ == "__main__":
    demo.launch()