import gradio as gr
from moviepy.editor import VideoFileClip, concatenate_videoclips
import numpy as np
from scipy.io import wavfile
import tempfile
import os
from pathlib import Path

def detect_silence(audio_array, sample_rate, threshold=0.01, min_silence_len=1000):
    """Detecta períodos de silêncio no áudio"""
    # Converte o threshold para amplitude
    amplitude_threshold = threshold * np.max(np.abs(audio_array))
    
    # Calcula a energia do áudio
    energy = np.abs(audio_array)
    if len(energy.shape) > 1:
        energy = np.mean(energy, axis=1)
    
    # Encontra regiões não silenciosas
    is_sound = energy > amplitude_threshold
    
    # Converte frames para segundos
    frame_length = int(sample_rate * (min_silence_len / 1000))
    
    # Suaviza a detecção para evitar cortes muito curtos
    sound_chunks = []
    start = None
    
    for i in range(len(is_sound)):
        if start is None and is_sound[i]:
            start = i
        elif start is not None and not is_sound[i]:
            if i - start > frame_length:
                sound_chunks.append((start / sample_rate, i / sample_rate))
            start = None
            
    if start is not None:
        sound_chunks.append((start / sample_rate, len(is_sound) / sample_rate))
        
    return sound_chunks

def process_video(video_path, threshold=0.01, min_silence_len=1000):
    """Remove silêncio do vídeo"""
    # Carrega o vídeo
    video = VideoFileClip(video_path)
    
    # Extrai o áudio para análise
    audio_array = video.audio.to_soundarray()
    sample_rate = video.audio.fps
    
    # Detecta regiões não silenciosas
    sound_chunks = detect_silence(audio_array, sample_rate, threshold, min_silence_len)
    
    if not sound_chunks:
        video.close()
        return video_path
        
    # Corta e concatena os segmentos não silenciosos
    clips = []
    for start, end in sound_chunks:
        clip = video.subclip(start, end)
        clips.append(clip)
    
    # Concatena os clips
    final_clip = concatenate_videoclips(clips)
    
    # Salva o resultado
    output_path = str(Path(video_path).parent / f"processed_{Path(video_path).name}")
    final_clip.write_videofile(output_path)
    
    # Limpa os recursos
    video.close()
    final_clip.close()
    for clip in clips:
        clip.close()
    
    return output_path

def remove_silence(video_input, silence_duration, silence_threshold):
    """Interface para remoção normal de silêncio"""
    try:
        if video_input is None:
            raise ValueError("Por favor, faça upload de um vídeo")
        
        # Converte o threshold de dB para amplitude relativa
        amplitude_threshold = 10 ** (silence_threshold / 20)
        
        return process_video(
            video_input,
            threshold=amplitude_threshold,
            min_silence_len=int(silence_duration * 1000)
        )
    except Exception as e:
        gr.Error(str(e))
        return None

def remove_max_silence(video_input):
    """Interface para remoção máxima de silêncio"""
    try:
        if video_input is None:
            raise ValueError("Por favor, faça upload de um vídeo")
        
        # Configurações agressivas para máxima remoção
        return process_video(
            video_input,
            threshold=0.05,  # Mais sensível ao som
            min_silence_len=100  # Remove silêncios mais curtos
        )
    except Exception as e:
        gr.Error(str(e))
        return None

# Interface Gradio
with gr.Blocks(title="Removedor de Silêncio de Vídeos") as app:
    gr.Markdown("# Removedor de Silêncio de Vídeos")
    
    with gr.Row():
        with gr.Column():
            video_input = gr.Video(
                label="Selecione ou Arraste o Vídeo"
            )
            
            with gr.Row():
                remove_max_btn = gr.Button("🔇 Remover 100% do Silêncio", variant="primary")
                remove_custom_btn = gr.Button("Remover Silêncio Personalizado")
            
            with gr.Group():
                gr.Markdown("### Configurações Personalizadas")
                silence_duration = gr.Slider(
                    minimum=0.1,
                    maximum=5.0,
                    value=1.0,
                    step=0.1,
                    label="Duração Mínima do Silêncio (segundos)"
                )
                silence_threshold = gr.Slider(
                    minimum=-60,
                    maximum=-20,
                    value=-40,
                    step=1,
                    label="Limite de Silêncio (dB)"
                )

    with gr.Row():
        video_output = gr.Video(label="Vídeo Processado")
    
    # Event handlers
    remove_max_btn.click(
        fn=remove_max_silence,
        inputs=[video_input],
        outputs=[video_output]
    )
    
    remove_custom_btn.click(
        fn=remove_silence,
        inputs=[
            video_input,
            silence_duration,
            silence_threshold
        ],
        outputs=[video_output]
    )

if __name__ == "__main__":
    app.launch(show_error=True)