pcdoido2 commited on
Commit
c22f4e0
·
verified ·
1 Parent(s): 1bedb6c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +32 -111
app.py CHANGED
@@ -21,7 +21,6 @@ for cat in CATEGORIAS:
21
  os.makedirs(os.path.join(BASE_ASSETS, cat, "cortes"), exist_ok=True)
22
  os.makedirs(os.path.join(BASE_ASSETS, cat, "tutoriais"), exist_ok=True)
23
  os.makedirs(os.path.join(BASE_SALVOS, cat), exist_ok=True)
24
-
25
  if pagina == "🎬 Gerador de Vídeo":
26
  st.title("🎥 TikTok Video Generator - PRO")
27
 
@@ -57,7 +56,7 @@ if pagina == "🎬 Gerador de Vídeo":
57
  zoom = st.slider("Zoom", 1.0, 2.0, 1.0, 0.1)
58
  blur_strength = st.slider("Blur no fundo", 1, 50, 10)
59
  velocidade_final = st.slider("Velocidade final", 0.5, 2.0, 1.0, 0.1)
60
- crf_value = st.slider("Qualidade CRF", 18, 30, 18)
61
 
62
  st.write("## Texto no Vídeo")
63
  ativar_texto = st.checkbox("Ativar texto")
@@ -80,24 +79,7 @@ if pagina == "🎬 Gerador de Vídeo":
80
  with st.expander("🎨 Filtros Avançados"):
81
  ativar_brilho = st.checkbox("Brilho extra")
82
  ativar_contraste = st.checkbox("Contraste forte")
83
- ativar_colorboost = st.checkbox("Cores intensas")
84
- ativar_azul = st.checkbox("Filtro Azul")
85
- ativar_quente = st.checkbox("Filtro Quente")
86
- ativar_desaturar = st.checkbox("Desaturar")
87
- ativar_vhs = st.checkbox("Efeito VHS")
88
-
89
- st.write("## Outros efeitos")
90
- ativar_espelhar = st.checkbox("Espelhar", True)
91
- ativar_filtro_cor = st.checkbox("Ajuste de cor", True)
92
- remover_borda = st.checkbox("Remover borda")
93
- tamanho_borda = st.slider("Tamanho da borda (px)", 0, 200, 0, 5)
94
-
95
- ativar_borda_personalizada = st.checkbox("Borda personalizada")
96
- if ativar_borda_personalizada:
97
- cor_borda = st.color_picker("Cor da borda", "#FF0000")
98
- animacao_borda = st.selectbox("Animação", ["Nenhuma", "Pulsante", "Cor Animada", "Neon", "Ondulada"])
99
-
100
- salvar_no_gerenciador = st.checkbox("Salvar no gerenciador de arquivos")
101
  if st.button("Gerar Vídeo(s)", key="gerar_video_usuario"):
102
  with st.spinner("🎬 Processando..."):
103
  progresso = st.progress(0)
@@ -139,7 +121,7 @@ if pagina == "🎬 Gerador de Vídeo":
139
  ativar_blur_fundo_n = ativar_blur_fundo
140
  ativar_espelhar_n = ativar_espelhar
141
 
142
- # Etapa 1 - Fundo com ponto aleatório
143
  if usar_fundo:
144
  fundo_origem = random.choice(cortes_names)
145
  fundo_convertido = os.path.join(temp_dir, f"fundo_convertido_{n}.mp4")
@@ -159,20 +141,20 @@ if pagina == "🎬 Gerador de Vídeo":
159
  "-vf",
160
  "scale='if(gt(iw/ih,720/1280),max(720,iw),-2)':'if(gt(iw/ih,720/1280),-2,max(1280,ih))',"
161
  "scale=720:1280:force_original_aspect_ratio=increase,crop=720:1280,fps=30",
162
- "-preset", "ultrafast", "-crf", "25",
163
  fundo_convertido
164
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
165
  else:
166
  fundo_convertido = os.path.join(temp_dir, f"fundo_vazio_{n}.mp4")
