root
commited on
Commit
·
db4c558
1
Parent(s):
38b696f
music
Browse files
app.py
CHANGED
|
@@ -357,36 +357,40 @@ def calculate_detailed_song_structure(audio_data):
|
|
| 357 |
"syllables": syllables_info
|
| 358 |
}
|
| 359 |
|
| 360 |
-
def generate_lyrics(genre, duration, emotion_results
|
| 361 |
-
"""Generate lyrics based on genre
|
| 362 |
-
#
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
#
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
|
|
|
|
| 387 |
|
| 388 |
-
|
| 389 |
-
|
|
|
|
|
|
|
|
|
|
| 390 |
You are a talented songwriter who specializes in {genre} music.
|
| 391 |
Write original {genre} song lyrics for a song that is {duration:.1f} seconds long.
|
| 392 |
|
|
@@ -409,60 +413,6 @@ The lyrics should:
|
|
| 409 |
- Match the song duration of {duration:.1f} seconds
|
| 410 |
- Keep each line concise and impactful
|
| 411 |
|
| 412 |
-
Your lyrics:
|
| 413 |
-
"""
|
| 414 |
-
|
| 415 |
-
else:
|
| 416 |
-
# Extract emotion and theme data from analysis results
|
| 417 |
-
primary_emotion = emotion_results["emotion_analysis"]["primary_emotion"]
|
| 418 |
-
primary_theme = emotion_results["theme_analysis"]["primary_theme"]
|
| 419 |
-
tempo = emotion_results["rhythm_analysis"]["tempo"]
|
| 420 |
-
key = emotion_results["tonal_analysis"]["key"]
|
| 421 |
-
mode = emotion_results["tonal_analysis"]["mode"]
|
| 422 |
-
|
| 423 |
-
# Create detailed structure instructions for the LLM
|
| 424 |
-
structure_instructions = "Follow this exact song structure with specified syllable counts:\n"
|
| 425 |
-
|
| 426 |
-
for section in song_structure["syllables"]:
|
| 427 |
-
section_type = section["type"].capitalize()
|
| 428 |
-
start_time = f"{section['start']:.1f}"
|
| 429 |
-
end_time = f"{section['end']:.1f}"
|
| 430 |
-
duration = f"{section['duration']:.1f}"
|
| 431 |
-
beat_count = section["beat_count"]
|
| 432 |
-
syllable_count = section["syllable_count"]
|
| 433 |
-
|
| 434 |
-
structure_instructions += f"* {section_type} ({start_time}s - {end_time}s, {duration}s duration):\n"
|
| 435 |
-
structure_instructions += f" - {beat_count} beats\n"
|
| 436 |
-
structure_instructions += f" - Approximately {syllable_count} syllables\n"
|
| 437 |
-
|
| 438 |
-
# Calculate approximate total number of lines based on syllables
|
| 439 |
-
total_syllables = sum(section["syllable_count"] for section in song_structure["syllables"])
|
| 440 |
-
estimated_lines = max(4, int(total_syllables / 8)) # Rough estimate: average 8 syllables per line
|
| 441 |
-
|
| 442 |
-
# Create prompt for the LLM
|
| 443 |
-
prompt = f"""
|
| 444 |
-
You are a talented songwriter who specializes in {genre} music.
|
| 445 |
-
Write original {genre} song lyrics for a song that is {duration:.1f} seconds long.
|
| 446 |
-
|
| 447 |
-
Music analysis has detected the following qualities in the music:
|
| 448 |
-
- Tempo: {tempo:.1f} BPM
|
| 449 |
-
- Key: {key} {mode}
|
| 450 |
-
- Primary emotion: {primary_emotion}
|
| 451 |
-
- Primary theme: {primary_theme}
|
| 452 |
-
|
| 453 |
-
{structure_instructions}
|
| 454 |
-
|
| 455 |
-
The lyrics should:
|
| 456 |
-
- Perfectly capture the essence and style of {genre} music
|
| 457 |
-
- Express the {primary_emotion} emotion and {primary_theme} theme
|
| 458 |
-
- Have approximately {estimated_lines} lines total, distributed across sections
|
| 459 |
-
- For each line, include a syllable count that matches the beats in that section
|
| 460 |
-
- Include timestamps [MM:SS] at the beginning of each section
|
| 461 |
-
- Be completely original
|
| 462 |
-
- Match the exact song structure provided above
|
| 463 |
-
|
| 464 |
-
Important: Each section should have lyrics with syllable counts matching the beats!
|
| 465 |
-
|
| 466 |
Your lyrics:
|
| 467 |
"""
|
| 468 |
|
|
@@ -479,50 +429,21 @@ Your lyrics:
|
|
| 479 |
# Extract and clean generated lyrics
|
| 480 |
lyrics = response[0]["generated_text"].strip()
|
| 481 |
|
| 482 |
-
# Add section labels if they're not present
|
| 483 |
-
if
|
| 484 |
lines = lyrics.split('\n')
|
| 485 |
formatted_lyrics = []
|
| 486 |
current_section = "Verse"
|
| 487 |
-
verse_count = 0
|
| 488 |
-
|
| 489 |
for i, line in enumerate(lines):
|
| 490 |
if i == 0:
|
| 491 |
formatted_lyrics.append("[Verse]")
|
| 492 |
-
verse_count = 1
|
| 493 |
elif i == verse_lines:
|
| 494 |
formatted_lyrics.append("\n[Chorus]")
|
| 495 |
elif i == verse_lines + chorus_lines and lines_count > 10:
|
| 496 |
formatted_lyrics.append("\n[Bridge]")
|
| 497 |
-
elif i == verse_lines + chorus_lines + (2 if lines_count > 10 else 0):
|
| 498 |
-
formatted_lyrics.append("\n[Verse]")
|
| 499 |
-
verse_count = 2
|
| 500 |
formatted_lyrics.append(line)
|
| 501 |
-
|
| 502 |
lyrics = '\n'.join(formatted_lyrics)
|
| 503 |
|
| 504 |
-
# Add timestamps in detailed mode if needed
|
| 505 |
-
elif song_structure is not None:
|
| 506 |
-
# Ensure the lyrics have proper section headings with timestamps
|
| 507 |
-
for section in song_structure["syllables"]:
|
| 508 |
-
section_type = section["type"].capitalize()
|
| 509 |
-
start_time_str = f"{int(section['start']) // 60:02d}:{int(section['start']) % 60:02d}"
|
| 510 |
-
section_header = f"[{start_time_str}] {section_type}"
|
| 511 |
-
|
| 512 |
-
# Check if this section header is missing and add it if needed
|
| 513 |
-
if section_header not in lyrics and section["type"] not in ["intro", "outro"]:
|
| 514 |
-
# Find where this section might be based on timestamp
|
| 515 |
-
time_matches = [
|
| 516 |
-
idx for idx, line in enumerate(lyrics.split('\n'))
|
| 517 |
-
if f"{int(section['start']) // 60:02d}:{int(section['start']) % 60:02d}" in line
|
| 518 |
-
]
|
| 519 |
-
|
| 520 |
-
if time_matches:
|
| 521 |
-
lines = lyrics.split('\n')
|
| 522 |
-
line_idx = time_matches[0]
|
| 523 |
-
lines[line_idx] = section_header
|
| 524 |
-
lyrics = '\n'.join(lines)
|
| 525 |
-
|
| 526 |
return lyrics
|
| 527 |
|
| 528 |
def process_audio(audio_file):
|
|
@@ -563,7 +484,8 @@ def process_audio(audio_file):
|
|
| 563 |
"emotion_analysis": {"primary_emotion": "Unknown"},
|
| 564 |
"theme_analysis": {"primary_theme": "Unknown"},
|
| 565 |
"rhythm_analysis": {"tempo": 0},
|
| 566 |
-
"tonal_analysis": {"key": "Unknown", "mode": ""}
|
|
|
|
| 567 |
}
|
| 568 |
|
| 569 |
# Calculate detailed song structure for better lyrics alignment
|
|
@@ -574,10 +496,10 @@ def process_audio(audio_file):
|
|
| 574 |
# Continue with a simpler approach if this fails
|
| 575 |
song_structure = None
|
| 576 |
|
| 577 |
-
# Generate lyrics based on top genre
|
| 578 |
try:
|
| 579 |
primary_genre, _ = top_genres[0]
|
| 580 |
-
lyrics = generate_lyrics(primary_genre, audio_data["duration"], emotion_results
|
| 581 |
except Exception as e:
|
| 582 |
print(f"Error generating lyrics: {str(e)}")
|
| 583 |
lyrics = f"Error generating lyrics: {str(e)}"
|
|
|
|
| 357 |
"syllables": syllables_info
|
| 358 |
}
|
| 359 |
|
| 360 |
+
def generate_lyrics(genre, duration, emotion_results):
|
| 361 |
+
"""Generate lyrics based on the genre and with appropriate length."""
|
| 362 |
+
# Calculate appropriate lyrics length based on audio duration
|
| 363 |
+
lines_count = calculate_lyrics_length(duration)
|
| 364 |
+
|
| 365 |
+
# Calculate approximate number of verses and chorus
|
| 366 |
+
if lines_count <= 6:
|
| 367 |
+
# Very short song - one verse and chorus
|
| 368 |
+
verse_lines = 2
|
| 369 |
+
chorus_lines = 2
|
| 370 |
+
elif lines_count <= 10:
|
| 371 |
+
# Medium song - two verses and chorus
|
| 372 |
+
verse_lines = 3
|
| 373 |
+
chorus_lines = 2
|
| 374 |
+
else:
|
| 375 |
+
# Longer song - two verses, chorus, and bridge
|
| 376 |
+
verse_lines = 3
|
| 377 |
+
chorus_lines = 2
|
| 378 |
+
|
| 379 |
+
# Extract emotion and theme data from analysis results
|
| 380 |
+
primary_emotion = emotion_results["emotion_analysis"]["primary_emotion"]
|
| 381 |
+
primary_theme = emotion_results["theme_analysis"]["primary_theme"]
|
| 382 |
+
|
| 383 |
+
# Extract numeric values safely with fallbacks
|
| 384 |
+
try:
|
| 385 |
+
tempo = float(emotion_results["rhythm_analysis"]["tempo"])
|
| 386 |
+
except (KeyError, ValueError, TypeError):
|
| 387 |
+
tempo = 0.0
|
| 388 |
|
| 389 |
+
key = emotion_results["tonal_analysis"]["key"]
|
| 390 |
+
mode = emotion_results["tonal_analysis"]["mode"]
|
| 391 |
+
|
| 392 |
+
# Create prompt for the LLM
|
| 393 |
+
prompt = f"""
|
| 394 |
You are a talented songwriter who specializes in {genre} music.
|
| 395 |
Write original {genre} song lyrics for a song that is {duration:.1f} seconds long.
|
| 396 |
|
|
|
|
| 413 |
- Match the song duration of {duration:.1f} seconds
|
| 414 |
- Keep each line concise and impactful
|
| 415 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
Your lyrics:
|
| 417 |
"""
|
| 418 |
|
|
|
|
| 429 |
# Extract and clean generated lyrics
|
| 430 |
lyrics = response[0]["generated_text"].strip()
|
| 431 |
|
| 432 |
+
# Add section labels if they're not present
|
| 433 |
+
if "Verse" not in lyrics and "Chorus" not in lyrics:
|
| 434 |
lines = lyrics.split('\n')
|
| 435 |
formatted_lyrics = []
|
| 436 |
current_section = "Verse"
|
|
|
|
|
|
|
| 437 |
for i, line in enumerate(lines):
|
| 438 |
if i == 0:
|
| 439 |
formatted_lyrics.append("[Verse]")
|
|
|
|
| 440 |
elif i == verse_lines:
|
| 441 |
formatted_lyrics.append("\n[Chorus]")
|
| 442 |
elif i == verse_lines + chorus_lines and lines_count > 10:
|
| 443 |
formatted_lyrics.append("\n[Bridge]")
|
|
|
|
|
|
|
|
|
|
| 444 |
formatted_lyrics.append(line)
|
|
|
|
| 445 |
lyrics = '\n'.join(formatted_lyrics)
|
| 446 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
return lyrics
|
| 448 |
|
| 449 |
def process_audio(audio_file):
|
|
|
|
| 484 |
"emotion_analysis": {"primary_emotion": "Unknown"},
|
| 485 |
"theme_analysis": {"primary_theme": "Unknown"},
|
| 486 |
"rhythm_analysis": {"tempo": 0},
|
| 487 |
+
"tonal_analysis": {"key": "Unknown", "mode": ""},
|
| 488 |
+
"summary": {"tempo": 0, "key": "Unknown", "mode": "", "primary_emotion": "Unknown", "primary_theme": "Unknown"}
|
| 489 |
}
|
| 490 |
|
| 491 |
# Calculate detailed song structure for better lyrics alignment
|
|
|
|
| 496 |
# Continue with a simpler approach if this fails
|
| 497 |
song_structure = None
|
| 498 |
|
| 499 |
+
# Generate lyrics based on top genre and emotion analysis
|
| 500 |
try:
|
| 501 |
primary_genre, _ = top_genres[0]
|
| 502 |
+
lyrics = generate_lyrics(primary_genre, audio_data["duration"], emotion_results)
|
| 503 |
except Exception as e:
|
| 504 |
print(f"Error generating lyrics: {str(e)}")
|
| 505 |
lyrics = f"Error generating lyrics: {str(e)}"
|