# tabs/audio_merger_tab.py - Audio Merger Tab Component 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 = [] # Check first audio file 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") # Check second audio 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" # Create file paths list for the merge function file_paths = [audio1_file, audio2_file] # Call the merge function 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): # Audio Upload Section 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 file_status = gr.Textbox( value="No files uploaded yet", label="📊 Upload Status", interactive=False, lines=1 ) # Detailed file info 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" ) # Instructions 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 """) # Results section with gr.Row(): with gr.Column(scale=1): # Status output 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): # Audio output merged_audio = gr.Audio( label="🎵 Merged Audio Result", type="numpy", interactive=False ) # Event handlers 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] )