|
|
|
import gradio as gr |
|
from numpy import ndarray |
|
|
|
from utils.audio_utils import load_audio_info, format_time, merge_audio_files |
|
|
|
|
|
def update_file_status(audio1_file, audio2_file): |
|
"""Update the status when audio files are uploaded""" |
|
if not audio1_file and not audio2_file: |
|
return "No files uploaded yet", "π Ready to upload audio files" |
|
|
|
total_duration = 0 |
|
valid_files = 0 |
|
file_info = [] |
|
|
|
|
|
if audio1_file: |
|
try: |
|
audio_data, sample_rate, duration = load_audio_info(audio1_file) |
|
if audio_data is not None: |
|
valid_files += 1 |
|
total_duration += duration |
|
file_info.append(f" 1. First Audio: {duration:.1f}s ({sample_rate:,} Hz)") |
|
else: |
|
file_info.append(f" 1. First Audio: β Invalid file") |
|
except: |
|
file_info.append(f" 1. First Audio: β Error loading file") |
|
|
|
|
|
if audio2_file: |
|
try: |
|
audio_data, sample_rate, duration = load_audio_info(audio2_file) |
|
if audio_data is not None: |
|
valid_files += 1 |
|
total_duration += duration |
|
file_info.append(f" 2. Second Audio: {duration:.1f}s ({sample_rate:,} Hz)") |
|
else: |
|
file_info.append(f" 2. Second Audio: β Invalid file") |
|
except: |
|
file_info.append(f" 2. Second Audio: β Error loading file") |
|
|
|
if valid_files == 0: |
|
status = "β No valid audio files found" |
|
details = "Please upload valid audio files (MP3, WAV, FLAC, etc.)" |
|
elif valid_files == 1: |
|
status = f"π 1 valid file uploaded ({format_time(total_duration)})" |
|
details = "Upload one more file to enable merging\n" + "\n".join(file_info) |
|
else: |
|
status = f"π 2 files ready ({format_time(total_duration)} total)" |
|
details = f"Files ready for merging:\n" + "\n".join(file_info) |
|
|
|
return status, details |
|
|
|
|
|
def process_merge(audio1_file, audio2_file) -> tuple[tuple[int, ndarray] | None, str]: |
|
"""Process merging of two audio files""" |
|
if not audio1_file or not audio2_file: |
|
return None, "β Please upload both audio files to merge" |
|
|
|
|
|
file_paths = [audio1_file, audio2_file] |
|
|
|
|
|
result, status = merge_audio_files(file_paths) |
|
|
|
return result, status |
|
|
|
|
|
def reset_everything(): |
|
"""Reset all components to initial state""" |
|
return None, None, None, "No files uploaded yet", "π Ready to upload audio files", "Ready to merge! Upload both audio files to get started." |
|
|
|
|
|
def create_audio_merger_tab(): |
|
"""Create the audio merger tab interface""" |
|
|
|
gr.Markdown("Upload two audio files and merge them in sequence. The first audio will play before the second audio.") |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=2): |
|
|
|
gr.Markdown("### π Upload Audio Files") |
|
|
|
with gr.Row(): |
|
audio1_file = gr.Audio( |
|
label="π΅ First Audio File", |
|
type="filepath", |
|
interactive=True |
|
) |
|
|
|
audio2_file = gr.Audio( |
|
label="π΅ Second Audio File", |
|
type="filepath", |
|
interactive=True |
|
) |
|
|
|
|
|
file_status = gr.Textbox( |
|
value="No files uploaded yet", |
|
label="π Upload Status", |
|
interactive=False, |
|
lines=1 |
|
) |
|
|
|
|
|
file_details = gr.Textbox( |
|
value="π Ready to upload audio files", |
|
label="π File Details", |
|
interactive=False, |
|
lines=4 |
|
) |
|
|
|
with gr.Column(scale=1): |
|
gr.Markdown("### ποΈ Merge Controls") |
|
|
|
merge_btn = gr.Button( |
|
"π΅ Merge Audio Files", |
|
variant="primary", |
|
size="lg" |
|
) |
|
|
|
clear_btn = gr.Button( |
|
"ποΈ Clear All Files", |
|
variant="secondary", |
|
size="lg" |
|
) |
|
|
|
|
|
gr.Markdown(""" |
|
**π Instructions:** |
|
1. **Upload** first audio file (will play first) |
|
2. **Upload** second audio file (will play second) |
|
3. **Merge** files in sequence |
|
4. **Download** the merged result |
|
|
|
**π― Features:** |
|
β’ Automatic sample rate conversion |
|
β’ Stereo to mono conversion |
|
β’ Duration calculations |
|
β’ High-quality WAV output |
|
""") |
|
|
|
|
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
|
|
merge_status = gr.Textbox( |
|
value="Ready to merge! Upload both audio files to get started.", |
|
label="π Merge Status & Details", |
|
interactive=False, |
|
lines=8 |
|
) |
|
|
|
with gr.Column(scale=1): |
|
|
|
merged_audio = gr.Audio( |
|
label="π΅ Merged Audio Result", |
|
type="numpy", |
|
interactive=False |
|
) |
|
|
|
|
|
audio1_file.change( |
|
fn=update_file_status, |
|
inputs=[audio1_file, audio2_file], |
|
outputs=[file_status, file_details] |
|
) |
|
|
|
audio2_file.change( |
|
fn=update_file_status, |
|
inputs=[audio1_file, audio2_file], |
|
outputs=[file_status, file_details] |
|
) |
|
|
|
merge_btn.click( |
|
fn=process_merge, |
|
inputs=[audio1_file, audio2_file], |
|
outputs=[merged_audio, merge_status] |
|
) |
|
|
|
clear_btn.click( |
|
fn=reset_everything, |
|
outputs=[audio1_file, audio2_file, merged_audio, file_status, file_details, merge_status] |
|
) |