File size: 9,373 Bytes
6ccf482 |
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 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
#!/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() |