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)}"
|