pcdoido2 commited on
Commit
015967f
·
verified ·
1 Parent(s): be5f942

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +150 -64
app.py CHANGED
@@ -186,67 +186,153 @@ if st.button("Gerar Vídeo(s)"):
186
  st.error(f"Erro inesperado: {str(e)}")
187
  finally:
188
  shutil.rmtree(temp_dir)
189
- st.markdown("---")
190
- st.subheader("🔐 Admin Enviar cortes para o sistema (opcional)")
191
-
192
- # Mesma senha do seu primeiro código: base64 de "admin123"
193
- SENHA_CODIFICADA = "YWRtaW4xMjM="
194
-
195
- if "autenticado_admin" not in st.session_state:
196
- st.session_state.autenticado_admin = False
197
-
198
- if not st.session_state.autenticado_admin:
199
- colA, colB = st.columns([3, 1])
200
- with colA:
201
- senha_input = st.text_input("Senha do Admin:", type="password", help="Dica: é a mesma do outro app 😉")
202
- with colB:
203
- if st.button("Entrar"):
204
- if base64.b64encode(senha_input.encode()).decode() == SENHA_CODIFICADA:
205
- st.session_state.autenticado_admin = True
206
- st.success("✅ Acesso liberado!")
207
- else:
208
- st.error(" Senha incorreta.")
209
- else:
210
- st.success("✅ Você está autenticado.")
211
-
212
- cat_admin = st.selectbox("Categoria para salvar os cortes:", CATEGORIAS, key="cat_admin_upload")
213
- pasta_admin = os.path.join(BASE_ASSETS, cat_admin, "cortes")
214
- st.caption(f"Pasta de destino: `{pasta_admin}`")
215
-
216
- arquivos_admin = st.file_uploader(
217
- "Envie os arquivos de CORTES (.mp4) para esta categoria",
218
- type=["mp4"], accept_multiple_files=True, key="admin_uploader"
219
- )
220
-
221
- if arquivos_admin:
222
- with st.spinner("⏳ Processando e padronizando cortes..."):
223
- for f in arquivos_admin:
224
- ext = os.path.splitext(f.name)[1].lower()
225
- nome_aleatorio = f"{random.randint(1000000, 9999999)}{ext}"
226
- temp_in = os.path.join(tempfile.gettempdir(), f"adm_input_{nome_aleatorio}")
227
- with open(temp_in, "wb") as out:
228
- out.write(f.read())
229
-
230
- final_out = os.path.join(pasta_admin, nome_aleatorio)
231
-
232
- # Padroniza o vídeo (igual ao seu primeiro app)
233
- subprocess.run([
234
- "ffmpeg", "-i", temp_in,
235
- "-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2,fps=30",
236
- "-c:v", "libx264", "-preset", "ultrafast", "-crf", "25",
237
- "-y", final_out
238
- ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
239
-
240
- os.remove(temp_in)
241
-
242
- st.success("✅ Cortes enviados, padronizados e salvos com sucesso!")
243
-
244
- # Listagem e exclusão
245
- st.write("Arquivos existentes nesta categoria:")
246
- try:
247
- arquivos_existentes = sorted([f for f in os.listdir(pasta_admin) if f.lower().endswith(".mp4")])
248
- except FileNotFoundError:
249
- arquivos_existentes = []
250
-
251
- if not arquivos_existentes:
252
- st.info("Nenhum arquivo encontrado nesta categoria.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  st.error(f"Erro inesperado: {str(e)}")
187
  finally:
188
  shutil.rmtree(temp_dir)
189
+ # Upload dos vídeos (MANTIDO)
190
+ cortes = st.file_uploader("Envie os vídeos de cortes", type=["mp4"], accept_multiple_files=True)
191
+
192
+ # Configurações (MANTIDO)
193
+ num_videos_finais = st.number_input("Quantos vídeos finais gerar?", min_value=1, max_value=10, value=1)
194
+ duracao_final = st.number_input("Duração final do vídeo (em segundos)", min_value=10, max_value=300, value=30)
195
+
196
+ # Min e Max duração dos cortes (MANTIDO)
197
+ duracao_min = st.slider("Duração mínima de cada corte (s)", 1, 30, 3)
198
+ duracao_max = st.slider("Duração máxima de cada corte (s)", 1, 60, 5)
199
+ if duracao_min > duracao_max:
200
+ st.warning("⚠️ A duração mínima não pode ser maior que a máxima.")
201
+
202
+ # Corte lateral e zoom (MANTIDO)
203
+ corte_lateral = st.slider("Corte lateral (%)", 0, 50, 0, 5)
204
+ zoom = st.slider("Zoom Central (1.0 = normal)", 1.0, 2.0, 1.0, 0.1)
205
+
206
+ # Velocidades e qualidade (MANTIDO)
207
+ velocidade_cortes = st.slider("Velocidade dos cortes", 0.5, 2.0, 1.0, 0.1)
208
+ velocidade_final = st.slider("Velocidade final do vídeo", 0.5, 2.0, 1.0, 0.1)
209
+ crf_value = st.slider("Qualidade CRF (menor = melhor qualidade)", 18, 30, 18)
210
+
211
+ # Outros (MANTIDO)
212
+ st.write("### Outros")
213
+ ativar_espelhar = st.checkbox("Espelhar Vídeo", value=True)
214
+ ativar_filtro_cor = st.checkbox("Filtro de Cor (Contraste/Saturação)", value=True)
215
+
216
+ # Botão principal (MANTIDO, mas agora combinando uploads + salvos)
217
+ if st.button("Gerar Vídeo(s)"):
218
+ # Verifica se temos pelo menos upload OU salvos
219
+ if not cortes and len(cortes_salvos_paths) == 0:
220
+ st.error("❌ Envie vídeos OU selecione uma categoria com cortes salvos para continuar.")
221
+ else:
222
+ with st.spinner('🎥 Seu vídeo está sendo gerado...'):
223
+ progresso = st.progress(0)
224
+ temp_dir = tempfile.mkdtemp()
225
+
226
+ try:
227
+ # === PREPARAR LISTA FINAL DE ARQUIVOS DE CORTE ===
228
+ cortes_names = []
229
+
230
+ # 1) Arquivos enviados (MANTIDO)
231
+ if cortes:
232
+ for idx, corte in enumerate(cortes):
233
+ nome = os.path.join(temp_dir, f"corte_{idx}_{random.randint(1000,9999)}.mp4")
234
+ with open(nome, "wb") as f:
235
+ f.write(corte.read())
236
+ cortes_names.append(nome)
237
+
238
+ # 2) Arquivos salvos na categoria (NOVO – usamos os caminhos diretamente)
239
+ if len(cortes_salvos_paths) > 0:
240
+ cortes_names.extend(cortes_salvos_paths)
241
+
242
+ if len(cortes_names) == 0:
243
+ st.error("❌ Não há cortes disponíveis após combinar uploads e salvos.")
244
+ shutil.rmtree(temp_dir)
245
+ st.stop()
246
+
247
+ progresso.progress(10)
248
+
249
+ for n in range(num_videos_finais):
250
+ cortes_prontos = []
251
+ random.shuffle(cortes_names)
252
+ progresso.progress(10 + int(20 * (n / num_videos_finais)))
253
+
254
+ tempo_total = 0
255
+ while tempo_total < duracao_final:
256
+ for c in cortes_names:
257
+ dur_proc = subprocess.run([
258
+ "ffprobe", "-v", "error", "-show_entries", "format=duration",
259
+ "-of", "default=noprint_wrappers=1:nokey=1", c
260
+ ], stdout=subprocess.PIPE)
261
+
262
+ dur = dur_proc.stdout.decode().strip()
263
+ try:
264
+ d = float(dur)
265
+ dur_aleatoria = random.uniform(duracao_min, duracao_max)
266
+ if d > dur_aleatoria:
267
+ ini = random.uniform(0, d - dur_aleatoria)
268
+ out = os.path.join(temp_dir, f"cut_{n}_{random.randint(1000,9999)}.mp4")
269
+ subprocess.run([
270
+ "ffmpeg", "-ss", str(ini), "-i", c, "-t", str(dur_aleatoria),
271
+ "-an", "-c:v", "libx264", "-preset", "ultrafast", "-crf", "30", out
272
+ ], check=True, stderr=subprocess.PIPE)
273
+ cortes_prontos.append(out)
274
+ tempo_total += dur_aleatoria / velocidade_cortes
275
+ if tempo_total >= duracao_final:
276
+ break
277
+ except:
278
+ continue
279
+
280
+ lista = os.path.join(temp_dir, f"lista_{n}.txt")
281
+ with open(lista, "w") as f:
282
+ for c in cortes_prontos:
283
+ f.write(f"file '{c}'\n")
284
+
285
+ video_raw = os.path.join(temp_dir, f"video_raw_{n}.mp4")
286
+ subprocess.run([
287
+ "ffmpeg", "-f", "concat", "-safe", "0", "-i", lista, "-c:v", "libx264",
288
+ "-preset", "ultrafast", "-crf", "30", video_raw
289
+ ], check=True, stderr=subprocess.PIPE)
290
+
291
+ progresso.progress(40 + int(20 * (n / num_videos_finais)))
292
+
293
+ filtros_main = []
294
+
295
+ if corte_lateral > 0:
296
+ fator = (100 - corte_lateral) / 100
297
+ filtros_main.append(f"crop=iw*{fator}:ih:(iw-iw*{fator})/2:0")
298
+
299
+ if zoom != 1.0:
300
+ filtros_main.append(f"scale=iw*{zoom}:ih*{zoom},crop=iw/{zoom}:ih/{zoom}")
301
+
302
+ filtros_main.append(f"setpts=PTS/{velocidade_cortes}")
303
+ if ativar_espelhar:
304
+ filtros_main.append("hflip")
305
+ if ativar_filtro_cor:
306
+ filtros_main.append("eq=contrast=1.1:saturation=1.2")
307
+
308
+ filtros_main.append("pad=ceil(iw/2)*2:ceil(ih/2)*2")
309
+ filtro_final = ",".join(filtros_main)
310
+
311
+ video_editado = os.path.join(temp_dir, f"video_editado_{n}.mp4")
312
+ subprocess.run([
313
+ "ffmpeg", "-i", video_raw, "-vf", filtro_final,
314
+ "-c:v", "libx264", "-preset", "ultrafast", "-crf", str(crf_value),
315
+ video_editado
316
+ ], check=True, stderr=subprocess.PIPE)
317
+
318
+ video_final = f"video_final_{n}_{int(time.time())}.mp4"
319
+ subprocess.run([
320
+ "ffmpeg", "-i", video_editado, "-filter:v", f"setpts=PTS/{velocidade_final}",
321
+ "-t", str(duracao_final), "-c:v", "libx264", "-preset", "ultrafast",
322
+ "-crf", str(crf_value), "-map_metadata", "-1", "-movflags", "+faststart", video_final
323
+ ], check=True, stderr=subprocess.PIPE)
324
+
325
+ progresso.progress(90 + int(10 * (n / num_videos_finais)))
326
+ st.video(video_final)
327
+ with open(video_final, "rb") as f:
328
+ st.download_button(f"📅 Baixar Vídeo {n+1}", f, file_name=video_final)
329
+
330
+ progresso.progress(100)
331
+ st.success("✅ Todos os vídeos foram gerados com sucesso!")
332
+
333
+ except subprocess.CalledProcessError as e:
334
+ st.error(f"Erro durante processamento: {e.stderr.decode()}")
335
+ except Exception as e:
336
+ st.error(f"Erro inesperado: {str(e)}")
337
+ finally:
338
+ shutil.rmtree(temp_dir)