Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import librosa | |
| import soundfile as sf | |
| import torchaudio | |
| import torch | |
| import numpy as np | |
| import zipfile | |
| import tempfile | |
| from pathlib import Path | |
| # ========================================================= | |
| # Core Resampling Logic | |
| # ========================================================= | |
| def resample_audio(y, sr, target_sr, backend): | |
| if backend == "librosa": | |
| y_out = librosa.resample(y, orig_sr=sr, target_sr=target_sr) | |
| elif backend == "soundfile": | |
| # soundfile is I/O only, librosa used for resampling | |
| y_out = librosa.resample(y, orig_sr=sr, target_sr=target_sr) | |
| elif backend == "torchaudio": | |
| waveform = torch.tensor(y).unsqueeze(0) | |
| resampler = torchaudio.transforms.Resample( | |
| orig_freq=sr, | |
| new_freq=target_sr | |
| ) | |
| y_out = resampler(waveform).squeeze(0).numpy() | |
| return y_out, target_sr | |
| # ========================================================= | |
| # Single File Processing | |
| # ========================================================= | |
| def single_file_process(audio, target_sr, backend): | |
| y, sr = audio | |
| y_out, sr_out = resample_audio(y, sr, target_sr, backend) | |
| return (sr_out, y_out) | |
| # ========================================================= | |
| # Batch ZIP Processing | |
| # ========================================================= | |
| def batch_process_zip(zip_file, target_sr, backend): | |
| output_zip_path = tempfile.NamedTemporaryFile( | |
| delete=False, suffix=".zip" | |
| ).name | |
| with zipfile.ZipFile(zip_file, "r") as zin, \ | |
| zipfile.ZipFile(output_zip_path, "w") as zout: | |
| for file in zin.namelist(): | |
| if not file.lower().endswith((".wav", ".mp3", ".flac", ".ogg")): | |
| continue | |
| # Read file from ZIP | |
| with zin.open(file) as f: | |
| with tempfile.NamedTemporaryFile(suffix=".wav") as tmp: | |
| tmp.write(f.read()) | |
| tmp.flush() | |
| # Load audio | |
| y, sr = librosa.load(tmp.name, sr=None, mono=True) | |
| # Resample | |
| y_out, sr_out = resample_audio(y, sr, target_sr, backend) | |
| # Save output | |
| out_name = f"{Path(file).stem}_{backend}_{target_sr}.wav" | |
| with tempfile.NamedTemporaryFile(suffix=".wav") as out_tmp: | |
| sf.write(out_tmp.name, y_out, sr_out) | |
| zout.write(out_tmp.name, out_name) | |
| return output_zip_path | |
| # ========================================================= | |
| # Gradio UI | |
| # ========================================================= | |
| with gr.Blocks(title="Audio Resampling Studio") as demo: | |
| gr.Markdown( | |
| """ | |
| # π Audio Resampling Studio | |
| Resample audio using **librosa**, **soundfile**, or **torchaudio**. | |
| **Features** | |
| - π§ Single-file processing | |
| - π¦ Batch ZIP processing | |
| - π― Sample rates: 16k, 22.05k, 44.1k, 48k | |
| """ | |
| ) | |
| with gr.Tabs(): | |
| # ================================================= | |
| # Single File Tab | |
| # ================================================= | |
| with gr.Tab("π§ Single File"): | |
| gr.Markdown("### Process a single audio file") | |
| audio_input = gr.Audio( | |
| type="numpy", | |
| label="Upload Audio" | |
| ) | |
| with gr.Row(): | |
| backend = gr.Radio( | |
| ["librosa", "soundfile", "torchaudio"], | |
| value="librosa", | |
| label="Backend" | |
| ) | |
| target_sr = gr.Dropdown( | |
| [16000, 22050, 44100, 48000], | |
| value=16000, | |
| label="Target Sample Rate (Hz)" | |
| ) | |
| process_btn = gr.Button("Resample Audio") | |
| audio_output = gr.Audio(label="Resampled Output") | |
| process_btn.click( | |
| fn=single_file_process, | |
| inputs=[audio_input, target_sr, backend], | |
| outputs=audio_output | |
| ) | |
| # ================================================= | |
| # Batch ZIP Tab | |
| # ================================================= | |
| with gr.Tab("π¦ Batch ZIP"): | |
| gr.Markdown( | |
| """ | |
| ### Batch ZIP Processing | |
| Upload a ZIP file containing audio files. | |
| You will receive a ZIP of **resampled WAV files**. | |
| """ | |
| ) | |
| zip_input = gr.File( | |
| label="Upload ZIP", | |
| file_types=[".zip"] | |
| ) | |
| with gr.Row(): | |
| backend_zip = gr.Radio( | |
| ["librosa", "soundfile", "torchaudio"], | |
| value="librosa", | |
| label="Backend" | |
| ) | |
| target_sr_zip = gr.Dropdown( | |
| [16000, 22050, 44100, 48000], | |
| value=16000, | |
| label="Target Sample Rate (Hz)" | |
| ) | |
| zip_btn = gr.Button("Process ZIP") | |
| zip_output = gr.File(label="Download Resampled ZIP") | |
| zip_btn.click( | |
| fn=batch_process_zip, | |
| inputs=[zip_input, target_sr_zip, backend_zip], | |
| outputs=zip_output | |
| ) | |
| gr.Markdown( | |
| """ | |
| --- | |
| **Output format:** WAV | |
| **CPU-safe:** Yes (HF Spaces compatible) | |
| **Filename format:** | |
| `originalname_backend_samplerate.wav` | |
| """ | |
| ) | |
| demo.launch() | |