slslslrhfem commited on
Commit
a34f200
·
1 Parent(s): 5bb6d1f

change download mechanism

Browse files
Files changed (1) hide show
  1. app.py +137 -70
app.py CHANGED
@@ -9,6 +9,7 @@ import os
9
  import glob
10
  from pathlib import Path
11
  from huggingface_hub import snapshot_download
 
12
 
13
  token = os.getenv("HF_TOKEN")
14
 
@@ -26,37 +27,54 @@ install_madmom()
26
  sys.path.insert(0, '.')
27
  sys.path.insert(0, './ml_models')
28
 
29
- # Import inference - any error will bubble up
30
-
31
-
32
  def download_data_from_hub():
 
33
  base_dir = Path(".")
34
  data_repo_id = "mippia/music-data"
35
 
 
 
 
36
  folders_to_check = ["covers80", "ml_models"]
37
  downloaded_folders = {}
38
 
39
  # Check LFS file
40
  lfs_file = base_dir / "1005_e_4"
 
41
  if lfs_file.exists():
42
  file_size = lfs_file.stat().st_size / (1024*1024)
43
- print(f"LFS file 1005_e_4: {file_size:.1f} MB")
44
  downloaded_folders["1005_e_4"] = str(lfs_file)
45
  else:
46
- print("LFS file 1005_e_4 not found")
47
  downloaded_folders["1005_e_4"] = None
48
 
49
- # Check if folders exist
 
 
 
 
 
 
 
 
 
 
 
 
50
  all_folders_exist = all((base_dir / folder).exists() and any((base_dir / folder).iterdir())
51
  for folder in folders_to_check)
 
52
 
53
  if not all_folders_exist:
54
- print(f"Downloading data folders from dataset: {data_repo_id}")
55
 
56
  # Download to a temporary directory first
57
  temp_dir = base_dir / "temp_download"
 
58
  temp_dir.mkdir(exist_ok=True)
59
 
 
60
  downloaded_path = snapshot_download(
61
  repo_id=data_repo_id,
62
  repo_type="dataset",
@@ -66,37 +84,59 @@ def download_data_from_hub():
66
  ignore_patterns=["*.md", "*.txt", ".gitattributes", "README.md"]
67
  )
68
 
69
- print("Dataset downloaded successfully")
70
 
71
- # Move folders from temp_download to current directory
72
- import shutil
 
 
 
 
 
 
 
73
 
 
 
74
  for folder_name in folders_to_check:
75
  temp_folder_path = temp_dir / folder_name
76
  target_folder_path = base_dir / folder_name
77
 
 
 
 
 
 
78
  if temp_folder_path.exists():
 
79
  if target_folder_path.exists():
 
80
  shutil.rmtree(target_folder_path)
 
 
 
81
  shutil.move(str(temp_folder_path), str(target_folder_path))
82
- print(f"Moved {folder_name} to current directory")
83
 
84
- file_count = len([f for f in target_folder_path.rglob("*") if f.is_file()])
85
- print(f"{folder_name}: {file_count:,} files")
86
- downloaded_folders[folder_name] = str(target_folder_path)
 
 
 
 
 
87
  else:
88
- print(f"{folder_name} not found in downloaded data")
89
- # Check what's actually in temp directory
90
- print(f"Contents of temp directory:")
91
- for item in temp_dir.iterdir():
92
- print(f" {item.name}")
93
  downloaded_folders[folder_name] = None
94
 
95
  # Clean up temp directory
96
- shutil.rmtree(temp_dir)
 
 
 
97
 
98
  else:
99
- print("Data folders already exist locally")
100
  for folder_name in folders_to_check:
101
  folder_path = base_dir / folder_name
102
  if folder_path.exists():
@@ -106,8 +146,39 @@ def download_data_from_hub():
106
  else:
107
  downloaded_folders[folder_name] = None
108
 
 
 
 
 
 
109
  return downloaded_folders
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  def find_song_file_by_title(song_title):
112
  covers80_path = Path("covers80")
113
 
@@ -140,30 +211,28 @@ def find_song_file_by_title(song_title):
140
  def process_audio_for_matching(audio_file):
141
  if audio_file is None:
