pcdoido2 commited on
Commit
f8f755c
·
verified ·
1 Parent(s): b09c088

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -20
app.py CHANGED
@@ -59,13 +59,18 @@ ativar_granulado = st.checkbox("Granulado", False)
59
  ativar_pb = st.checkbox("Preto e branco", False)
60
  ativar_vignette = st.checkbox("Vignette", False)
61
 
62
- # Novos efeitos PRO
63
  st.write("### Efeitos PRO")
64
- ativar_zoom_dinamico = st.checkbox("Ativar Zoom/Pan Dinâmico (Movimento de câmera)", value=False)
 
 
65
  ativar_color_grading = st.checkbox("Aplicar Color Grading Aleatório", value=False)
66
  ativar_transicoes = st.checkbox("Adicionar Transições Cinemáticas", value=False)
67
  ativar_freeze_frame = st.checkbox("Aplicar Freeze Frame automático", value=False)
68
  ativar_slow_motion = st.checkbox("Aplicar Slow Motion Inteligente aleatório", value=False)
 
 
 
69
 
70
  # Efeitos extras
71
  st.write("### Outros efeitos")
@@ -89,9 +94,8 @@ if st.button("Gerar Vídeo(s)"):
89
  temp_dir = tempfile.mkdtemp()
90
 
91
  try:
92
- # Salvar ou gerar fundo
93
  fundo_path = os.path.join(temp_dir, "fundo.mp4")
94
-
95
  if video_fundo:
96
  with open(fundo_path, "wb") as f:
97
  f.write(video_fundo.read())
@@ -102,7 +106,7 @@ if st.button("Gerar Vídeo(s)"):
102
  "-pix_fmt", "yuv420p", "-y", fundo_path
103
  ], check=True, stderr=subprocess.PIPE)
104
 
105
- # Salvar e converter tutorial (se enviado)
106
  if video_tutorial:
107
  tutorial_path = os.path.join(temp_dir, "tutorial_raw.mp4")
108
  with open(tutorial_path, "wb") as f:
@@ -114,7 +118,7 @@ if st.button("Gerar Vídeo(s)"):
114
  "-y", tutorial_mp4
115
  ], check=True, stderr=subprocess.PIPE)
116
 
117
- # Padronizar vídeos de cortes
118
  cortes_names = []
119
  for idx, corte in enumerate(cortes):
120
  path_in = os.path.join(temp_dir, f"corte_in_{idx}.mp4")
@@ -128,7 +132,7 @@ if st.button("Gerar Vídeo(s)"):
128
  ], check=True, stderr=subprocess.PIPE)
129
  cortes_names.append(path_out)
130
 
131
- # Cortar fundo para a duração final
132
  fundo_cortado = os.path.join(temp_dir, "fundo_cortado.mp4")
