Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -22,6 +22,7 @@ from TTS.api import TTS
|
|
22 |
import base64
|
23 |
import pickle
|
24 |
import json
|
|
|
25 |
|
26 |
# Suppress warnings
|
27 |
warnings.filterwarnings("ignore")
|
@@ -108,6 +109,12 @@ def apply_stage_mode(audio):
|
|
108 |
processed = apply_bass_boost(processed, gain=6)
|
109 |
return apply_limiter(processed, limit_dB=-2)
|
110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
# === Loudness Matching (EBU R128) ===
|
112 |
try:
|
113 |
import pyloudnorm as pyln
|
@@ -362,7 +369,7 @@ def batch_process_audio(files, selected_effects, isolate_vocals, preset_name, ex
|
|
362 |
results.append(processed_path)
|
363 |
session_logs.append(log)
|
364 |
|
365 |
-
zip_path = os.path.join(
|
366 |
with zipfile.ZipFile(zip_path, 'w') as zipf:
|
367 |
for i, res in enumerate(results):
|
368 |
filename = f"processed_{i}.{export_format.lower()}"
|
@@ -382,11 +389,31 @@ def auto_tune_vocal(audio_path, target_key="C"):
|
|
382 |
except Exception as e:
|
383 |
return None
|
384 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
# === Real-Time Spectrum Analyzer + Live EQ Preview ===
|
386 |
def visualize_spectrum(audio_path):
|
387 |
y, sr = torchaudio.load(audio_path)
|
388 |
y_np = y.numpy().flatten()
|
389 |
-
|
390 |
stft = librosa.stft(y_np)
|
391 |
db = librosa.amplitude_to_db(abs(stft))
|
392 |
|
@@ -428,7 +455,7 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
428 |
output_audio, waveform_img, session_log_out, genre_out, status_box
|
429 |
])
|
430 |
|
431 |
-
# --- AI Mastering Chain Tab β
|
432 |
with gr.Tab("π§ AI Mastering Chain"):
|
433 |
gr.Interface(
|
434 |
fn=ai_mastering_chain,
|
@@ -457,7 +484,7 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
457 |
description="Enhance clarity and presence using saturation styles like Tube or Tape."
|
458 |
)
|
459 |
|
460 |
-
# --- Remix Mode
|
461 |
with gr.Tab("π Remix Mode"):
|
462 |
gr.Interface(
|
463 |
fn=stem_split,
|
@@ -474,7 +501,7 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
474 |
clear_btn=None
|
475 |
)
|
476 |
|
477 |
-
# --- Preset Cards Gallery ===
|
478 |
with gr.Tab("π Preset Gallery"):
|
479 |
gr.Markdown("### Select a preset visually")
|
480 |
preset_gallery = gr.Gallery(value=[
|
@@ -498,7 +525,7 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
498 |
|
499 |
preset_gallery.select(fn=load_preset_by_card, inputs=[], outputs=[preset_name_out, preset_effects_out])
|
500 |
|
501 |
-
# --- Vocal Doubler / Harmonizer ===
|
502 |
with gr.Tab("π§ Vocal Doubler / Harmonizer"):
|
503 |
gr.Interface(
|
504 |
fn=lambda x: apply_harmony(x),
|
@@ -508,7 +535,7 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
508 |
description="Enhance vocals with doubling or harmony"
|
509 |
)
|
510 |
|
511 |
-
# --- Batch Processing
|
512 |
with gr.Tab("π Batch Processing"):
|
513 |
gr.Interface(
|
514 |
fn=batch_process_audio,
|
@@ -543,7 +570,21 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
543 |
description="Correct vocal pitch automatically"
|
544 |
)
|
545 |
|
546 |
-
# ---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
547 |
with gr.Tab("π Frequency Spectrum"):
|
548 |
gr.Interface(
|
549 |
fn=visualize_spectrum,
|
@@ -553,7 +594,7 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
553 |
description="See the frequency breakdown of your audio"
|
554 |
)
|
555 |
|
556 |
-
# --- Loudness Graph Tab ===
|
557 |
with gr.Tab("π Loudness Graph"):
|
558 |
gr.Interface(
|
559 |
fn=match_loudness,
|
@@ -566,7 +607,7 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
566 |
description="Ensure consistent volume using EBU R128 standard"
|
567 |
)
|
568 |
|
569 |
-
# --- Save/Load Mix Session (.aiproj) ===
|
570 |
def save_project(audio, preset, effects):
|
571 |
project_data = {
|
572 |
"audio": AudioSegment.from_file(audio).raw_data,
|
@@ -607,7 +648,7 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
607 |
description="Load your saved session"
|
608 |
)
|
609 |
|
610 |
-
# --- Prompt-Based Editing Tab ===
|
611 |
def process_prompt(audio, prompt):
|
612 |
return apply_noise_reduction(audio)
|
613 |
|
@@ -624,7 +665,7 @@ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
|
|
624 |
allow_flagging="never"
|
625 |
)
|
626 |
|
627 |
-
# --- Vocal Presets for Singers ===
|
628 |
with gr.Tab("π€ Vocal Presets for Singers"):
|
629 |
gr.Interface(
|
630 |
fn=process_audio,
|
|
|
22 |
import base64
|
23 |
import pickle
|
24 |
import json
|
25 |
+
from moviepy.editor import TextClip, CompositeVideoClip, ColorClip, AudioFileClip
|
26 |
|
27 |
# Suppress warnings
|
28 |
warnings.filterwarnings("ignore")
|
|
|
109 |
processed = apply_bass_boost(processed, gain=6)
|
110 |
return apply_limiter(processed, limit_dB=-2)
|
111 |
|
112 |
+
def apply_bitcrush(audio, bit_depth=8):
|
113 |
+
samples = np.array(audio.get_array_of_samples())
|
114 |
+
max_val = 2 ** (bit_depth) - 1
|
115 |
+
downsampled = np.round(samples / (32768 / max_val)).astype(np.int16)
|
116 |
+
return array_to_audiosegment(downsampled, audio.frame_rate // 2, channels=audio.channels)
|
117 |
+
|
118 |
# === Loudness Matching (EBU R128) ===
|
119 |
try:
|
120 |
import pyloudnorm as pyln
|
|
|
369 |
results.append(processed_path)
|
370 |
session_logs.append(log)
|
371 |
|
372 |
+
zip_path = os.path.join(output_dir, "batch_output.zip")
|
373 |
with zipfile.ZipFile(zip_path, 'w') as zipf:
|
374 |
for i, res in enumerate(results):
|
375 |
filename = f"processed_{i}.{export_format.lower()}"
|
|
|
389 |
except Exception as e:
|
390 |
return None
|
391 |
|
392 |
+
# === Create Karaoke Video from Audio + Lyrics ===
|
393 |
+
def create_karaoke_video(audio_path, lyrics, bg_image=None):
|
394 |
+
try:
|
395 |
+
from moviepy.editor import TextClip, CompositeVideoClip, ColorClip, AudioFileClip
|
396 |
+
|
397 |
+
audio = AudioFileClip(audio_path)
|
398 |
+
video = ColorClip(size=(1280, 720), color=(0, 0, 0), duration=audio.duration_seconds)
|
399 |
+
words = [(word.strip(), i * 3, (i+1)*3) for i, word in enumerate(lyrics.split())]
|
400 |
+
|
401 |
+
text_clips = [
|
402 |
+
TextClip(word, fontsize=60, color='white').set_position('center').set_duration(end - start).set_start(start)
|
403 |
+
for word, start, end in words
|
404 |
+
]
|
405 |
+
|
406 |
+
final_video = CompositeVideoClip([video] + text_clips).set_audio(audio)
|
407 |
+
out_path = os.path.join(tempfile.gettempdir(), "karaoke.mp4")
|
408 |
+
final_video.write_videofile(out_path, codec="libx264", audio_codec="aac")
|
409 |
+
return out_path
|
410 |
+
except Exception as e:
|
411 |
+
return f"β οΈ Failed: {str(e)}"
|
412 |
+
|
413 |
# === Real-Time Spectrum Analyzer + Live EQ Preview ===
|
414 |
def visualize_spectrum(audio_path):
|
415 |
y, sr = torchaudio.load(audio_path)
|
416 |
y_np = y.numpy().flatten()
|
|
|
417 |
stft = librosa.stft(y_np)
|
418 |
db = librosa.amplitude_to_db(abs(stft))
|
419 |
|
|
|
455 |
output_audio, waveform_img, session_log_out, genre_out, status_box
|
456 |
])
|
457 |
|
458 |
+
# --- AI Mastering Chain Tab β Fully Defined ===
|
459 |
with gr.Tab("π§ AI Mastering Chain"):
|
460 |
gr.Interface(
|
461 |
fn=ai_mastering_chain,
|
|
|
484 |
description="Enhance clarity and presence using saturation styles like Tube or Tape."
|
485 |
)
|
486 |
|
487 |
+
# --- Remix Mode β Now Included ===
|
488 |
with gr.Tab("π Remix Mode"):
|
489 |
gr.Interface(
|
490 |
fn=stem_split,
|
|
|
501 |
clear_btn=None
|
502 |
)
|
503 |
|
504 |
+
# --- Preset Cards Gallery β Visual Selection ===
|
505 |
with gr.Tab("π Preset Gallery"):
|
506 |
gr.Markdown("### Select a preset visually")
|
507 |
preset_gallery = gr.Gallery(value=[
|
|
|
525 |
|
526 |
preset_gallery.select(fn=load_preset_by_card, inputs=[], outputs=[preset_name_out, preset_effects_out])
|
527 |
|
528 |
+
# --- Vocal Doubler / Harmonizer β Added ===
|
529 |
with gr.Tab("π§ Vocal Doubler / Harmonizer"):
|
530 |
gr.Interface(
|
531 |
fn=lambda x: apply_harmony(x),
|
|
|
535 |
description="Enhance vocals with doubling or harmony"
|
536 |
)
|
537 |
|
538 |
+
# --- Batch Processing β Full Support ===
|
539 |
with gr.Tab("π Batch Processing"):
|
540 |
gr.Interface(
|
541 |
fn=batch_process_audio,
|
|
|
570 |
description="Correct vocal pitch automatically"
|
571 |
)
|
572 |
|
573 |
+
# --- Karaoke Video Creator β Added Back ===
|
574 |
+
with gr.Tab("πΉ Create Karaoke Video"):
|
575 |
+
gr.Interface(
|
576 |
+
fn=create_karaoke_video,
|
577 |
+
inputs=[
|
578 |
+
gr.Audio(label="Upload Track", type="filepath"),
|
579 |
+
gr.Textbox(label="Lyrics", lines=10),
|
580 |
+
gr.File(label="Background (Optional)")
|
581 |
+
],
|
582 |
+
outputs=gr.Video(label="Karaoke Video"),
|
583 |
+
title="Make Karaoke Videos from Audio + Lyrics",
|
584 |
+
description="Generate karaoke-style videos with real-time sync."
|
585 |
+
)
|
586 |
+
|
587 |
+
# --- Real-Time Spectrum Analyzer + Live EQ Preview β Added Back ===
|
588 |
with gr.Tab("π Frequency Spectrum"):
|
589 |
gr.Interface(
|
590 |
fn=visualize_spectrum,
|
|
|
594 |
description="See the frequency breakdown of your audio"
|
595 |
)
|
596 |
|
597 |
+
# --- Loudness Graph Tab β Added Back ===
|
598 |
with gr.Tab("π Loudness Graph"):
|
599 |
gr.Interface(
|
600 |
fn=match_loudness,
|
|
|
607 |
description="Ensure consistent volume using EBU R128 standard"
|
608 |
)
|
609 |
|
610 |
+
# --- Save/Load Mix Session (.aiproj) β Added Back ===
|
611 |
def save_project(audio, preset, effects):
|
612 |
project_data = {
|
613 |
"audio": AudioSegment.from_file(audio).raw_data,
|
|
|
648 |
description="Load your saved session"
|
649 |
)
|
650 |
|
651 |
+
# --- Prompt-Based Editing Tab β Added Back ===
|
652 |
def process_prompt(audio, prompt):
|
653 |
return apply_noise_reduction(audio)
|
654 |
|
|
|
665 |
allow_flagging="never"
|
666 |
)
|
667 |
|
668 |
+
# --- Vocal Presets for Singers β Added Back ===
|
669 |
with gr.Tab("π€ Vocal Presets for Singers"):
|
670 |
gr.Interface(
|
671 |
fn=process_audio,
|