167
  subprocess.run([
168
  "ffmpeg", "-f", "lavfi", "-i", f"color=color=black:size=720x1280:d={duracao_final}:rate=30",
169
- "-c:v", "libx264", "-t", str(duracao_final), "-preset", "ultrafast", "-crf", "25",
170
  fundo_convertido
171
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
172
  etapa_atual += 1
173
  atualizar_barra(n, etapa_atual, num_videos_finais, total_etapas)
174
 
175
- # Etapa 2 - Cortes
176
  tentativas = 0
177
  while tempo_total < duracao_final and tentativas < 100:
178
  tentativas += 1
@@ -197,7 +179,7 @@ if pagina == "🎬 Gerador de Vídeo":
197
  subprocess.run([
198
  "ffmpeg", "-ss", str(ini), "-i", c, "-t", str(duracao_aleatoria),
199
  "-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2",
200
- "-an", "-c:v", "libx264", "-preset", "ultrafast", "-crf", "30", out
201
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
202
  cortes_prontos.append(out)
203
  cortes_usados.append((c, ini, duracao_aleatoria))
@@ -215,96 +197,45 @@ if pagina == "🎬 Gerador de Vídeo":
215
  video_raw = os.path.join(temp_dir, f"video_raw_{n}.mp4")
216
  subprocess.run([
217
  "ffmpeg", "-f", "concat", "-safe", "0", "-i", lista,
218
- "-c:v", "libx264", "-preset", "ultrafast", "-crf", "30", video_raw
219
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
220
-
221
  etapa_atual += 1
222
  atualizar_barra(n, etapa_atual, num_videos_finais, total_etapas)
223
 
224
- # Etapa 3 - Filtros e Efeitos
225
- filtros_main = ["scale=720:1280:force_original_aspect_ratio=decrease"]
226
- if zoom_n != 1.0:
227
- filtros_main.append(f"scale=iw*{zoom_n}:ih*{zoom_n}")
228
- if ativar_espelhar_n:
229
- filtros_main.append("hflip")
230
- if remover_borda_n and tamanho_borda_n > 0:
231
- filtros_main.append(f"crop=in_w-{tamanho_borda_n*2}:in_h-{tamanho_borda_n*2}")
232
- if ativar_filtro_cor:
233
- filtros_main.append("eq=contrast=1.1:saturation=1.2")
234
- filtros_main.append("scale=trunc(iw/2)*2:trunc(ih/2)*2")
235
- if ativar_borda_personalizada:
236
- cor_ffmpeg = f"0x{cor_borda.lstrip('#')}FF"
237
- filtros_main.append(f"drawbox=x=0:y=0:w=iw:h=ih:color={cor_ffmpeg}:t=5")
238
-
239
- filtro_complex = f"[0:v]scale=720:1280:force_original_aspect_ratio=increase,crop=720:1280"
240
- if ativar_blur_fundo_n:
241
- filtro_complex += f",boxblur={blur_strength_n}:1"
242
- if ativar_sepia:
243
- filtro_complex += ",colorchannelmixer=.393:.769:.189:0:.349:.686:.168:0:.272:.534:.131"
244
- if ativar_granulado:
245
- filtro_complex += ",noise=alls=20:allf=t+u"
246
- if ativar_pb:
247
- filtro_complex += ",hue=s=0.3"
248
- if ativar_vignette:
249
- filtro_complex += ",vignette"
250
- if ativar_brilho:
251
- filtro_complex += ",eq=brightness=0.05"
252
- if ativar_contraste:
253
- filtro_complex += ",eq=contrast=1.3"
254
- if ativar_colorboost:
255
- filtro_complex += ",eq=saturation=1.5"
256
- if ativar_azul:
257
- filtro_complex += ",colorbalance=bs=0.5"
258
- if ativar_quente:
259
- filtro_complex += ",colorbalance=rs=0.3"
260
- if ativar_desaturar:
261
- filtro_complex += ",hue=s=0.5"
262
- if ativar_vhs:
263
- filtro_complex += ",noise=alls=10:allf=t+u,format=yuv420p"
264
-
265
- filtro_complex += "[blur];"
266
- filtro_complex += f"[1:v]{','.join(filtros_main)}[zoomed];"
267
- filtro_complex += "[blur][zoomed]overlay=(W-w)/2:(H-h)/2[base]"
268
-
269
- if ativar_texto and texto_personalizado.strip():
270
- y_pos = "100" if posicao_texto == "Topo" else "(h-text_h)/2" if posicao_texto == "Centro" else "h-text_h-100"
271
- enable = f":enable='lt(t\\,{segundos_texto})'" if duracao_texto == "Apenas primeiros segundos" else ""
272
- texto_clean = texto_personalizado.replace(":", "\\:").replace("'", "\\'")
273
- filtro_complex += f";[base]drawtext=text='{texto_clean}':"
274
- filtro_complex += (
275
- f"fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf:"
276
- f"fontcolor={cor_texto}:fontsize={tamanho_texto}:"
277
- f"shadowcolor={cor_sombra}:shadowx=3:shadowy=3:"
278
- f"x=(w-text_w)/2:y={y_pos}{enable}[final]"
279
- )
280
- else:
281
- filtro_complex += ";[base]null[final]"
282
-
283
  video_editado = os.path.join(temp_dir, f"video_editado_{n}.mp4")
284
  subprocess.run([
285
  "ffmpeg", "-i", fundo_convertido, "-i", video_raw,
286
  "-filter_complex", filtro_complex,
287
  "-map", "[final]",
288
- "-c:v", "libx264", "-preset", "ultrafast", "-crf", str(crf_value),
289
  video_editado
290
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
291
 
292
  etapa_atual += 1
293
  atualizar_barra(n, etapa_atual, num_videos_finais, total_etapas)
294
 
295
- # Etapa 4 - Tutorial
 
 
 
 
 
 
 
 
296
  if usar_tutorial and tutorials_salvos:
297
  tutorial_path = random.choice(tutorials_salvos)
298
  tutorial_mp4 = os.path.join(temp_dir, f"tutorial_conv_{n}.mp4")
299
  subprocess.run([
300
  "ffmpeg", "-i", tutorial_path, "-vf", "scale=720:1280,fps=30",
301
- "-c:v", "libx264", "-preset", "ultrafast", "-crf", str(crf_value),
302
  "-y", tutorial_mp4
303
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
304
 
305
  dur_proc = subprocess.run([
306
  "ffprobe", "-v", "error", "-show_entries", "format=duration",
307
- "-of", "default=noprint_wrappers=1:nokey=1", video_editado
308
  ], stdout=subprocess.PIPE)
309
  dur_f = float(dur_proc.stdout.decode().strip() or 0)
310
  pt = dur_f / 2 if dur_f < 10 else random.uniform(5, dur_f - 5)
@@ -312,11 +243,11 @@ if pagina == "🎬 Gerador de Vídeo":
312
  part1 = os.path.join(temp_dir, f"part1_{n}.mp4")
313
  part2 = os.path.join(temp_dir, f"part2_{n}.mp4")
314
 
315
- subprocess.run(["ffmpeg", "-i", video_editado, "-ss", "0", "-t", str(pt),
316
- "-c:v", "libx264", "-preset", "ultrafast", part1],
317
  stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
318
- subprocess.run(["ffmpeg", "-i", video_editado, "-ss", str(pt),
319
- "-c:v", "libx264", "-preset", "ultrafast", part2],
320
  stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
321
 
322
  final_txt = os.path.join(temp_dir, f"final_{n}.txt")
@@ -325,25 +256,17 @@ if pagina == "🎬 Gerador de Vídeo":
325
 
326
  video_final_raw = os.path.join(temp_dir, f"video_final_raw_{n}.mp4")
327
  subprocess.run(["ffmpeg", "-f", "concat", "-safe", "0", "-i", final_txt,
328
- "-c:v", "libx264", "-preset", "ultrafast", "-crf", str(crf_value),
329
  video_final_raw], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
330
  else:
331
- video_final_raw = video_editado
332
  etapa_atual += 1
333
  atualizar_barra(n, etapa_atual, num_videos_finais, total_etapas)
334
 
335
- # Etapa 5 - Velocidade final
336
- video_com_velocidade = os.path.join(temp_dir, f"video_com_velocidade_{n}.mp4")
337
- subprocess.run([
338
- "ffmpeg", "-y", "-i", video_final_raw, "-an",
339
- "-filter:v", f"setpts=PTS/{velocidade_final_n}",
340
- "-c:v", "libx264", "-preset", "ultrafast", "-crf", str(crf_value),
341
- video_com_velocidade
342
- ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
343
-
344
  dur_final_str = subprocess.run([
345
  "ffprobe", "-v", "error", "-show_entries", "format=duration",
346
- "-of", "default=noprint_wrappers=1:nokey=1", video_com_velocidade
347
  ], stdout=subprocess.PIPE).stdout.decode().strip()
348
  if not dur_final_str:
349
  continue
@@ -357,12 +280,12 @@ if pagina == "🎬 Gerador de Vídeo":
357
  "-vn", "-acodec", "aac", "-y", musica_cortada],
358
  stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
359
 
360
- subprocess.run(["ffmpeg", "-i", video_com_velocidade, "-i", musica_cortada,
361
  "-map", "0:v:0", "-map", "1:a:0",
362
  "-c:v", "copy", "-c:a", "aac", "-shortest", final_name],
363
  stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
364
  else:
365
- shutil.copy(video_com_velocidade, final_name)
366
 
367
  if salvar_no_gerenciador:
368
  destino = os.path.join(BASE_SALVOS, categoria_selecionada, final_name)
@@ -377,7 +300,6 @@ if pagina == "🎬 Gerador de Vídeo":
377
  st.error(f"❌ Erro inesperado: {str(e)}")
378
  finally:
379
  shutil.rmtree(temp_dir)
380
-
381
  # ======================== GERENCIADOR ========================
382
  elif pagina == "📂 Gerenciador de Arquivos":
383
  st.header("📂 Vídeos Salvos por Categoria")
@@ -419,7 +341,6 @@ elif pagina == "📂 Gerenciador de Arquivos":
419
  os.remove(file_path)
420
  st.success(f"❌ Arquivo '{file}' excluído.")
421
  st.rerun()
422
-
423
  # ======================== ADMIN ========================
424
  elif pagina == "🔐 Admin":
425
  st.title("🔐 Área de Administração")
@@ -469,7 +390,7 @@ elif pagina == "🔐 Admin":
469
  subprocess.run([
470
  "ffmpeg", "-i", temp,
471
  "-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2,fps=30",
472
- "-c:v", "libx264", "-preset", "ultrafast", "-crf", "25",
473
  "-y", final
474
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
475
  else:
 
21
  os.makedirs(os.path.join(BASE_ASSETS, cat, "cortes"), exist_ok=True)
22
  os.makedirs(os.path.join(BASE_ASSETS, cat, "tutoriais"), exist_ok=True)
23
  os.makedirs(os.path.join(BASE_SALVOS, cat), exist_ok=True)
 
24
  if pagina == "🎬 Gerador de Vídeo":
25
  st.title("🎥 TikTok Video Generator - PRO")
26
 
 
56
  zoom = st.slider("Zoom", 1.0, 2.0, 1.0, 0.1)
57
  blur_strength = st.slider("Blur no fundo", 1, 50, 10)
58
  velocidade_final = st.slider("Velocidade final", 0.5, 2.0, 1.0, 0.1)
59
+ crf_value = 18 # fixado em 18 para melhor qualidade
60
 
61
  st.write("## Texto no Vídeo")
62
  ativar_texto = st.checkbox("Ativar texto")
 
79
  with st.expander("🎨 Filtros Avançados"):
80
  ativar_brilho = st.checkbox("Brilho extra")
81
  ativar_contraste = st.checkbox("Contraste forte")
82
+ ativar_colorboost = st.checkbox("Cores i_
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  if st.button("Gerar Vídeo(s)", key="gerar_video_usuario"):
84
  with st.spinner("🎬 Processando..."):
85
  progresso = st.progress(0)
 
121
  ativar_blur_fundo_n = ativar_blur_fundo
122
  ativar_espelhar_n = ativar_espelhar
123
 
124
+ # ======================== ETAPA 1 - Fundo ========================
125
  if usar_fundo:
126
  fundo_origem = random.choice(cortes_names)
127
  fundo_convertido = os.path.join(temp_dir, f"fundo_convertido_{n}.mp4")
 
141
  "-vf",
142
  "scale='if(gt(iw/ih,720/1280),max(720,iw),-2)':'if(gt(iw/ih,720/1280),-2,max(1280,ih))',"
143
  "scale=720:1280:force_original_aspect_ratio=increase,crop=720:1280,fps=30",
144
+ "-preset", "veryfast", "-crf", "18",
145
  fundo_convertido
146
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
147
  else:
148
  fundo_convertido = os.path.join(temp_dir, f"fundo_vazio_{n}.mp4")
149
  subprocess.run([
150
  "ffmpeg", "-f", "lavfi", "-i", f"color=color=black:size=720x1280:d={duracao_final}:rate=30",
151
+ "-c:v", "libx264", "-t", str(duracao_final), "-preset", "veryfast", "-crf", "18",
152
  fundo_convertido
153
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
154
  etapa_atual += 1
155
  atualizar_barra(n, etapa_atual, num_videos_finais, total_etapas)
156
 
157
+ # ======================== ETAPA 2 - Cortes ========================
158
  tentativas = 0
159
  while tempo_total < duracao_final and tentativas < 100:
160
  tentativas += 1
 
179
  subprocess.run([
180
  "ffmpeg", "-ss", str(ini), "-i", c, "-t", str(duracao_aleatoria),
181
  "-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2",
182
+ "-an", "-c:v", "libx264", "-preset", "veryfast", "-crf", "18", out
183
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
184
  cortes_prontos.append(out)
185
  cortes_usados.append((c, ini, duracao_aleatoria))
 
197
  video_raw = os.path.join(temp_dir, f"video_raw_{n}.mp4")
198
  subprocess.run([
199
  "ffmpeg", "-f", "concat", "-safe", "0", "-i", lista,
200
+ "-c:v", "libx264", "-preset", "veryfast", "-crf", "18", video_raw
201
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 
202
  etapa_atual += 1
203
  atualizar_barra(n, etapa_atual, num_videos_finais, total_etapas)
204
 
205
+ # ======================== ETAPA 3 - Filtros e Efeitos ========================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  video_editado = os.path.join(temp_dir, f"video_editado_{n}.mp4")
207
  subprocess.run([
208
  "ffmpeg", "-i", fundo_convertido, "-i", video_raw,
209
  "-filter_complex", filtro_complex,
210
  "-map", "[final]",
211
+ "-c:v", "libx264", "-preset", "veryfast", "-crf", "18",
212
  video_editado
213
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
214
 
215
  etapa_atual += 1
216
  atualizar_barra(n, etapa_atual, num_videos_finais, total_etapas)
217
 
218
+ # ======================== ETAPA 3.5 - Aceleração ANTES do Tutorial ========================
219
+ video_editado_speed = os.path.join(temp_dir, f"video_editado_speed_{n}.mp4")
220
+ subprocess.run([
221
+ "ffmpeg", "-y", "-i", video_editado, "-an",
222
+ "-filter:v", f"setpts=PTS/{velocidade_final_n}",
223
+ "-c:v", "libx264", "-preset", "veryfast", "-crf", "18",
224
+ video_editado_speed
225
+ ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
226
+ # ======================== ETAPA 4 - Tutorial ========================
227
  if usar_tutorial and tutorials_salvos:
228
  tutorial_path = random.choice(tutorials_salvos)
229
  tutorial_mp4 = os.path.join(temp_dir, f"tutorial_conv_{n}.mp4")
230
  subprocess.run([
231
  "ffmpeg", "-i", tutorial_path, "-vf", "scale=720:1280,fps=30",
232
+ "-c:v", "libx264", "-preset", "veryfast", "-crf", 18,
233
  "-y", tutorial_mp4
234
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
235
 
236
  dur_proc = subprocess.run([
237
  "ffprobe", "-v", "error", "-show_entries", "format=duration",
238
+ "-of", "default=noprint_wrappers=1:nokey=1", video_editado_speed
239
  ], stdout=subprocess.PIPE)
240
  dur_f = float(dur_proc.stdout.decode().strip() or 0)
241
  pt = dur_f / 2 if dur_f < 10 else random.uniform(5, dur_f - 5)
 
243
  part1 = os.path.join(temp_dir, f"part1_{n}.mp4")
244
  part2 = os.path.join(temp_dir, f"part2_{n}.mp4")
245
 
246
+ subprocess.run(["ffmpeg", "-i", video_editado_speed, "-ss", "0", "-t", str(pt),
247
+ "-c:v", "libx264", "-preset", "veryfast", "-crf", 18, part1],
248
  stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
249
+ subprocess.run(["ffmpeg", "-i", video_editado_speed, "-ss", str(pt),
250
+ "-c:v", "libx264", "-preset", "veryfast", "-crf", 18, part2],
251
  stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
252
 
253
  final_txt = os.path.join(temp_dir, f"final_{n}.txt")
 
256
 
257
  video_final_raw = os.path.join(temp_dir, f"video_final_raw_{n}.mp4")
258
  subprocess.run(["ffmpeg", "-f", "concat", "-safe", "0", "-i", final_txt,
259
+ "-c:v", "libx264", "-preset", "veryfast", "-crf", 18,
260
  video_final_raw], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
261
  else:
262
+ video_final_raw = video_editado_speed
263
  etapa_atual += 1
264
  atualizar_barra(n, etapa_atual, num_videos_finais, total_etapas)
265
 
266
+ # ======================== ETAPA 5 - FINALIZAÇÃO ========================
 
 
 
 
 
 
 
 
267
  dur_final_str = subprocess.run([
268
  "ffprobe", "-v", "error", "-show_entries", "format=duration",
269
+ "-of", "default=noprint_wrappers=1:nokey=1", video_final_raw
270
  ], stdout=subprocess.PIPE).stdout.decode().strip()
271
  if not dur_final_str:
272
  continue
 
280
  "-vn", "-acodec", "aac", "-y", musica_cortada],
281
  stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
282
 
283
+ subprocess.run(["ffmpeg", "-i", video_final_raw, "-i", musica_cortada,
284
  "-map", "0:v:0", "-map", "1:a:0",
285
  "-c:v", "copy", "-c:a", "aac", "-shortest", final_name],
286
  stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
287
  else:
288
+ shutil.copy(video_final_raw, final_name)
289
 
290
  if salvar_no_gerenciador:
291
  destino = os.path.join(BASE_SALVOS, categoria_selecionada, final_name)
 
300
  st.error(f"❌ Erro inesperado: {str(e)}")
301
  finally:
302
  shutil.rmtree(temp_dir)
 
303
  # ======================== GERENCIADOR ========================
304
  elif pagina == "📂 Gerenciador de Arquivos":
305
  st.header("📂 Vídeos Salvos por Categoria")
 
341
  os.remove(file_path)
342
  st.success(f"❌ Arquivo '{file}' excluído.")
343
  st.rerun()
 
344
  # ======================== ADMIN ========================
345
  elif pagina == "🔐 Admin":
346
  st.title("🔐 Área de Administração")
 
390
  subprocess.run([
391
  "ffmpeg", "-i", temp,
392
  "-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2,fps=30",
393
+ "-c:v", "libx264", "-preset", "veryfast", "-crf", "18",
394
  "-y", final
395
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
396
  else: