rm-dev-null commited on
Commit
50dc6d8
·
verified ·
1 Parent(s): ab343a7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -82
app.py CHANGED
@@ -4,36 +4,48 @@ from pydub import AudioSegment
4
  import shazamio
5
  import os
6
  import time
 
 
 
 
7
 
8
- # Environment variables
9
- token = os.environ.get('TOKEN')
10
  client_id = os.environ.get('SOUNDCLOUD_CLIENT_ID')
11
  client_secret = os.environ.get('SOUNDCLOUD_CLIENT_SECRET')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- # Function to download audio
14
  def download_audio(streaming_url, output_path, headers):
15
  try:
16
  response = requests.get(streaming_url, headers=headers, stream=True)
17
- response.raise_for_status()
18
  with open(output_path, 'wb') as f:
19
  for chunk in response.iter_content(chunk_size=8192):
20
  f.write(chunk)
21
- return "Audio downloaded successfully."
22
  except Exception as e:
23
- return f"Error downloading audio: {e}"
24
 
25
- # Function to identify track using Shazam
26
- async def identify_track(shazam, audio_chunk):
27
  try:
28
- temp_file = 'temp_chunk.wav'
29
  audio_chunk.export(temp_file, format='wav')
30
-
31
- # Ensure temp_file exists and is not a directory
32
- if not os.path.isfile(temp_file):
33
- raise FileNotFoundError(f"Temporary file '{temp_file}' does not exist or is not a valid file.")
34
-
35
  result = await shazam.recognize_file(temp_file)
36
- os.remove(temp_file) # Clean up temporary file
37
  if result and 'track' in result:
38
  track_data = result['track']
