Curlyblaze commited on
Commit
33c6c4b
Β·
verified Β·
1 Parent(s): c346b0c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -110
app.py CHANGED
@@ -4,150 +4,80 @@ from transformers import pipeline
4
  from moviepy import ImageClip, AudioFileClip
5
  import os
6
 
7
- # --- 1. INITIALIZE ENGINES ---
8
- # Music Genre Classifier (Public & Fast)
9
  classifier = pipeline("audio-classification", model="dima806/music_genres_classification")
10
-
11
- # External AI Spaces (API Clients)
12
  mastering_client = Client("amaai-lab/SonicMaster")
13
  image_client = Client("black-forest-labs/FLUX.1-schnell")
14
 
15
- # --- 2. LOGIC FUNCTIONS ---
16
-
17
  def master_logic(audio_path):
18
  if not audio_path: return None, None, "Upload a track!", None
19
-
20
- # 1. Detect Genre
21
  results = classifier(audio_path)
22
  genre = results[0]['label']
23
 
24
- # 2. AI Mastering
25
  result = mastering_client.predict(
26
  handle_file(audio_path),
27
  f"Professional {genre} studio master.",
28
  42, 25, 3.5
29
  )
30
 
31
- # --- THE CLEANUP FIX ---
32
- raw_output = result[1] # This is "Saved: /path/to/file.wav\nElapsed: 19s"
33
-
34
- try:
35
- # We split by "Saved: " and take the second part,
36
- # then split by "\n" and take the first part.
37
- clean_path = raw_output.split("Saved: ")[1].split("\n")[0].strip()
38
- except Exception:
39
- # Fallback just in case the API format is different
40
- clean_path = raw_output
41
-
42
- return clean_path, clean_path, f"Genre: {genre} | Mastered ✨", clean_path
43
 
44
  def art_logic(status_text, vibe):
45
- if not status_text or "Ready" in status_text:
46
- return None
47
-
48
- # Clean the genre from the status message
49
- clean_genre = str(status_text).split("**")[1] if "**" in str(status_text) else "Music"
50
- prompt = f"Professional album cover art, {clean_genre} style, {vibe}, 4k, ultra-detailed, no text."
51
 
52
- # Flux API call
53
  img_result = image_client.predict(
54
- prompt=prompt,
55
- seed=0,
56
- width=1024,
57
- height=1024,
58
- guidance_scale=3.5,
59
- num_inference_steps=4,
60
  api_name="/infer"
61
  )
62
  return img_result[0]
63
 
64
  def video_logic(audio_path, image_path):
65
- if not audio_path or not image_path:
66
- return None
67
-
68
- # MoviePy v2.0+ Syntax (Uses 'with_' and 'subclipped')
69
  audio = AudioFileClip(audio_path).subclipped(0, 30)
70
  img = ImageClip(image_path).with_duration(audio.duration).resized(width=1080)
71
-
72
- # Create 9:16 Vertical Video
73
- video = img.on_color(size=(1080, 1920), color=(15, 15, 15), pos="center")
74
- video = video.with_audio(audio)
75
-
76
- out_path = "promo_snippet.mp4"
77
- video.write_videofile(out_path, fps=24, codec="libx264", audio_codec="aac")
78
- return out_path
79
 
80
  def toggle_ab(choice, raw, mastered):
81
  return mastered if "Mastered" in choice else raw
82
 
83
- # --- 3. UI LAYOUT ---
84
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
85
- gr.HTML("<h1 style='text-align: center;'>🎧 AI Artist Command Center</h1>")
86
-
87
- # Persistent storage for audio paths
88
  raw_storage = gr.State()
89
  master_storage = gr.State()
90
 
91
  with gr.Tabs():
92
- # TAB 1: MASTERING & COMPARISON
93
- with gr.TabItem("πŸŽ™οΈ 1. Master"):
 
94
  with gr.Row():
95
- in_audio = gr.Audio(label="Step 1: Upload Raw Demo", type="filepath")
96
- with gr.Column():
97
- monitor = gr.Audio(label="Step 2: Studio Monitor", interactive=False)
98
- ab_toggle = gr.Radio(
99
- choices=["Original πŸ”ˆ", "Mastered ✨"],
100
- value="Mastered ✨",
101
- label="A/B Comparison (Instant Bypass)"
102
- )
103
-
104
- master_btn = gr.Button("πŸš€ START MASTERING", variant="primary")
105
- status_display = gr.Markdown("Ready to analyze...")
106
- download_wav = gr.File(label="Download High-Res WAV")
107
-
108
- # TAB 2: ARTWORK GENERATION
109
- with gr.TabItem("πŸ–ΌοΈ 2. Album Art"):
110
- with gr.Row():
111
- with gr.Column():
112
- vibe_in = gr.Textbox(label="Visual Vibe", placeholder="e.g. Cyberpunk Tokyo, oil painting...")
113
- art_btn = gr.Button("🎨 GENERATE COVER")
114
- art_out = gr.Image(label="Your Artwork", type="filepath")
115
-
116
- # TAB 3: SOCIAL MEDIA EXPORT
117
- with gr.TabItem("πŸ“± 3. Social Promo"):
118
- promo_btn = gr.Button("🎬 CREATE TIKTOK SNIPPET", variant="primary")
119
- video_out = gr.Video(label="Final 9:16 Video")
120
-
121
- # --- 4. WIRING THE EVENTS ---
122
-
123
- # Mastering logic
124
- master_btn.click(
125
- fn=master_logic,
126
- inputs=in_audio,
127
- outputs=[monitor, download_wav, status_display, master_storage]
128
- ).then(
129
- fn=lambda x: x, inputs=in_audio, outputs=raw_storage
130
- )
131
-
132
- # A/B Toggle logic
133
- ab_toggle.change(
134
- fn=toggle_ab,
135
- inputs=[ab_toggle, raw_storage, master_storage],
136
- outputs=monitor
137
- )
138
-
139
- # Art logic (takes the genre from status + user vibe)
140
- art_btn.click(
141
- fn=art_logic,
142
- inputs=[status_display, vibe_in],
143
- outputs=art_out
144
- )
145
-
146
- # Video logic (takes mastered audio + generated art)
147
- promo_btn.click(
148
- fn=video_logic,
149
- inputs=[master_storage, art_out],
150
- outputs=video_out
151
  )
 
 
 