133
  subprocess.run([
134
  "ffmpeg", "-i", fundo_path, "-t", str(duracao_final),
@@ -156,22 +160,35 @@ if st.button("Gerar Vídeo(s)"):
156
 
157
  filtros_corte = []
158
 
159
- # ✅ Zoom/Pan Dinâmico corrigido
160
  if ativar_zoom_dinamico:
161
- filtros_corte.append("scale=iw*1.05:ih*1.05,crop=iw-20:ih-20")
 
 
 
162
  else:
163
  filtros_corte.append("scale=trunc(iw/2)*2:trunc(ih/2)*2")
164
 
 
 
 
 
 
 
 
 
 
 
165
  # ✅ Transições Cinemáticas
166
  if ativar_transicoes:
167
  filtros_corte.append("fade=t=in:st=0:d=0.3,fade=t=out:st=4.7:d=0.3")
168
 
169
- # ✅ Slow Motion Inteligente (aleatório)
170
  aplicar_slow = ativar_slow_motion and random.random() < 0.3
171
  if aplicar_slow:
172
  filtros_corte.append("setpts=1.5*PTS")
173
 
174
- # ✅ Freeze Frame (aleatório, 0.5s no meio)
175
  aplicar_freeze = ativar_freeze_frame and random.random() < 0.3
176
  if aplicar_freeze:
177
  freeze_frame = os.path.join(temp_dir, f"freeze_{random.randint(1000,9999)}.mp4")
@@ -197,7 +214,7 @@ if st.button("Gerar Vídeo(s)"):
197
  break
198
  except:
199
  continue
200
- # Concatenação dos cortes
201
  lista = os.path.join(temp_dir, f"lista_{n}.txt")
202
  with open(lista, "w") as f:
203
  for c in cortes_prontos:
@@ -212,7 +229,7 @@ if st.button("Gerar Vídeo(s)"):
212
 
213
  progresso.progress(35 + n * 5)
214
 
215
- # Filtros aplicados ao vídeo principal (sobre o vídeo de cortes)
216
  filtros_main = ["scale=720:1280:force_original_aspect_ratio=decrease"]
217
 
218
  if zoom != 1.0:
@@ -231,15 +248,27 @@ if st.button("Gerar Vídeo(s)"):
231
 
232
  # ✅ Color Grading aleatório
233
  if ativar_color_grading:
234
- opcoes_color = [
235
  "curves=preset=vintage",
236
  "curves=preset=strong_contrast",
237
- "eq=brightness=0.05:saturation=1.4:contrast=1.3",
238
  "hue=s=0.6",
239
  "colorchannelmixer=.5:0:.5:0:.5:0:.5:0:.5:0:.5"
240
- ]
241
- filtros_main.append(random.choice(opcoes_color))
 
 
 
 
 
 
 
242
 
 
 
 
 
 
243
  filtros_main.append("scale=trunc(iw/2)*2:trunc(ih/2)*2")
244
  # Montar filter_complex
245
  filtro_complex = (
@@ -262,11 +291,28 @@ if st.button("Gerar Vídeo(s)"):
262
  filtro_complex += f"[1:v]{','.join(filtros_main)}[zoomed];"
263
  filtro_complex += "[blur][zoomed]overlay=(W-w)/2:(H-h)/2[base]"
264
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  if ativar_texto and texto_personalizado.strip():
266
  y_pos = "100" if posicao_texto == "Topo" else "(h-text_h)/2" if posicao_texto == "Centro" else "h-text_h-100"
267
  enable = f":enable='lt(t\\,{segundos_texto})'" if duracao_texto == "Apenas primeiros segundos" else ""
268
  texto_clean = texto_personalizado.replace(":", "\\:").replace("'", "\\'")
269
- filtro_complex += f";[base]drawtext=text='{texto_clean}':"
270
  filtro_complex += (
271
  f"fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf:"
272
  f"fontcolor={cor_texto}:fontsize={tamanho_texto}:"
@@ -274,7 +320,7 @@ if st.button("Gerar Vídeo(s)"):
274
  f"x=(w-text_w)/2:y={y_pos}{enable}[final]"
275
  )
276
  else:
277
- filtro_complex += ";[base]null[final]"
278
 
279
  # Gerar vídeo com filtros
280
  video_editado = os.path.join(temp_dir, f"video_editado_{n}.mp4")
@@ -336,7 +382,7 @@ if st.button("Gerar Vídeo(s)"):
336
  ], stdout=subprocess.PIPE)
337
  dur_video_real = float(dur_proc.stdout.decode().strip())
338
 
339
- # 🎵 Cortar música para a duração real
340
  if musica:
341
  musica_path = os.path.join(temp_dir, "musica_original.mp3")
342
  with open(musica_path, "wb") as f:
 
59
  ativar_pb = st.checkbox("Preto e branco", False)
60
  ativar_vignette = st.checkbox("Vignette", False)
61
 
62
+ # Efeitos PRO
63
  st.write("### Efeitos PRO")
64
+ ativar_zoom_dinamico = st.checkbox("Ativar Zoom Progressivo", value=False)
65
+ zoom_dinamico_velocidade = st.slider("Velocidade do Zoom", 0.001, 0.01, 0.003, step=0.001)
66
+ movimento_camera = st.selectbox("Movimento de Câmera", ["Nenhum", "Esquerda para Direita", "Direita para Esquerda"])
67
  ativar_color_grading = st.checkbox("Aplicar Color Grading Aleatório", value=False)
68
  ativar_transicoes = st.checkbox("Adicionar Transições Cinemáticas", value=False)
69
  ativar_freeze_frame = st.checkbox("Aplicar Freeze Frame automático", value=False)
70
  ativar_slow_motion = st.checkbox("Aplicar Slow Motion Inteligente aleatório", value=False)
71
+ ativar_frame_blending = st.checkbox("Aplicar Frame Blending", value=False)
72
+ ativar_motion_crop = st.checkbox("Ativar Motion Crop Inteligente", value=False)
73
+ ativar_color_space_alt = st.checkbox("Alternar Color Space (anti-detect)", value=False)
74
 
75
  # Efeitos extras
76
  st.write("### Outros efeitos")
 
94
  temp_dir = tempfile.mkdtemp()
95
 
96
  try:
97
+ # Fundo
98
  fundo_path = os.path.join(temp_dir, "fundo.mp4")
 
99
  if video_fundo:
100
  with open(fundo_path, "wb") as f:
101
  f.write(video_fundo.read())
 
106
  "-pix_fmt", "yuv420p", "-y", fundo_path
107
  ], check=True, stderr=subprocess.PIPE)
