4p5l34e5nhen5r / app.py
ASesYusuf1's picture
Update app.py
ec0caeb verified
Raw
History Blame
14.7 kB
import gradio as gr
import subprocess
import os
import numpy as np
import librosa
import soundfile as sf
import matplotlib.pyplot as plt
import librosa.display
import gc
import torch
import noisereduce as nr
import warnings
from scipy import signal
from scipy.stats import kurtosis, skew
import spaces
import urllib.request
warnings.filterwarnings("ignore")
# Set environment variables and torch settings
os.environ["TOKENIZERS_PARALLELISM"] = "true"
torch.set_float32_matmul_precision("high")
# Check for GPU availability
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")
# Create output directory
output_folder = "output_file"
os.makedirs(output_folder, exist_ok=True)
print(f"Output folder ready: {output_folder}")
# Setup function to download models and configs using wget or urllib
def setup():
# Create Apollo directory structure
os.makedirs("Apollo/model", exist_ok=True)
os.makedirs("Apollo/configs", exist_ok=True)
# Define files and their URLs
files_to_download = {
"Apollo/inference.py": "https://raw.githubusercontent.com/jarredou/Apollo-Colab-Inference/main/inference.py",
"Apollo/model/pytorch_model.bin": "https://huggingface.co/JusperLee/Apollo/resolve/main/pytorch_model.bin",
"Apollo/model/apollo_model.ckpt": "https://huggingface.co/jarredou/lew_apollo_vocal_enhancer/resolve/main/apollo_model.ckpt",
"Apollo/model/apollo_model_v2.ckpt": "https://huggingface.co/jarredou/lew_apollo_vocal_enhancer/resolve/main/apollo_model_v2.ckpt",
"Apollo/model/apollo_universal_model.ckpt": "https://huggingface.co/ASesYusuf1/Apollo_universal_model/resolve/main/apollo_universal_model.ckpt",
"Apollo/configs/config_apollo_vocal.yaml": "https://huggingface.co/jarredou/lew_apollo_vocal_enhancer/resolve/main/config_apollo_vocal.yaml",
"Apollo/configs/config_apollo.yaml": "https://huggingface.co/ASesYusuf1/Apollo_universal_model/resolve/main/config_apollo.yaml",
"Apollo/configs/apollo.yaml": "https://huggingface.co/JusperLee/Apollo/resolve/main/apollo.yaml",
}
# Download files if they don't exist
for file_path, url in files_to_download.items():
if not os.path.exists(file_path):
print(f"Downloading {file_path}...")
try:
# Try wget first
subprocess.run(["wget", "-O", file_path, url], check=True, capture_output=True, text=True)
print(f"Downloaded {file_path} with wget")
except (subprocess.CalledProcessError, FileNotFoundError) as e:
print(f"wget failed for {file_path}: {e}. Falling back to urllib...")
try:
urllib.request.urlretrieve(url, file_path)
print(f"Downloaded {file_path} with urllib")
except Exception as e:
print(f"Failed to download {file_path}: {e}")
raise Exception(f"Failed to download {file_path}")
# Run setup
try:
setup()
except Exception as e:
print(f"Setup failed: {e}")
raise
# Processing function
@spaces.GPU
def process_audio(input_file, model, chunk_size, overlap):
if not input_file:
return "No file uploaded.", None, None
input_file_path = input_file
original_file_name = os.path.splitext(os.path.basename(input_file_path))[0]
output_file_path = f'{output_folder}/{original_file_name}_processed.wav'
# Model selection
model_paths = {
'MP3 Enhancer': ('Apollo/model/pytorch_model.bin', 'Apollo/configs/apollo.yaml'),
'Lew Vocal Enhancer': ('Apollo/model/apollo_model.ckpt', 'Apollo/configs/apollo.yaml'),
'Lew Vocal Enhancer v2 (beta)': ('Apollo/model/apollo_model_v2.ckpt', 'Apollo/configs/config_apollo_vocal.yaml'),
'Apollo Universal Model': ('Apollo/model/apollo_universal_model.ckpt', 'Apollo/configs/config_apollo.yaml')
}
if model not in model_paths:
return "Invalid model selected.", None, None
ckpt, config = model_paths[model]
if not os.path.exists(ckpt) or not os.path.exists(config):
return f"Model files not found: {ckpt} or {config}", None, None
print(f"Model selected: {model}")
print("Processing started. Please wait...")
command = f"python Apollo/inference.py --in_wav '{input_file_path}' --out_wav '{output_file_path}' --chunk_size {chunk_size} --overlap {overlap} --ckpt '{ckpt}' --config '{config}'"
try:
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
for line in process.stdout:
print(f"Processing: {line.strip()}")
process.stdout.close()
process.wait()
if process.returncode != 0:
return "An error occurred while processing the audio.", None, None
print("Processing completed.")
return output_file_path, input_file_path, None
except Exception as e:
return f"Error: {str(e)}", None, None
# Mid/Side separation and combination
def mid_side_separation(audio_file):
try:
y, sr = librosa.load(audio_file, sr=None, mono=False)
if y.ndim == 1:
raise ValueError("Stereo audio file required!")
left, right = y[0], y[1]
mid = (left + right) / 2
side = (left - right) / 2
mid_path = os.path.join(output_folder, "mid.wav")
side_path = os.path.join(output_folder, "side.wav")
sf.write(mid_path, mid, sr)
sf.write(side_path, side, sr)
return mid_path, side_path, sr
except Exception as e:
raise ValueError(f"Error in mid/side separation: {str(e)}")
def mid_side_combine(mid_file, side_file, output_path):
try:
mid_data, sr_mid = librosa.load(mid_file, sr=None, mono=True)
side_data, sr_side = librosa.load(side_file, sr=None, mono=True)
if sr_mid != sr_side:
raise ValueError("Mid and Side sample rates do not match!")
left = mid_data + side_data
right = mid_data - side_data
stereo = np.stack([left, right], axis=0)
sf.write(output_path, stereo.T, sr_mid)
return output_path
except Exception as e:
raise ValueError(f"Error in mid/side combination: {str(e)}")
@spaces.GPU
def process_mid_side_upscale(input_file, model, chunk_size, overlap):
if not input_file:
return "No file uploaded.", None, None
try:
print("Separating Mid and Side channels...")
mid_path, side_path, sr = mid_side_separation(input_file)
print("Processing Mid channel...")
mid_restored, _, _ = process_audio(mid_path, model, chunk_size, overlap)
if not mid_restored.endswith(".wav"):
return mid_restored, None, None
print("Processing Side channel...")
side_restored, _, _ = process_audio(side_path, model, chunk_size, overlap)
if not side_restored.endswith(".wav"):
return side_restored, None, None
original_file_name = os.path.splitext(os.path.basename(input_file))[0]
final_output_path = os.path.join(output_folder, f"{original_file_name}_upscaled.wav")
print("Combining processed Mid and Side channels...")
final_audio = mid_side_combine(mid_restored, side_restored, final_output_path)
print("Mid/Side upscaling completed.")
return final_audio, input_file, None
except Exception as e:
return f"Error: {str(e)}", None, None
# Spectrum analysis
def spectrum(audio_file):
if not audio_file:
return None, "No file selected"
try:
chunk_duration = 30 # Reduced for ZeroGPU memory constraints
hop_length = 512
n_fft = 2048 # Reduced for ZeroGPU memory constraints
with sf.SoundFile(audio_file) as sf_desc:
duration = len(sf_desc) / sf_desc.samplerate
num_chunks = int(np.ceil(duration / chunk_duration))
freqs = librosa.fft_frequencies(sr=sf_desc.samplerate, n_fft=n_fft)
total_frames = int(np.ceil(duration * sf_desc.samplerate / hop_length))
S_db_full = np.zeros((len(freqs), total_frames))
for chunk_idx in range(num_chunks):
start_time = chunk_idx * chunk_duration
y, sr = librosa.load(audio_file, offset=start_time, duration=chunk_duration, sr=None)
S_chunk = np.abs(librosa.stft(y, n_fft=n_fft, hop_length=hop_length))
S_db_chunk = librosa.amplitude_to_db(S_chunk, ref=np.max)
start_frame = int(start_time * sr / hop_length)
end_frame = start_frame + S_db_chunk.shape[1]
S_db_full[:, start_frame:end_frame] = S_db_chunk
del S_chunk, S_db_chunk
gc.collect()
downsample_factor = 4
S_db_downsampled = S_db_full[:, ::downsample_factor]
threshold = np.max(S_db_downsampled) - 60
significant_freqs = freqs[np.any(S_db_downsampled > threshold, axis=1)]
max_freq = np.max(significant_freqs) if len(significant_freqs) > 0 else sr / 2
plt.figure(figsize=(15, 8)) # Reduced size for ZeroGPU
display_hop = 4
librosa.display.specshow(
S_db_full[:, ::display_hop],
sr=sr,
hop_length=hop_length * display_hop,
x_axis='time',
y_axis='hz',
cmap='magma'
)
freq_ticks = [2000, 4000, 6000, 8000, 10000, 12000, 14000, 16000, 18000, 20000]
plt.yticks(freq_ticks, [f"{f/1000:.0f}" for f in freq_ticks])
plt.colorbar(format='%+2.0f dB')
plt.title('Frequency Spectrum', fontsize=16)
plt.xlabel('Time (seconds)', fontsize=12)
plt.ylabel('Frequency (kHz)', fontsize=12)
output_image_path = os.path.join(output_folder, 'spectrum.png')
plt.savefig(output_image_path, bbox_inches='tight', dpi=150) # Reduced DPI for ZeroGPU
plt.close()
del S_db_full, S_db_downsampled
gc.collect()
closest_freq = min(freq_ticks, key=lambda x: abs(x - max_freq))
return output_image_path, f"Maximum Frequency {int(closest_freq)} Hz"
except Exception as e:
return None, f"Error: {str(e)}"
# Credits
def show_credits():
return """This Web UI was created using AI tools and written by U.Z.S.
**Apollo-Colab-Inference** (https://github.com/jarredou/Apollo-Colab-Inference):
This project was developed by Jarred Ou and provides a colab-based inference implementation of the Apollo model for audio enhancement.
**Apollo** (https://github.com/JusperLee/Apollo):
Created by Jusper Lee, Apollo is a deep learning-based model aimed at improving vocal clarity and overall audio quality in recordings.
"""
# Gradio Interface
app = gr.Blocks(css="""
.gradio-container { background-color: black; color: white; font-family: Arial, sans-serif; }
.footer { position: absolute; bottom: 10px; right: 10px; font-size: 12px; color: white; }
.gradio-button { background-color: #6a0dad; color: white; border: 1px solid #5a0b8a; border-radius: 5px; }
.gradio-button:hover { background-color: #5a0b8a; }
.gradio-input { background-color: rgba(106, 13, 173, 0.8); border: 1px solid #5a0b8a; color: white; border-radius: 5px; }
.gradio-input:focus { border-color: #ffffff; box-shadow: 0 0 5px rgba(255, 255, 255, 0.5); }
.gradio-slider { background-color: rgba(106, 13, 173, 0.8); color: white; }
.gradio-label { color: white; }
.gradio-tabs { background-color: rgba(106, 13, 173, 0.8); color: white; }
@media (max-width: 600px) {
.gradio-button { width: 100%; font-size: 16px; }
.gradio-input { width: 100%; font-size: 16px; }
.gradio-slider { width: 100%; }
.gradio-label { font-size: 14px; }
}
""")
with app:
with gr.Tab("Home"):
gr.Markdown("# Apollo Audio Enhancement")
with gr.Row():
audio_input = gr.File(label="Select Audio File", file_types=["audio"])
model = gr.Radio(
["MP3 Enhancer", "Lew Vocal Enhancer", "Lew Vocal Enhancer v2 (beta)", "Apollo Universal Model"],
label="Select Model"
)
gr.Markdown("**For Universal model, please set Chunk_Size to 19**", elem_classes="model-note")
chunk_size = gr.Slider(minimum=3, maximum=25, step=1, value=25, label="Chunk Size")
overlap = gr.Slider(minimum=2, maximum=10, step=1, value=2, label="Overlap")
output_audio = gr.Audio(label="Processed Audio")
original_audio = gr.Audio(label="Original Audio")
error_message = gr.Textbox(label="Status")
process_button = gr.Button("Process Audio")
process_button.click(process_audio, inputs=[audio_input, model, chunk_size, overlap], outputs=[output_audio, original_audio, error_message])
with gr.Tab("Spectrum"):
gr.Markdown("# Spectrum Analysis")
spectrogram_input = gr.File(label="Select Audio File for Spectrum", file_types=["audio"])
output_spectrum = gr.Image(label="Frequency Spectrum")
max_freq_info = gr.Textbox(label="Maximum Frequency Information")
spectrum_button = gr.Button("Show Spectrum")
spectrum_button.click(spectrum, inputs=[spectrogram_input], outputs=[output_spectrum, max_freq_info])
with gr.Tab("Mid/Side Upscale"):
gr.Markdown("# 🎚️ Mid/Side Audio Upscaling")
gr.Markdown("Upload a stereo audio file to separate, enhance, and recombine its Mid and Side channels using Apollo.")
with gr.Row():
ms_input = gr.File(label="Select Stereo Audio File", file_types=["audio"])
ms_model = gr.Radio(
["MP3 Enhancer", "Lew Vocal Enhancer", "Lew Vocal Enhancer v2 (beta)", "Apollo Universal Model"],
label="Select Model",
value="Apollo Universal Model"
)
ms_chunk_size = gr.Slider(minimum=3, maximum=25, step=1, value=18, label="Chunk Size")
ms_overlap = gr.Slider(minimum=2, maximum=10, step=1, value=2, label="Overlap")
ms_output = gr.Audio(label="Upscaled Audio")
ms_original = gr.Audio(label="Original Audio")
ms_error_message = gr.Textbox(label="Status")
ms_process_button = gr.Button("Process Mid/Side Upscale")
ms_process_button.click(
process_mid_side_upscale,
inputs=[ms_input, ms_model, ms_chunk_size, ms_overlap],
outputs=[ms_output, ms_original, ms_error_message]
)
with gr.Tab("Credits"):
gr.Markdown("## Credits")
gr.Markdown(show_credits())
gr.Markdown("Developed by U.Z.S using ChatGPT.", elem_classes="footer")
app.launch()