152
 
153
- demo.launch()
 
 
4
  from moviepy import ImageClip, AudioFileClip
5
  import os
6
 
7
+ # --- ENGINES ---
 
8
  classifier = pipeline("audio-classification", model="dima806/music_genres_classification")
 
 
9
  mastering_client = Client("amaai-lab/SonicMaster")
10
  image_client = Client("black-forest-labs/FLUX.1-schnell")
11
 
 
 
12
  def master_logic(audio_path):
13
  if not audio_path: return None, None, "Upload a track!", None
 
 
14
  results = classifier(audio_path)
15
  genre = results[0]['label']
16
 
17
+ # API call: returns [audio_file, status_text]
18
  result = mastering_client.predict(
19
  handle_file(audio_path),
20
  f"Professional {genre} studio master.",
21
  42, 25, 3.5
22
  )
23
 
24
+ # USE result[0] for the actual file
25
+ mastered_file = result[0]
26
+ return mastered_file, mastered_file, f"Genre: **{genre}** | Mastered ✨", mastered_file
 
 
 
 
 
 
 
 
 
27
 
28
  def art_logic(status_text, vibe):
29
+ if not status_text or "Ready" in status_text: return None
30
+ clean_genre = status_text.split("**")[1] if "**" in status_text else "Music"
 
 
 
 
31
 
 
32
  img_result = image_client.predict(
33
+ prompt=f"Professional album cover, {clean_genre}, {vibe}, high res",
34
+ seed=0, width=1024, height=1024, guidance_scale=3.5, num_inference_steps=4,
 
 
 
 
35
  api_name="/infer"
36
  )
37
  return img_result[0]
38
 
39
  def video_logic(audio_path, image_path):
40
+ if not audio_path or not image_path: return None
 
 
 
41
  audio = AudioFileClip(audio_path).subclipped(0, 30)
42
  img = ImageClip(image_path).with_duration(audio.duration).resized(width=1080)
43
+ video = img.on_color(size=(1080, 1920), color=(15, 15, 15), pos="center").with_audio(audio)
44
+ video.write_videofile("promo.mp4", fps=24, codec="libx264")
45
+ return "promo.mp4"
 
 
 
 
 
46
 
47
  def toggle_ab(choice, raw, mastered):
48
  return mastered if "Mastered" in choice else raw
49
 
50
+ # --- UI ---
51
+ with gr.Blocks() as demo:
52
+ gr.Markdown("# 🎡 AI Artist Studio")
 
 
53
  raw_storage = gr.State()
54
  master_storage = gr.State()
55
 
56
  with gr.Tabs():
57
+ with gr.TabItem("🎧 1. Master"):
58
+ in_audio = gr.Audio(label="Upload", type="filepath")
59
+ master_btn = gr.Button("πŸš€ MASTER", variant="primary")
60
  with gr.Row():
61
+ monitor = gr.Audio(label="Monitor")
62
+ ab_toggle = gr.Radio(["Original πŸ”ˆ", "Mastered ✨"], value="Mastered ✨", label="A/B")
63
+ status = gr.Markdown("Ready")
64
+ export_file = gr.File(label="WAV")
65
+
66
+ with gr.TabItem("🎨 2. Art"):
67
+ vibe_in = gr.Textbox(label="Vibe")
68
+ art_btn = gr.Button("🎨 ART")
69
+ art_out = gr.Image()
70
+
71
+ with gr.TabItem("πŸ“± 3. Promo"):
72
+ promo_btn = gr.Button("🎬 VIDEO")
73
+ video_out = gr.Video()
74
+
75
+ master_btn.click(master_logic, in_audio, [monitor, export_file, status, master_storage]).then(
76
+ lambda x: x, in_audio, raw_storage
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  )
78
+ ab_toggle.change(toggle_ab, [ab_toggle, raw_storage, master_storage], monitor)
79
+ art_btn.click(art_logic, [status, vibe_in], art_out)
80
+ promo_btn.click(video_logic, [master_storage, art_out], video_out)
81
 
82
+ # Theme moved to launch to fix the UserWarning
83
+ demo.launch(theme=gr.themes.Soft())