108
 
109
+ # Tutorial
110
  if video_tutorial:
111
  tutorial_path = os.path.join(temp_dir, "tutorial_raw.mp4")
112
  with open(tutorial_path, "wb") as f:
 
118
  "-y", tutorial_mp4
119
  ], check=True, stderr=subprocess.PIPE)
120
 
121
+ # Padronizar vídeos
122
  cortes_names = []
123
  for idx, corte in enumerate(cortes):
124
  path_in = os.path.join(temp_dir, f"corte_in_{idx}.mp4")
 
132
  ], check=True, stderr=subprocess.PIPE)
133
  cortes_names.append(path_out)
134
 
135
+ # Fundo cortado
136
  fundo_cortado = os.path.join(temp_dir, "fundo_cortado.mp4")
137
  subprocess.run([
138
  "ffmpeg", "-i", fundo_path, "-t", str(duracao_final),
 
160
 
161
  filtros_corte = []
162
 
163
+ # ✅ Zoom Progressivo
164
  if ativar_zoom_dinamico:
165
+ filtros_corte.append(
166
+ f"zoompan=z='min(zoom+{zoom_dinamico_velocidade},1.5)':d=1:"
167
+ f"x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)',fps=30,scale=1280:720"
168
+ )
169
  else:
170
  filtros_corte.append("scale=trunc(iw/2)*2:trunc(ih/2)*2")
171
 
172
+ # ✅ Pan de câmera (horizontal)
173
+ if movimento_camera == "Esquerda para Direita":
174
+ filtros_corte.append("crop=w=720:h=1280:x='t*50':y=0")
175
+ elif movimento_camera == "Direita para Esquerda":
176
+ filtros_corte.append("crop=w=720:h=1280:x='(main_w-w)-t*50':y=0")
177
+
178
+ # ✅ Motion Crop Inteligente (simulado)
179
+ if ativar_motion_crop:
180
+ filtros_corte.append("crop=720:1280:x='abs(mod(t*100\\,main_w-w))':y='(main_h-h)/2'")
181
+
182
  # ✅ Transições Cinemáticas
183
  if ativar_transicoes:
184
  filtros_corte.append("fade=t=in:st=0:d=0.3,fade=t=out:st=4.7:d=0.3")
185
 
186
+ # ✅ Slow Motion Inteligente
187
  aplicar_slow = ativar_slow_motion and random.random() < 0.3
188
  if aplicar_slow:
189
  filtros_corte.append("setpts=1.5*PTS")
190
 
191
+ # ✅ Freeze Frame
192
  aplicar_freeze = ativar_freeze_frame and random.random() < 0.3
193
  if aplicar_freeze:
194
  freeze_frame = os.path.join(temp_dir, f"freeze_{random.randint(1000,9999)}.mp4")
 
214
  break
215
  except:
216
  continue
217
+ # Concatenação dos cortes com ajuste para múltiplos de 2
218
  lista = os.path.join(temp_dir, f"lista_{n}.txt")
219
  with open(lista, "w") as f:
220
  for c in cortes_prontos:
 
229
 
230
  progresso.progress(35 + n * 5)
231
 
232
+ # Filtros principais sobre o vídeo principal
233
  filtros_main = ["scale=720:1280:force_original_aspect_ratio=decrease"]
234
 
235
  if zoom != 1.0:
 
248
 
249
  # ✅ Color Grading aleatório
250
  if ativar_color_grading:
251
+ filtros_main.append(random.choice([
252
  "curves=preset=vintage",
253
  "curves=preset=strong_contrast",
254
+ "eq=brightness=0.05:saturation=1.5:contrast=1.2",
255
  "hue=s=0.6",
256
  "colorchannelmixer=.5:0:.5:0:.5:0:.5:0:.5:0:.5"
257
+ ]))
258
+
259
+ # ✅ Color Space alternado
260
+ if ativar_color_space_alt:
261
+ filtros_main.append(random.choice([
262
+ "colorspace=all=bt601-6-625",
263
+ "colorspace=all=bt470bg",
264
+ "colorspace=all=smpte240m"
265
+ ]))
266
 
267
+ # ✅ Frame Blending (minterpolate)
268
+ if ativar_frame_blending:
269
+ filtros_main.append("minterpolate='mi_mode=mci:mc_mode=aobmc:vsbmc=1'")
270
+
271
+ # Garantir múltiplos de 2 no final
272
  filtros_main.append("scale=trunc(iw/2)*2:trunc(ih/2)*2")
273
  # Montar filter_complex
274
  filtro_complex = (
 
291
  filtro_complex += f"[1:v]{','.join(filtros_main)}[zoomed];"
292
  filtro_complex += "[blur][zoomed]overlay=(W-w)/2:(H-h)/2[base]"
293
 
294
+ if ativar_borda_personalizada:
295
+ cor_ffmpeg = f"0x{cor_borda.lstrip('#')}FF"
296
+ anim_map = {
297
+ "Nenhuma": "",
298
+ "Borda Pulsante": "enable='lt(mod(t,1),0.5)'",
299
+ "Cor Animada": "enable='lt(mod(t,1),0.5)'",
300
+ "Neon": "enable='lt(mod(t,0.5),0.25)'",
301
+ "Ondulada": "enable='gt(sin(t*3.14),0)'"
302
+ }
303
+ drawbox = f"drawbox=x=0:y=0:w=iw:h=ih:color={cor_ffmpeg}:t=5"
304
+ if anim_map[animacao_borda]:
305
+ drawbox += f":{anim_map[animacao_borda]}"
306
+ filtro_complex += f";[base]{drawbox}[borda]"
307
+ filtro_complex += ";[borda]null[texto]"
308
+ else:
309
+ filtro_complex += ";[base]null[texto]"
310
+
311
  if ativar_texto and texto_personalizado.strip():
312
  y_pos = "100" if posicao_texto == "Topo" else "(h-text_h)/2" if posicao_texto == "Centro" else "h-text_h-100"
313
  enable = f":enable='lt(t\\,{segundos_texto})'" if duracao_texto == "Apenas primeiros segundos" else ""
314
  texto_clean = texto_personalizado.replace(":", "\\:").replace("'", "\\'")
315
+ filtro_complex += f";[texto]drawtext=text='{texto_clean}':"
316
  filtro_complex += (
317
  f"fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf:"
318
  f"fontcolor={cor_texto}:fontsize={tamanho_texto}:"
 
320
  f"x=(w-text_w)/2:y={y_pos}{enable}[final]"
321
  )
322
  else:
323
+ filtro_complex += ";[texto]null[final]"
324
 
325
  # Gerar vídeo com filtros
326
  video_editado = os.path.join(temp_dir, f"video_editado_{n}.mp4")
 
382
  ], stdout=subprocess.PIPE)
383
  dur_video_real = float(dur_proc.stdout.decode().strip())
384
 
385
+ # 🎵 Música sincronizada
386
  if musica:
387
  musica_path = os.path.join(temp_dir, "musica_original.mp3")
388
  with open(musica_path, "wb") as f: