# app.py import gradio as gr from pytube import YouTube import moviepy.editor as mp import os import re import time # Para nomes de arquivos únicos # Função para limpar o nome do arquivo def sanitize_filename(filename): # Remove caracteres inválidos para nomes de arquivo no Windows/Linux/Mac sanitized = re.sub(r'[\\/*?:"<>|]', "", filename) # Limita o comprimento para evitar problemas return sanitized[:100] # Função principal que baixa e converte def baixar_audio_youtube(youtube_url): try: print(f"Processando URL: {youtube_url}") yt = YouTube(youtube_url) # 1. Filtrar e selecionar o melhor stream de áudio # Prioriza streams 'mp4' ou 'webm' que moviepy geralmente lida bem audio_stream = yt.streams.filter(only_audio=True).order_by('abr').desc().first() if not audio_stream: print("Erro: Nenhum stream de áudio encontrado.") return "Erro: Nenhuma stream de áudio encontrada para este vídeo.", None print(f"Título: {yt.title}") print(f"Stream selecionado: {audio_stream}") # 2. Baixar o áudio print("Baixando áudio...") # Cria um nome de arquivo temporário seguro e único temp_filename_base = sanitize_filename(yt.title) timestamp = int(time.time()) # Usa a extensão correta do stream baixado (geralmente mp4 ou webm para áudio) ext = audio_stream.mime_type.split('/')[-1] temp_download_path = f"{temp_filename_base}_{timestamp}.{ext}" audio_stream.download(filename=temp_download_path) print(f"Áudio baixado para: {temp_download_path}") # 3. Converter para MP3 usando moviepy print("Convertendo para MP3...") mp3_filename = f"{temp_filename_base}_{timestamp}.mp3" # Garante que o arquivo MP3 de destino não exista (embora improvável com timestamp) if os.path.exists(mp3_filename): os.remove(mp3_filename) audio_clip = mp.AudioFileClip(temp_download_path) # codec='libmp3lame' é geralmente o encoder padrão e de boa qualidade para MP3 audio_clip.write_audiofile(mp3_filename, codec='libmp3lame') audio_clip.close() # Libera o arquivo print(f"Convertido com sucesso para: {mp3_filename}") # 4. Limpar o arquivo temporário baixado try: os.remove(temp_download_path) print(f"Arquivo temporário removido: {temp_download_path}") except OSError as e: print(f"Aviso: Não foi possível remover o arquivo temporário {temp_download_path}. Erro: {e}") # 5. Retornar o caminho para o arquivo MP3 para o Gradio # Gradio serve o arquivo a partir do diretório onde o script roda return f"Sucesso! Áudio '{yt.title}' pronto.", mp3_filename except Exception as e: print(f"Ocorreu um erro: {e}") # Tenta limpar arquivos parciais se existirem if 'temp_download_path' in locals() and os.path.exists(temp_download_path): try: os.remove(temp_download_path) except OSError: pass # Ignora erro na limpeza if 'mp3_filename' in locals() and os.path.exists(mp3_filename): try: os.remove(mp3_filename) except OSError: pass # Ignora erro na limpeza return f"Ocorreu um erro: {str(e)}. Verifique o link ou tente novamente.", None # --- Interface Gradio --- with gr.Blocks() as iface: gr.Markdown( """ # Baixar Áudio do YouTube em MP3 Cole o link (URL) de um vídeo do YouTube abaixo para extrair e baixar o áudio em formato MP3. """ ) with gr.Row(): youtube_link_input = gr.Textbox(label="Link do Vídeo do YouTube", placeholder="Ex: https://www.youtube.com/watch?v=...") with gr.Row(): submit_button = gr.Button("Baixar e Converter para MP3") with gr.Row(): status_output = gr.Textbox(label="Status", interactive=False) with gr.Row(): mp3_output_file = gr.File(label="Download do Arquivo MP3") # Use gr.File para permitir download submit_button.click( fn=baixar_audio_youtube, inputs=youtube_link_input, outputs=[status_output, mp3_output_file] # Mapeia os retornos para os componentes de saída ) gr.Examples( [["https://www.youtube.com/watch?v=dQw4w9WgXcQ"], ["https://www.youtube.com/watch?v=kJQP7kiw5Fk"]], inputs=youtube_link_input ) # Lançar a interface (necessário para rodar localmente ou no Hugging Face Spaces) if __name__ == "__main__": iface.launch()