142
  return """
143
- <div style='text-align: center; color: #ef4444; padding: 30px; background: #fef2f2; border-radius: 12px; border: 2px dashed #fecaca;'>
144
  <h3>No Audio File</h3>
145
  <p>Please upload an audio file to get started!</p>
146
  </div>
147
  """
148
 
149
- # Call inference directly - any error will show up
150
- from inference import inference
151
  result = inference(audio_file)
152
 
153
  if result.get('message') != 'success':
154
  return f"""
155
- <div style="text-align: center; padding: 25px; background: #fef3c7; border-radius: 12px; border: 1px solid #fde68a; margin: 10px 0;">
156
- <h3 style="color: #92400e; margin-bottom: 15px;">No Matches Found</h3>
157
- <p style="color: #92400e; font-size: 1.1em;">{result.get('message', 'Unknown error occurred')}</p>
158
  </div>
159
  """
160
 
161
  matches = result.get('matches', [])
162
  if not matches:
163
  return """
164
- <div style="text-align: center; padding: 25px; background: #fef3c7; border-radius: 12px; border: 1px solid #fde68a; margin: 10px 0;">
165
- <h3 style="color: #92400e; margin-bottom: 15px;">No Matches Found</h3>
166
- <p style="color: #92400e; font-size: 1.1em;">No matching vocals found in database.</p>
167
  </div>
168
  """
169
 
@@ -177,7 +246,7 @@ def process_audio_for_matching(audio_file):
177
  library_time = match.get('library_time', 0)
178
 
179
  # Ranking colors
180
- rank_colors = {1: '#ef4444', 2: '#f97316', 3: '#22c55e'}
181
  rank_color = rank_colors.get(rank, '#6b7280')
182
 
183
  # Find song file
@@ -190,7 +259,7 @@ def process_audio_for_matching(audio_file):
190
  audio_player = f"""
191
  <div style="margin: 15px 0; padding: 15px; background: #f8fafc; border-radius: 8px;">
192
  <div style="text-align: center; margin-bottom: 10px;">
193
- <strong style="color: #1e293b;">Play matched vocal section</strong>
194
  </div>
195
  <audio controls preload="metadata" style="width: 100%;">
196
  <source src="file/{rel_song_path}#t={library_time:.1f}" type="audio/mpeg">
@@ -199,11 +268,11 @@ def process_audio_for_matching(audio_file):
199
  </audio>
200
  <div style="text-align: center; margin-top: 8px;">
201
  <button onclick="seekToTime(this.parentElement.previousElementSibling.querySelector('audio'), {library_time})"
202
- style="background: #3b82f6; color: white; border: none; padding: 5px 15px; border-radius: 6px; cursor: pointer; font-size: 0.9em;">
203
  Jump to {library_time:.1f}s
204
  </button>
205
  </div>
206
- <p style="font-size: 0.8em; color: #64748b; text-align: center; margin: 5px 0 0 0;">
207
  Vocal match found at {library_time:.1f}s
208
  </p>
209
  </div>
@@ -211,9 +280,9 @@ def process_audio_for_matching(audio_file):
211
  file_info = f"Found: {os.path.basename(song_file_path)}"
212
  else:
213
  audio_player = f"""
214
- <div style="margin: 10px 0; padding: 10px; background: #fef3c7; border-radius: 8px; text-align: center;">
215
- <p style="color: #92400e; margin: 0;">Song file not found for playback</p>
216
- <p style="font-size: 0.8em; color: #92400e; margin: 5px 0 0 0;">Match at {library_time:.1f}s in "{song_title}"</p>
217
  </div>
