AudioEditor / tabs /audio_cutter_tab.py
Ahmet Emre Şafak
initial commit
0a0ea7b
# tabs/audio_cutter_tab.py - Audio Cutter Tab Component
import gradio as gr
from numpy import ndarray
from utils.audio_utils import cut_audio, format_time, load_audio_info
def update_duration_info(audio_file):
"""Update the duration info when a new file is uploaded
This function is designed for UI purposes only to update Gradio interface elements
when a new audio file is uploaded. It should NOT be used by agents or automated
systems as it returns Gradio update objects for slider components. Agents should
use the underlying audio utility functions directly instead.
"""
print("Logging audiofile")
print(audio_file)
if audio_file is None:
return "No file uploaded", "Sample rate: N/A", gr.update(maximum=100), gr.update(maximum=100)
# Load audio info
audio_data, sample_rate, duration = load_audio_info(audio_file)
if duration is None:
return "❌ Could not read audio file", "Sample rate: N/A", gr.update(maximum=100), gr.update(maximum=100)
duration_text = f"πŸ“ File duration: {format_time(duration)} ({duration:.1f} seconds)"
sample_rate_text = f"🎡 Sample rate: {sample_rate:,} Hz"
# Update sliders with new maximum
return duration_text, sample_rate_text, gr.update(maximum=duration, value=0), gr.update(maximum=duration,
value=min(30, duration))
def process_cut_audio(audio_file: str, _start_time: float, _end_time: float) -> tuple[tuple[int | float, ndarray] | None, str]:
"""Process audio cutting to extract a segment from an audio file.
This function loads an audio file, validates the time parameters, and cuts out
a specific segment between the start and end times. It handles various audio
formats and provides detailed error messages for troubleshooting.
Args:
audio_file (str): Full URL to the input audio file to be cut
(supports MP3, WAV, M4A, FLAC, OGG, and other common formats)
_start_time (float): Start time in seconds where the cut should begin
(will be clamped to 0 if negative)
_end_time (float): End time in seconds where the cut should end
(will be clamped to file duration if exceeds it)
Returns:
tuple: A tuple containing:
- First element: Either a tuple of (sample_rate: int, audio_data: array)
for the cut audio segment, or None if an error occurred
- Second element: A status message string indicating success with details
or error information
Example:
result, status = process_cut_audio("/path/to/audio.mp3", 10.5, 25.0)
if result is not None:
sample_rate, audio_data = result
print(f"Cut successful: {status}")
else:
print(f"Error: {status}")
Note:
- Time parameters are automatically validated and clamped to valid ranges
- Start time must be less than end time after validation
- Output audio data maintains the original sample rate
- Function returns user-friendly status messages for UI display
"""
if audio_file is None:
return None, "Please upload an audio file first."
try:
# Load audio data and sample rate
audio_data, sample_rate, duration = load_audio_info(audio_file)
if audio_data is None:
return None, "❌ Could not load audio file."
# Validate time inputs
if _start_time < 0:
_start_time = 0
if _end_time > duration:
_end_time = duration
if _start_time >= _end_time:
return None, f"Start time ({_start_time:.1f}s) must be less than end time ({_end_time:.1f}s)"
# Convert seconds to milliseconds for the cut_audio function
start_millis = int(_start_time * 1000)
end_millis = int(_end_time * 1000)
# Cut the audio using your function
cut_audio_data = cut_audio(audio_data, sample_rate, start_millis, end_millis)
# Create status message
cut_duration = (end_millis - start_millis) / 1000.0
status = f"βœ… Audio cut successfully! Duration: {format_time(cut_duration)} (from {format_time(_start_time)} to {format_time(_end_time)})"
return (sample_rate, cut_audio_data,), status
except Exception as e:
return None, f"❌ Error cutting audio: {str(e)}"
def create_audio_cutter_tab():
"""Create the audio cutter tab interface"""
gr.Markdown("Upload an audio file and specify the start and end times to cut a segment.")
with gr.Row():
with gr.Column(scale=2):
# File upload
audio_input = gr.Audio(
label="πŸ“€ Upload Audio File",
type="filepath"
)
# Audio info
duration_info = gr.Markdown("No file uploaded")
sample_rate_info = gr.Markdown("Sample rate: N/A")
# Time controls
with gr.Row():
start_time = gr.Slider(
minimum=0,
maximum=100,
value=0,
step=0.1,
label="⏱️ Start Time (seconds)",
info="When to start cutting"
)
end_time = gr.Slider(
minimum=0,
maximum=100,
value=30,
step=0.1,
label="⏱️ End Time (seconds)",
info="When to stop cutting"
)
# Cut button
cut_btn = gr.Button("βœ‚οΈ Cut Audio", variant="primary", size="lg")
# Status message
status_msg = gr.Markdown("")
with gr.Column(scale=1):
# Output audio
audio_output = gr.Audio(
label="🎧 Cut Audio Result",
type="filepath"
)
# Download info
gr.Markdown(
"πŸ’Ύ **Download:** Right-click the audio player above and select 'Save audio as...' to download the cut audio file.")
# Event handlers
audio_input.change(
fn=update_duration_info,
inputs=[audio_input],
outputs=[duration_info, sample_rate_info, start_time, end_time]
)
cut_btn.click(
fn=process_cut_audio,
inputs=[audio_input, start_time, end_time],
outputs=[audio_output, status_msg]
)
# Usage tips
with gr.Accordion("πŸ“‹ Usage Tips", open=False):
gr.Markdown("""
**Supported formats:** MP3, WAV, M4A, FLAC, OGG, and more
**How to use:**
1. Upload your audio file
2. Check the duration and sample rate information
3. Use the sliders to set start and end times
4. Click "Cut Audio" to process
5. Play the result and download if satisfied
**Tips:**
- The sliders will automatically adjust to your file's duration
- Sample rate is preserved in the output file
- You can fine-tune times using the slider or type exact values
- Output format is WAV for best compatibility
""")