Download app.py from cngsm/Minimal: direct link, hf CLI and curl.
- Browser
- Download file 9.37 kB
-
https://huggingface.co/spaces/cngsm/Minimal/resolve/main/app.py
- Command line
-
hf download hf://spaces/cngsm/Minimal/app.py
-
curl -L -o app.py https://huggingface.co/spaces/cngsm/Minimal/resolve/main/app.py
9.37 kB
| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| import gradio as gr | |
| import os | |
| import random | |
| class CineAnalistaV3: | |
| def __init__(self): | |
| self.segment_duration = 8 | |
| self.lighting_types = [ | |
| "iluminação natural suave", "luz lateral dramática", "contraluz artístico", | |
| "iluminação difusa", "luz dura e contrastante", "iluminação dourada" | |
| ] | |
| self.shot_types = [ | |
| "Close-up extremo", "Plano médio", "Plano geral", | |
| "Plano detalhe", "Plano americano", "Grande plano geral" | |
| ] | |
| self.environments = [ | |
| "interior residencial", "ambiente urbano", "espaço natural", | |
| "escritório moderno", "ambiente industrial", "cenário noturno" | |
| ] | |
| self.emotions = [ | |
| "contemplativo", "tenso", "sereno", "ansioso", | |
| "determinado", "melancólico", "esperançoso" | |
| ] | |
| def get_video_info(self, video_path): | |
| """Obtém informações básicas do vídeo""" | |
| try: | |
| # Tentar importar cv2 dinamicamente | |
| import cv2 | |
| cap = cv2.VideoCapture(video_path) | |
| if not cap.isOpened(): | |
| return 30, 1 | |
| fps = cap.get(cv2.CAP_PROP_FPS) or 30 | |
| frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT) or 900 | |
| duration = frame_count / fps | |
| cap.release() | |
| return max(duration, 8), max(int(duration / self.segment_duration), 1) | |
| except Exception as e: | |
| print(f"Erro ao analisar vídeo: {e}") | |
| return 30, 4 # fallback: 30 segundos, 4 segmentos | |
| def generate_segment_analysis(self, segment_num, start_time, end_time): | |
| """Gera análise para um segmento""" | |
| shot_type = random.choice(self.shot_types) | |
| lighting = random.choice(self.lighting_types) | |
| environment = random.choice(self.environments) | |
| emotion = random.choice(self.emotions) | |
| retrato_falado = f"""{shot_type} capturando uma cena em {environment} durante os segundos {start_time:.1f} a {end_time:.1f}. | |
| A composição apresenta {lighting}, criando uma atmosfera {emotion}. | |
| A paleta de cores revela tons equilibrados com texturas naturais bem definidas. | |
| O enquadramento demonstra profundidade de campo cuidadosamente controlada, | |
| destacando elementos principais enquanto mantém o contexto visual harmônico. | |
| A qualidade da imagem sugere captação profissional com atenção aos detalhes técnicos.""" | |
| style = random.choice(["cinematic", "realistic cinematic", "professional"]) | |
| shot = random.choice(["close-up", "medium shot", "wide shot"]) | |
| lighting_en = random.choice(["natural lighting", "dramatic lighting", "soft lighting"]) | |
| veo3_prompt = f"{style} {shot}, {lighting_en}, professional video quality, smooth motion, high detail, {self.segment_duration} seconds" | |
| return retrato_falado, veo3_prompt | |
| def process_video(self, video_path, progress_callback=None): | |
| """Processa o vídeo em segmentos""" | |
| try: | |
| if not video_path or not os.path.exists(video_path): | |
| raise Exception("Arquivo de vídeo não encontrado") | |
| # Obter informações do vídeo | |
| duration, num_segments = self.get_video_info(video_path) | |
| if progress_callback: | |
| progress_callback(0.1, f"Vídeo carregado. Duração: {duration:.1f}s") | |
| results = [] | |
| for i in range(num_segments): | |
| start_time = i * self.segment_duration | |
| end_time = min((i + 1) * self.segment_duration, duration) | |
| if progress_callback: | |
| progress = 0.1 + (0.8 * (i + 1) / num_segments) | |
| progress_callback(progress, f"Analisando Cena {i+1:02d}/{num_segments:02d}") | |
| retrato, prompt = self.generate_segment_analysis(i+1, start_time, end_time) | |
| results.append({ | |
| "cena": i + 1, | |
| "tempo": f"{start_time:.1f}s - {end_time:.1f}s", | |
| "retrato_falado": retrato, | |
| "veo3_prompt": prompt | |
| }) | |
| return results, num_segments | |
| except Exception as e: | |
| raise Exception(f"Erro ao processar vídeo: {str(e)}") | |
| def format_results(results, num_segments): | |
| """Formata os resultados para exibição""" | |
| output = f"# 🎬 Análise Completa - {num_segments} segmentos de 8 segundos\n\n" | |
| for result in results: | |
| output += f"### **Cena {result['cena']:02d}** ({result['tempo']})\n\n" | |
| output += f"**1. Retrato Falado (PT-BR):**\n" | |
| output += f"> *{result['retrato_falado']}*\n\n" | |
| output += f"**2. Prompt para Veo 3 (EN):**\n" | |
| output += f"> *{result['veo3_prompt']}*\n\n" | |
| output += "---\n\n" | |
| return output | |
| def process_video_interface(video_file, progress=gr.Progress()): | |
| """Interface principal para processamento do vídeo""" | |
| if video_file is None: | |
| return "❌ Por favor, faça upload de um vídeo.", "❌ Nenhum vídeo selecionado" | |
| try: | |
| # Obter caminho do arquivo | |
| video_path = video_file.name if hasattr(video_file, 'name') else str(video_file) | |
| print(f"Processando: {video_path}") | |
| # Inicializar analisador | |
| analista = CineAnalistaV3() | |
| # Processar vídeo | |
| def update_progress(prog, desc): | |
| progress(prog, desc=desc) | |
| progress(0.05, desc="Iniciando análise...") | |
| results, num_segments = analista.process_video(video_path, update_progress) | |
| # Formatar resultados | |
| progress(0.95, desc="Formatando resultados...") | |
| formatted_output = format_results(results, num_segments) | |
| progress(1.0, desc="Análise concluída!") | |
| return formatted_output, f"✅ Análise concluída! {num_segments} segmentos processados." | |
| except Exception as e: | |
| error_msg = f"❌ Erro: {str(e)}" | |
| print(f"Erro completo: {e}") | |
| return error_msg, "❌ Falha no processamento" | |
| def create_interface(): | |
| """Cria a interface Gradio""" | |
| with gr.Blocks( | |
| title="🎭 Cine-Analista V.3", | |
| theme=gr.themes.Soft() | |
| ) as interface: | |
| # Header | |
| gr.Markdown(""" | |
| # 🎭 Cine-Analista V.3 | |
| ### Análise Forense de Vídeos & Geração de Prompts Veo 3 | |
| **Decompõe vídeos em segmentos de 8 segundos com descrições cinematográficas detalhadas** | |
| """) | |
| # Instruções | |
| gr.Markdown(""" | |
| 📋 **Como usar:** | |
| 1. **Upload**: Envie seu vídeo (MP4, AVI, MOV, WebM) | |
| 2. **Análise**: Clique em "Iniciar Análise" | |
| 3. **Resultados**: Visualize as descrições por segmento | |
| """) | |
| # Interface principal | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| video_input = gr.Video(label="📹 Upload do Vídeo") | |
| analyze_btn = gr.Button( | |
| "🎬 Iniciar Análise Cinematográfica", | |
| variant="primary", | |
| size="lg" | |
| ) | |
| status_msg = gr.Textbox( | |
| label="📊 Status", | |
| interactive=False, | |
| lines=2 | |
| ) | |
| with gr.Column(scale=2): | |
| results_output = gr.Markdown( | |
| label="📝 Resultados da Análise", | |
| value="🎬 **Aguardando vídeo...**\n\nFaça upload e clique em 'Iniciar Análise'." | |
| ) | |
| # Event handler | |
| analyze_btn.click( | |
| fn=process_video_interface, | |
| inputs=[video_input], | |
| outputs=[results_output, status_msg], | |
| show_progress=True | |
| ) | |
| # Exemplo | |
| gr.Markdown(""" | |
| --- | |
| ### 🎯 Exemplo de Saída: | |
| **Cena 01** (0.0s - 8.0s) | |
| **1. Retrato Falado (PT-BR):** | |
| > *Close-up extremo capturando uma cena em ambiente urbano. A composição apresenta iluminação lateral dramática, criando uma atmosfera contemplativa...* | |
| **2. Prompt para Veo 3 (EN):** | |
| > *Cinematic close-up, dramatic lighting, professional video quality, 8 seconds* | |
| """) | |
| # Footer | |
| gr.Markdown(""" | |
| --- | |
| <div style="text-align: center; color: #666;"> | |
| <p>🎭 <strong>Cine-Analista V.3</strong> - Análise cinematográfica profissional</p> | |
| </div> | |
| """) | |
| return interface | |
| def main(): | |
| """Função principal""" | |
| try: | |
| print("🎭 Iniciando Cine-Analista V.3...") | |
| app = create_interface() | |
| app.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=True, | |
| show_error=True | |
| ) | |
| except Exception as e: | |
| print(f"Erro ao iniciar: {e}") | |
| raise | |
| if __name__ == "__main__": | |
| main() |