218
  """
219
  file_info = f"Song file not found: {song_title}"
@@ -222,33 +291,33 @@ def process_audio_for_matching(audio_file):
222
  <div style="background: #ffffff; border-radius: 12px; padding: 20px; margin: 15px 0;
223
  border-left: 5px solid {rank_color}; box-shadow: 0 3px 10px rgba(0,0,0,0.1);">
224
  <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
225
- <h3 style="color: #1e293b; margin: 0; font-size: 1.2em;">
226
  <span style="background: {rank_color}; color: white; padding: 4px 8px; border-radius: 15px; font-size: 0.8em; margin-right: 10px;">
227
  #{rank}
228
  </span>
229
  {song_title}
230
  </h3>
231
- <span style="background: #f1f5f9; color: #1e293b; padding: 6px 12px; border-radius: 20px; font-weight: 600;">
232
  {confidence}
233
  </span>
234
  </div>
235
 
236
- <div style="background: #f8fafc; border-radius: 8px; padding: 12px; margin: 10px 0;">
237
  <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; text-align: center;">
238
  <div>
239
- <strong style="color: #3b82f6;">Your Audio</strong>
240
- <br><span style="color: #ef4444; font-size: 1.1em;">{test_time:.1f}s</span>
241
  </div>
242
  <div>
243
- <strong style="color: #3b82f6;">Matched At</strong>
244
- <br><span style="color: #22c55e; font-size: 1.1em;">{library_time:.1f}s</span>
245
  </div>
246
  </div>
247
  </div>
248
 
249
  {audio_player}
250
 
251
- <div style="font-size: 0.9em; color: #64748b; text-align: center; margin-top: 10px;">
252
  {file_info}
253
  </div>
254
  </div>
@@ -256,16 +325,16 @@ def process_audio_for_matching(audio_file):
256
 
257
  formatted_result = f"""
258
  <div style="background: #ffffff; border-radius: 16px; padding: 30px;
259
- box-shadow: 0 4px 20px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; margin: 10px 0;">
260
  <div style="text-align: center; margin-bottom: 25px;">
261
- <h2 style="color: #1e293b; margin-bottom: 10px; font-size: 1.8em;">Vocal Matching Results</h2>
262
- <p style="color: #64748b; font-size: 1.1em;">Found {len(matches)} similar vocals in Covers80 dataset</p>
263
  </div>
264
 
265
  {matches_html}
266
 
267
- <div style="text-align: center; margin-top: 25px; padding: 15px; background: #f1f5f9; border-radius: 8px;">
268
- <p style="color: #475569; margin: 0; font-size: 0.95em;">
269
  <strong>How to read results:</strong> Vocal similarity scores with timestamp locations.
270
  Play the audio to hear the matched vocal sections.
271
  </p>
@@ -285,7 +354,7 @@ def process_audio_for_matching(audio_file):
285
  # CSS styles
286
  custom_css = """
287
  .gradio-container {
288
- background: #f8fafc !important;
289
  min-height: 100vh;
290
  padding: 20px;
291
  }
@@ -296,19 +365,19 @@ custom_css = """
296
  margin: 0 auto !important;
297
  padding: 40px !important;
298
  max-width: 900px;
299
- border: 1px solid #e2e8f0 !important;
300
  }
301
  h1 {
302
  text-align: center !important;
303
  font-size: 2.5em !important;
304
  font-weight: 700 !important;
305
  margin-bottom: 15px !important;
306
- color: #1e293b !important;
307
  }
308
  .gradio-markdown p {
309
  text-align: center !important;
310
  font-size: 1.1em !important;
311
- color: #64748b !important;
312
  margin-bottom: 25px !important;
313
  line-height: 1.6;
314
  }
@@ -316,23 +385,23 @@ h1 {
316
  background: #ffffff !important;
317
  border-radius: 12px !important;
318
  padding: 25px !important;
319
- border: 2px dashed #cbd5e1 !important;
320
  margin-bottom: 25px !important;
321
  transition: all 0.3s ease !important;
322
  }
323
  .upload-container:hover {
324
- border-color: #3b82f6 !important;
325
- background: #f8fafc !important;
326
  }
327
  .output-container {
328
  background: #ffffff !important;
329
  border-radius: 12px !important;
330
  padding: 20px !important;
331
- border: 1px solid #e2e8f0 !important;
332
  min-height: 200px !important;
333
  }