39
  return {
@@ -43,70 +55,92 @@ async def identify_track(shazam, audio_chunk):
43
  else:
44
  return None
45
  except Exception as e:
46
- return f"Error identifying track: {e}"
47
 
48
- # Main processing function
49
  async def process_dj_set(track_url, progress=gr.Progress()):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  try:
51
- status = "Resolving SoundCloud URL..."
52
- headers = {'Authorization': f'Bearer {token}'}
53
  resolve_response = requests.get(f'https://api.soundcloud.com/resolve.json?url={track_url}', headers=headers)
54
-
55
  if resolve_response.status_code != 200:
56
- return "Failed to resolve track URL.", ""
57
-
58
  track_data = resolve_response.json()
59
- streaming_url = track_data.get('stream_url')
60
-
61
- if not streaming_url:
62
- return "Streaming URL not found.", ""
63
-
64
- status = "Downloading audio..."
65
- download_status = download_audio(streaming_url, 'track.wav', headers)
66
-
67
- if "Error" in download_status:
68
- return download_status, ""
69
-
70
- status = "Processing audio..."
71
-
72
- # Ensure 'track.wav' exists and is not a directory
73
- if not os.path.isfile('track.wav'):
74
- raise FileNotFoundError("Downloaded audio file 'track.wav' does not exist or is not valid.")
75
-
76
- audio = AudioSegment.from_wav('track.wav')
77
-
78
- chunk_duration = 30000 # 30 seconds
79
- overlap = 10000 # 10 seconds
80
-
81
- chunks = []
82
- start = 0
83
-
84
- while start + chunk_duration < len(audio):
85
- end = start + chunk_duration
86
- chunk = audio[start:end]
87
- chunks.append((start, chunk))
88
- start += chunk_duration - overlap
89
-
90
- shazam = shazamio.Shazam()
91
- tracklist = []
92
-
93
- for start_time, chunk in chunks:
94
- progress(0.1)
95
- track_info = await identify_track(shazam, chunk)
96
-
97
- if isinstance(track_info, str) and "Error" in track_info: # Check for errors in identification
98
- return track_info, ""
99
-
100
- if track_info:
101
- timestamp = time.strftime("%M:%S", time.gmtime(start_time / 1000))
102
- tracklist.append(f"{timestamp} - {track_info['title']} by {track_info['subtitle']}")
103
-
104
- status = "Generating output..."
105
- tracklist_output = "\n".join(tracklist)
106
-
107
- return tracklist_output, tracklist_output
108
  except Exception as e:
109
- return f"An error occurred during processing: {e}", ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
  css = """
112
  #col-container {
@@ -118,26 +152,22 @@ css = """
118
  with gr.Blocks(css=css) as demo:
119
  with gr.Column(elem_id="col-container"):
120
  gr.Markdown("# SoundCloud DJ Set Track Identifier")
121
-
122
  with gr.Row():
123
- track_url_input = gr.Text(
124
  label="SoundCloud DJ Set URL",
125
  show_label=False,
126
  max_lines=1,
127
  placeholder="Enter SoundCloud DJ set URL",
128
  container=False,
129
  )
130
-
131
  run_button = gr.Button("Process", scale=0, variant="primary")
132
-
133
- result_output = gr.Textbox(label="Tracklist", show_label=False)
134
-
135
  with gr.Accordion("Download Tracklist", open=False):
136
  download_button = gr.File(label="Download")
 
137
 
138
- gr.Examples(examples=["https://soundcloud.com/your-track-url"], inputs=[track_url_input])
139
-
140
- run_button.click(process_dj_set, inputs=track_url_input, outputs=[result_output, download_button])
141
 
142
  if __name__ == "__main__":
143
- demo.launch(share=False)
 
4
  import shazamio
5
  import os
6
  import time
7
+ import tempfile
8
+ from pathlib import Path
9
+ import sys
10
+ import asyncio
11
 
12
+ # Replace with your actual client ID and client secret
 
13
  client_id = os.environ.get('SOUNDCLOUD_CLIENT_ID')
14
  client_secret = os.environ.get('SOUNDCLOUD_CLIENT_SECRET')
15
+ token = os.environ.get('TOKEN')
16
+
17
+ def get_soundcloud_access_token(client_id, client_secret):
18
+ try:
19
+ auth_string = f'{client_id}:{client_secret}'
20
+ auth_headers = {
21
+ 'Authorization': 'Basic ' + base64.b64encode(auth_string.encode()).decode()
22
+ }
23
+ data = {
24
+ 'grant_type': 'client_credentials'
25
+ }
26
+ response = requests.post('https://api.soundcloud.com/oauth2/token', headers=auth_headers, data=data)
27
+ if response.status_code == 200:
28
+ token_data = response.json()
29
+ return token_data['access_token']
30
+ else:
31
+ raise Exception(f"Failed to obtain access token: {response.text}")
32
+ except Exception as e:
33
+ return f"Error obtaining access token: {str(e)}"
34
 
 
35
  def download_audio(streaming_url, output_path, headers):
36
  try:
37
  response = requests.get(streaming_url, headers=headers, stream=True)
 
38
  with open(output_path, 'wb') as f:
39
  for chunk in response.iter_content(chunk_size=8192):
40
  f.write(chunk)
 
41
  except Exception as e:
42
+ raise Exception(f"Error downloading audio: {str(e)}")
43
 
44
+ async def identify_track(shazam, audio_chunk, temp_dir):
 
45
  try:
46
+ temp_file = os.path.join(temp_dir, 'temp_chunk.wav')
47
  audio_chunk.export(temp_file, format='wav')
 
 
 
 
 
48
  result = await shazam.recognize_file(temp_file)
 
49
  if result and 'track' in result:
50
  track_data = result['track']
51
  return {
 
55
  else:
56
  return None
57
  except Exception as e:
58
+ return f"Error identifying track: {str(e)}"
59
 
 
60
  async def process_dj_set(track_url, progress=gr.Progress()):
61
+ temp_dir = "/tmp"
62
+ output_path = os.path.join(temp_dir, 'track.wav')
63
+ tracklist_path = os.path.join(temp_dir, 'tracklist.txt')
64
+ status_messages = []
65
+
66
+ # Check environment variables
67
+ if not client_id or not client_secret or not token:
68
+ return "", "", "Environment variables not set."
69
+
70
+ # Get access token
71
+ access_token = get_soundcloud_access_token(client_id, client_secret)
72
+ if isinstance(access_token, str) and access_token.startswith("Error"):
73
+ return "", "", access_token
74
+
75
+ headers = {
76
+ 'Authorization': f'Bearer {access_token}'
77
+ }
78
+
79
+ # Resolve track URL
80
  try:
 
 
81
  resolve_response = requests.get(f'https://api.soundcloud.com/resolve.json?url={track_url}', headers=headers)
 
82
  if resolve_response.status_code != 200:
83
+ return "", "", f"Failed to resolve track URL: {resolve_response.text}"
 
84
  track_data = resolve_response.json()
85
+ streaming_url = track_data['stream_url']
86
+ status_messages.append("Track URL resolved successfully.")
87
+ except Exception as e:
88
+ return "", "", f"Error resolving track URL: {str(e)}"
89
+
90
+ # Download audio
91
+ try:
92
+ download_audio(streaming_url, output_path, headers)
93
+ status_messages.append("Audio downloaded successfully.")
94
+ except Exception as e:
95
+ return "", "", f"Error downloading audio: {str(e)}"
96
+
97
+ # Load audio
98
+ try:
99
+ audio = AudioSegment.from_wav(output_path)
100
+ status_messages.append("Audio loaded successfully.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  except Exception as e:
102
+ return "", "", f"Error loading audio: {str(e)}"
103
+
104
+ # Split audio into chunks
105
+ chunk_duration = 30000 # 30 seconds
106
+ overlap = 10000 # 10 seconds
107
+ chunks = []
108
+ start = 0
109
+ while start + chunk_duration < len(audio):
110
+ end = start + chunk_duration
111
+ chunk = audio[start:end]
112
+ chunks.append((start, chunk))
113
+ start += chunk_duration - overlap
114
+
115
+ # Initialize Shazam
116
+ shazam = shazamio.Shazam()
117
+
118
+ # Identify tracks
119
+ tracklist = []
120
+ for start_time, chunk in chunks:
121
+ progress(0.1)
122
+ track_info = await identify_track(shazam, chunk, temp_dir)
123
+ if isinstance(track_info, dict):
124
+ timestamp = time.strftime("%M:%S", time.gmtime(start_time / 1000))
125
+ tracklist.append(f"{timestamp} - {track_info['title']} by {track_info['subtitle']}")
126
+ elif isinstance(track_info, str):
127
+ status_messages.append(track_info)
128
+
129
+ # Prepare tracklist output
130
+ tracklist_output = "\n".join(tracklist)
131
+ with open(tracklist_path, 'w') as f:
132
+ f.write(tracklist_output)
133
+
134
+ # Clean up temporary directory
135
+ import shutil
136
+ shutil.rmtree(temp_dir)
137
+
138
+ # Prepare status message
139
+ status_message = "\n".join(status_messages)
140
+ if not tracklist:
141
+ status_message += "\nNo tracks identified."
142
+
143
+ return tracklist_output, tracklist_path, status_message
144
 
145
  css = """
146
  #col-container {
 
152
  with gr.Blocks(css=css) as demo:
153
  with gr.Column(elem_id="col-container"):
154
  gr.Markdown("# SoundCloud DJ Set Track Identifier")
155
+ status_text = gr.Markdown(elem_id="status_text")
156
  with gr.Row():
157
+ track_url = gr.Text(
158
  label="SoundCloud DJ Set URL",
159
  show_label=False,
160
  max_lines=1,
161
  placeholder="Enter SoundCloud DJ set URL",
162
  container=False,
163
  )
 
164
  run_button = gr.Button("Process", scale=0, variant="primary")
165
+ result = gr.Textbox(label="Tracklist", show_label=False)
 
 
166
  with gr.Accordion("Download Tracklist", open=False):
167
  download_button = gr.File(label="Download")
168
+ gr.Examples(examples=["https://soundcloud.com/your-track-url"], inputs=[track_url])
169
 
170
+ run_button.click(process_dj_set, inputs=track_url, outputs=[result, download_button, status_text])
 
 
171
 
172
  if __name__ == "__main__":
173
+ demo.launch()