File size: 7,275 Bytes
0a0ea7b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# 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
        """)