334
  .gr-button {
335
- background: #3b82f6 !important;
336
  color: #ffffff !important;
337
  border: none !important;
338
  border-radius: 8px !important;
@@ -342,9 +411,9 @@ h1 {
342
  transition: all 0.2s ease !important;
343
  }
344
  .gr-button:hover {
345
- background: #2563eb !important;
346
  transform: translateY(-1px) !important;
347
- box-shadow: 0 4px 12px rgba(59, 130, 246, 0.25) !important;
348
  }
349
  @media (max-width: 768px) {
350
  h1 { font-size: 2em !important; }
@@ -353,8 +422,6 @@ h1 {
353
  }
354
  """
355
 
356
- # App initialization is already done above
357
-
358
  # Gradio interface
359
  demo = gr.Interface(
360
  fn=process_audio_for_matching,
@@ -369,18 +436,18 @@ demo = gr.Interface(
369
  ),
370
  title="Music Plagiarism Detection",
371
  description="""
372
- <div style="text-align: center; font-size: 1.1em; color: #64748b; margin: 25px 0; line-height: 1.6;">
373
  <p><strong>Music Plagiarism Detection: Problem Formulation and a Segment-based Solution</strong></p>
374
- <p style="font-size: 0.9em; color: #94a3b8; margin: 10px 0;">
375
  Authors: Seonghyeon Go, Yumin Kim<br>
376
- MIPPIA Inc.
 
377
  </p>
378
- <hr style="border: none; border-top: 1px solid #e2e8f0; margin: 20px 0;">
379
- <p>Upload any music file to detect vocal similarities in our database.</p>
380
  <p>The system analyzes only vocal characteristics, ignoring instrumental parts.</p>
381
- <p style="font-size: 0.95em; color: #94a3b8; margin-top: 15px;">
382
  Supported formats: MP3, WAV, M4A, FLAC<br>
383
- Database: Covers80 dataset<br>
384
  Processing may take some time
385
  </p>
386
  </div>
 
9
  import glob
10
  from pathlib import Path
11
  from huggingface_hub import snapshot_download
12
+ import shutil
13
 
14
  token = os.getenv("HF_TOKEN")
15
 
 
27
  sys.path.insert(0, '.')
28
  sys.path.insert(0, './ml_models')
29
 
 
 
 
30
  def download_data_from_hub():
31
+ print("=== DOWNLOAD FUNCTION START ===")
32
  base_dir = Path(".")
33
  data_repo_id = "mippia/music-data"
34
 
35
+ print(f"Base directory: {base_dir.absolute()}")
36
+ print(f"Repository: {data_repo_id}")
37
+
38
  folders_to_check = ["covers80", "ml_models"]
39
  downloaded_folders = {}
40
 
41
  # Check LFS file
42
  lfs_file = base_dir / "1005_e_4"
43
+ print(f"Checking LFS file: {lfs_file}")
44
  if lfs_file.exists():
45
  file_size = lfs_file.stat().st_size / (1024*1024)
46
+ print(f"LFS file found: {file_size:.1f} MB")
47
  downloaded_folders["1005_e_4"] = str(lfs_file)
48
  else:
49
+ print("LFS file not found")
50
  downloaded_folders["1005_e_4"] = None
51
 
52
+ # Check existing folders
53
+ print("=== CHECKING EXISTING FOLDERS ===")
54
+ for folder in folders_to_check:
55
+ folder_path = base_dir / folder
56
+ print(f"Checking {folder} at {folder_path}")
57
+ if folder_path.exists():
58
+ if any(folder_path.iterdir()):
59
+ print(f" {folder} exists and has content")
60
+ else:
61
+ print(f" {folder} exists but is empty")
62
+ else:
63
+ print(f" {folder} does not exist")
64
+
65
  all_folders_exist = all((base_dir / folder).exists() and any((base_dir / folder).iterdir())
66
  for folder in folders_to_check)
67
+ print(f"All folders exist: {all_folders_exist}")
68
 
69
  if not all_folders_exist:
70
+ print("=== STARTING DOWNLOAD ===")
71
 
72
  # Download to a temporary directory first
73
  temp_dir = base_dir / "temp_download"
74
+ print(f"Creating temp directory: {temp_dir}")
75
  temp_dir.mkdir(exist_ok=True)
76
 
77
+ print("Calling snapshot_download...")
78
  downloaded_path = snapshot_download(
79
  repo_id=data_repo_id,
80
  repo_type="dataset",
 
84
  ignore_patterns=["*.md", "*.txt", ".gitattributes", "README.md"]
85
  )
86
 
87
+ print(f"Download completed to: {downloaded_path}")
88
 
89
+ # Check what was downloaded
90
+ print("=== CHECKING TEMP DOWNLOAD CONTENTS ===")
91
+ print(f"Temp directory contents:")
92
+ for item in temp_dir.iterdir():
93
+ item_type = "DIR" if item.is_dir() else "FILE"
94
+ print(f" {item.name} ({item_type})")
95
+ if item.is_dir():
96
+ file_count = len([f for f in item.rglob("*") if f.is_file()])
97
+ print(f" Contains {file_count} files")
98
 
99
+ # Move folders from temp to current directory
100
+ print("=== MOVING FOLDERS ===")
101
  for folder_name in folders_to_check:
102
  temp_folder_path = temp_dir / folder_name
103
  target_folder_path = base_dir / folder_name
104
 
105
+ print(f"Processing {folder_name}:")
106
+ print(f" Source: {temp_folder_path}")
107
+ print(f" Target: {target_folder_path}")
108
+ print(f" Source exists: {temp_folder_path.exists()}")
109
+
110
  if temp_folder_path.exists():
111
+ # Remove existing target if it exists
112
  if target_folder_path.exists():
113
+ print(f" Removing existing target directory")
114
  shutil.rmtree(target_folder_path)
115
+
116
+ # Move folder
117
+ print(f" Moving folder...")
118
  shutil.move(str(temp_folder_path), str(target_folder_path))
 
119
 
120
+ # Verify move
121
+ if target_folder_path.exists():
122
+ file_count = len([f for f in target_folder_path.rglob("*") if f.is_file()])
123
+ print(f" SUCCESS: {folder_name} moved with {file_count:,} files")
124
+ downloaded_folders[folder_name] = str(target_folder_path)
125
+ else:
126
+ print(f" ERROR: Move failed for {folder_name}")
127
+ downloaded_folders[folder_name] = None
128
  else:
129
+ print(f" ERROR: {folder_name} not found in temp download")
 
 
 
 
130
  downloaded_folders[folder_name] = None
131
 
132
  # Clean up temp directory
133
+ print("=== CLEANING UP TEMP DIRECTORY ===")
134
+ if temp_dir.exists():
135
+ shutil.rmtree(temp_dir)
136
+ print("Temp directory removed")
137
 
138
  else:
139
+ print("=== USING EXISTING FOLDERS ===")
140
  for folder_name in folders_to_check:
141
  folder_path = base_dir / folder_name
142
  if folder_path.exists():
 
146
  else:
147
  downloaded_folders[folder_name] = None
148
 
149
+ print("=== FINAL STATUS ===")
150
+ for key, value in downloaded_folders.items():
151
+ print(f"{key}: {value}")
152
+
153
+ print("=== DOWNLOAD FUNCTION END ===")
154
  return downloaded_folders
155
 
156
+ # Download data and check results
157
+ print("Starting Music Plagiarism Detection App...")
158
+ folders = download_data_from_hub()
159
+
160
+ # Final verification
161
+ print("=== FINAL VERIFICATION ===")
162
+ current_dir = Path(".")
163
+ print(f"Current directory contents after download:")
164
+ for item in current_dir.iterdir():
165
+ item_type = "DIR" if item.is_dir() else "FILE"
166
+ print(f" {item.name} ({item_type})")
167
+
168
+ # Check ml_models specifically
169
+ ml_models_path = Path("ml_models")
170
+ print(f"ml_models check:")
171
+ print(f" Exists: {ml_models_path.exists()}")
172
+ if ml_models_path.exists():
173
+ print(f" Is directory: {ml_models_path.is_dir()}")
174
+ print(f" Contents:")
175
+ for item in ml_models_path.iterdir():
176
+ print(f" {item.name}")
177
+
178
+ # Import inference
179
+ print("=== IMPORTING INFERENCE ===")
180
+ from inference import inference
181
+
182
  def find_song_file_by_title(song_title):
183
  covers80_path = Path("covers80")
184
 
 
211
  def process_audio_for_matching(audio_file):
212
  if audio_file is None:
213
  return """
214
+ <div style='text-align: center; color: #dc2626; padding: 30px; background: #fef2f2; border-radius: 12px; border: 2px dashed #fecaca;'>
215
  <h3>No Audio File</h3>
216
  <p>Please upload an audio file to get started!</p>
217
  </div>
218
  """
219
 
 
 
220
  result = inference(audio_file)
221
 
222
  if result.get('message') != 'success':
223
  return f"""
224
+ <div style="text-align: center; padding: 25px; background: #fefce8; border-radius: 12px; border: 1px solid #fde047; margin: 10px 0;">
225
+ <h3 style="color: #a16207; margin-bottom: 15px;">No Matches Found</h3>
226
+ <p style="color: #a16207; font-size: 1.1em;">{result.get('message', 'Unknown error occurred')}</p>
227
  </div>
228
  """
229
 
230
  matches = result.get('matches', [])
231
  if not matches:
232
  return """
233
+ <div style="text-align: center; padding: 25px; background: #fefce8; border-radius: 12px; border: 1px solid #fde047; margin: 10px 0;">
234
+ <h3 style="color: #a16207; margin-bottom: 15px;">No Matches Found</h3>
235
+ <p style="color: #a16207; font-size: 1.1em;">No matching vocals found in the dataset.</p>
236
  </div>
237
  """
238
 
 
246
  library_time = match.get('library_time', 0)
247
 
248
  # Ranking colors
249
+ rank_colors = {1: '#dc2626', 2: '#ea580c', 3: '#16a34a'}
250
  rank_color = rank_colors.get(rank, '#6b7280')
251
 
252
  # Find song file
 
259
  audio_player = f"""
260
  <div style="margin: 15px 0; padding: 15px; background: #f8fafc; border-radius: 8px;">
261
  <div style="text-align: center; margin-bottom: 10px;">
262
+ <strong style="color: #1f2937;">Play matched vocal section</strong>
263
  </div>
264
  <audio controls preload="metadata" style="width: 100%;">
265
  <source src="file/{rel_song_path}#t={library_time:.1f}" type="audio/mpeg">
 
268
  </audio>
269
  <div style="text-align: center; margin-top: 8px;">
270
  <button onclick="seekToTime(this.parentElement.previousElementSibling.querySelector('audio'), {library_time})"
271
+ style="background: #2563eb; color: white; border: none; padding: 5px 15px; border-radius: 6px; cursor: pointer; font-size: 0.9em;">
272
  Jump to {library_time:.1f}s
273
  </button>
274
  </div>
275
+ <p style="font-size: 0.8em; color: #374151; text-align: center; margin: 5px 0 0 0;">
276
  Vocal match found at {library_time:.1f}s
277
  </p>
278
  </div>
 
280
  file_info = f"Found: {os.path.basename(song_file_path)}"
281
  else:
282
  audio_player = f"""
283
+ <div style="margin: 10px 0; padding: 10px; background: #fefce8; border-radius: 8px; text-align: center;">
284
+ <p style="color: #a16207; margin: 0;">Song file not found for playback</p>
285
+ <p style="font-size: 0.8em; color: #a16207; margin: 5px 0 0 0;">Match at {library_time:.1f}s in "{song_title}"</p>
286
  </div>
287
  """
288
  file_info = f"Song file not found: {song_title}"
 
291
  <div style="background: #ffffff; border-radius: 12px; padding: 20px; margin: 15px 0;
292
  border-left: 5px solid {rank_color}; box-shadow: 0 3px 10px rgba(0,0,0,0.1);">
293
  <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
294
+ <h3 style="color: #111827; margin: 0; font-size: 1.2em;">
295
  <span style="background: {rank_color}; color: white; padding: 4px 8px; border-radius: 15px; font-size: 0.8em; margin-right: 10px;">
296
  #{rank}
297
  </span>
298
  {song_title}
299
  </h3>
300
+ <span style="background: #f3f4f6; color: #111827; padding: 6px 12px; border-radius: 20px; font-weight: 600;">
301
  {confidence}
302
  </span>
303
  </div>
304
 
305
+ <div style="background: #f9fafb; border-radius: 8px; padding: 12px; margin: 10px 0;">
306
  <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; text-align: center;">
307
  <div>
308
+ <strong style="color: #1f2937;">Your Audio</strong>
309
+ <br><span style="color: #dc2626; font-size: 1.1em;">{test_time:.1f}s</span>
310
  </div>
311
  <div>
312
+ <strong style="color: #1f2937;">Matched At</strong>
313
+ <br><span style="color: #16a34a; font-size: 1.1em;">{library_time:.1f}s</span>
314
  </div>
315
  </div>
316
  </div>
317
 
318
  {audio_player}
319
 
320
+ <div style="font-size: 0.9em; color: #374151; text-align: center; margin-top: 10px;">
321
  {file_info}
322
  </div>
323
  </div>
 
325
 
326
  formatted_result = f"""
327
  <div style="background: #ffffff; border-radius: 16px; padding: 30px;
328
+ box-shadow: 0 4px 20px rgba(0,0,0,0.08); border: 1px solid #e5e7eb; margin: 10px 0;">
329
  <div style="text-align: center; margin-bottom: 25px;">
330
+ <h2 style="color: #111827; margin-bottom: 10px; font-size: 1.8em;">Vocal Matching Results</h2>
331
+ <p style="color: #374151; font-size: 1.1em;">Found {len(matches)} similar vocals in Covers80 dataset</p>
332
  </div>
333
 
334
  {matches_html}
335
 
336
+ <div style="text-align: center; margin-top: 25px; padding: 15px; background: #f3f4f6; border-radius: 8px;">
337
+ <p style="color: #374151; margin: 0; font-size: 0.95em;">
338
  <strong>How to read results:</strong> Vocal similarity scores with timestamp locations.
339
  Play the audio to hear the matched vocal sections.
340
  </p>
 
354
  # CSS styles
355
  custom_css = """
356
  .gradio-container {
357
+ background: #f9fafb !important;
358
  min-height: 100vh;
359
  padding: 20px;
360
  }
 
365
  margin: 0 auto !important;
366
  padding: 40px !important;
367
  max-width: 900px;
368
+ border: 1px solid #e5e7eb !important;
369
  }
370
  h1 {
371
  text-align: center !important;
372
  font-size: 2.5em !important;
373
  font-weight: 700 !important;
374
  margin-bottom: 15px !important;
375
+ color: #111827 !important;
376
  }
377
  .gradio-markdown p {
378
  text-align: center !important;
379
  font-size: 1.1em !important;
380
+ color: #374151 !important;
381
  margin-bottom: 25px !important;
382
  line-height: 1.6;
383
  }
 
385
  background: #ffffff !important;
386
  border-radius: 12px !important;
387
  padding: 25px !important;
388
+ border: 2px dashed #d1d5db !important;
389
  margin-bottom: 25px !important;
390
  transition: all 0.3s ease !important;
391
  }
392
  .upload-container:hover {
393
+ border-color: #2563eb !important;
394
+ background: #f9fafb !important;
395
  }
396
  .output-container {
397
  background: #ffffff !important;
398
  border-radius: 12px !important;
399
  padding: 20px !important;
400
+ border: 1px solid #e5e7eb !important;
401
  min-height: 200px !important;
402
  }
403
  .gr-button {
404
+ background: #2563eb !important;
405
  color: #ffffff !important;
406
  border: none !important;
407
  border-radius: 8px !important;
 
411
  transition: all 0.2s ease !important;
412
  }
413
  .gr-button:hover {
414
+ background: #1d4ed8 !important;
415
  transform: translateY(-1px) !important;
416
+ box-shadow: 0 4px 12px rgba(37, 99, 235, 0.25) !important;
417
  }
418
  @media (max-width: 768px) {
419
  h1 { font-size: 2em !important; }
 
422
  }
423
  """
424
 
 
 
425
  # Gradio interface
426
  demo = gr.Interface(
427
  fn=process_audio_for_matching,
 
436
  ),
437
  title="Music Plagiarism Detection",
438
  description="""
439
+ <div style="text-align: center; font-size: 1.1em; color: #374151; margin: 25px 0; line-height: 1.6;">
440
  <p><strong>Music Plagiarism Detection: Problem Formulation and a Segment-based Solution</strong></p>
441
+ <p style="font-size: 0.9em; color: #6b7280; margin: 10px 0;">
442
  Authors: Seonghyeon Go, Yumin Kim<br>
443
+ MIPPIA Inc.<br>
444
+ Submitted to ICASSP 2026
445
  </p>
446
+ <hr style="border: none; border-top: 1px solid #e5e7eb; margin: 20px 0;">
447
+ <p>Upload any music file to detect vocal similarities in the Covers80 dataset.</p>
448
  <p>The system analyzes only vocal characteristics, ignoring instrumental parts.</p>
449
+ <p style="font-size: 0.95em; color: #6b7280; margin-top: 15px;">
450
  Supported formats: MP3, WAV, M4A, FLAC<br>
 
451
  Processing may take some time
452
  </p>
453
  </div>