Update app.py
Browse files
app.py
CHANGED
@@ -9,7 +9,7 @@ import time
|
|
9 |
st.set_page_config(page_title="TikTok Video Generator", layout="centered")
|
10 |
st.title("🎥 TikTok Video Generator - PRO")
|
11 |
|
12 |
-
st.markdown("Envie seus vídeos e gere conteúdo com efeitos
|
13 |
|
14 |
# Uploads dos vídeos de cortes (principal)
|
15 |
st.markdown("<div style='background-color:#F0F0FF;padding:10px;border-radius:8px'>", unsafe_allow_html=True)
|
@@ -37,7 +37,7 @@ velocidade_cortes = st.slider("Velocidade dos cortes", 0.5, 2.0, 1.0, 0.1)
|
|
37 |
velocidade_final = st.slider("Velocidade final", 0.5, 2.0, 1.0, 0.1)
|
38 |
crf_value = st.slider("Qualidade CRF", 18, 30, 23)
|
39 |
|
40 |
-
# Texto
|
41 |
st.write("### Texto no Vídeo")
|
42 |
ativar_texto = st.checkbox("Ativar texto", value=False)
|
43 |
if ativar_texto:
|
@@ -59,21 +59,15 @@ ativar_granulado = st.checkbox("Granulado", False)
|
|
59 |
ativar_pb = st.checkbox("Preto e branco", False)
|
60 |
ativar_vignette = st.checkbox("Vignette", False)
|
61 |
|
62 |
-
# Efeitos
|
63 |
-
st.write("### Efeitos
|
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 |
-
#
|
76 |
-
st.write("### Outros
|
77 |
ativar_espelhar = st.checkbox("Espelhar vídeo", True)
|
78 |
ativar_filtro_cor = st.checkbox("Ajuste de cor", True)
|
79 |
remover_borda = st.checkbox("Remover borda do vídeo")
|
@@ -160,46 +154,23 @@ if st.button("Gerar Vídeo(s)"):
|
|
160 |
|
161 |
filtros_corte = []
|
162 |
|
163 |
-
# ✅
|
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 |
-
# ✅ Movimento de Câmera (com upscale)
|
173 |
if movimento_camera == "Esquerda para Direita":
|
174 |
-
filtros_corte.append("scale=
|
175 |
elif movimento_camera == "Direita para Esquerda":
|
176 |
-
filtros_corte.append("scale=
|
177 |
-
|
178 |
-
|
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
|
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")
|
195 |
-
subprocess.run([
|
196 |
-
"ffmpeg", "-ss", str(ini + duracao_corte/2), "-i", c,
|
197 |
-
"-t", "0.001", "-vf", "scale=1280:720", "-c:v", "libx264",
|
198 |
-
"-y", freeze_frame
|
199 |
-
], check=True, stderr=subprocess.PIPE)
|
200 |
-
cortes_prontos.append(freeze_frame)
|
201 |
-
tempo_total += 0.5
|
202 |
-
|
203 |
filtro_final = ",".join(filtros_corte)
|
204 |
|
205 |
subprocess.run([
|
@@ -229,7 +200,7 @@ if st.button("Gerar Vídeo(s)"):
|
|
229 |
|
230 |
progresso.progress(35 + n * 5)
|
231 |
|
232 |
-
# Filtros principais sobre o vídeo
|
233 |
filtros_main = ["scale=720:1280:force_original_aspect_ratio=decrease"]
|
234 |
|
235 |
if zoom != 1.0:
|
@@ -256,19 +227,7 @@ if st.button("Gerar Vídeo(s)"):
|
|
256 |
"colorchannelmixer=.5:0:.5:0:.5:0:.5:0:.5:0:.5"
|
257 |
]))
|
258 |
|
259 |
-
#
|
260 |
-
if ativar_color_space_alt:
|
261 |
-
filtros_main.append(random.choice([
|
262 |
-
"colorspace=ispace=bt709:ospace=bt601",
|
263 |
-
"colorspace=ispace=bt709:ospace=bt470bg",
|
264 |
-
"colorspace=ispace=bt709:ospace=smpte240m"
|
265 |
-
]))
|
266 |
-
|
267 |
-
# ✅ Frame Blending (com scale antes)
|
268 |
-
if ativar_frame_blending:
|
269 |
-
filtros_main.append("scale=trunc(iw/2)*2:trunc(ih/2)*2,minterpolate='mi_mode=mci:mc_mode=aobmc:vsbmc=1'")
|
270 |
-
|
271 |
-
# Final padronização
|
272 |
filtros_main.append("scale=trunc(iw/2)*2:trunc(ih/2)*2")
|
273 |
# Montar filter_complex
|
274 |
filtro_complex = (
|
@@ -343,7 +302,7 @@ if st.button("Gerar Vídeo(s)"):
|
|
343 |
|
344 |
progresso.progress(90)
|
345 |
# Tutorial no meio, se fornecido
|
346 |
-
video_final_raw = video_acelerado
|
347 |
if video_tutorial:
|
348 |
dur_proc = subprocess.run([
|
349 |
"ffprobe", "-v", "error", "-show_entries", "format=duration",
|
@@ -375,14 +334,14 @@ if st.button("Gerar Vídeo(s)"):
|
|
375 |
video_final_raw
|
376 |
], check=True, stderr=subprocess.PIPE)
|
377 |
|
378 |
-
#
|
379 |
dur_proc = subprocess.run([
|
380 |
"ffprobe", "-v", "error", "-show_entries", "format=duration",
|
381 |
"-of", "default=noprint_wrappers=1:nokey=1", video_final_raw
|
382 |
], stdout=subprocess.PIPE)
|
383 |
dur_video_real = float(dur_proc.stdout.decode().strip())
|
384 |
|
385 |
-
# Música
|
386 |
if musica:
|
387 |
musica_path = os.path.join(temp_dir, "musica_original.mp3")
|
388 |
with open(musica_path, "wb") as f:
|
|
|
9 |
st.set_page_config(page_title="TikTok Video Generator", layout="centered")
|
10 |
st.title("🎥 TikTok Video Generator - PRO")
|
11 |
|
12 |
+
st.markdown("Envie seus vídeos e gere conteúdo com efeitos modernos e automáticos!")
|
13 |
|
14 |
# Uploads dos vídeos de cortes (principal)
|
15 |
st.markdown("<div style='background-color:#F0F0FF;padding:10px;border-radius:8px'>", unsafe_allow_html=True)
|
|
|
37 |
velocidade_final = st.slider("Velocidade final", 0.5, 2.0, 1.0, 0.1)
|
38 |
crf_value = st.slider("Qualidade CRF", 18, 30, 23)
|
39 |
|
40 |
+
# Texto (opcional)
|
41 |
st.write("### Texto no Vídeo")
|
42 |
ativar_texto = st.checkbox("Ativar texto", value=False)
|
43 |
if ativar_texto:
|
|
|
59 |
ativar_pb = st.checkbox("Preto e branco", False)
|
60 |
ativar_vignette = st.checkbox("Vignette", False)
|
61 |
|
62 |
+
# Efeitos selecionados (os únicos que ficarão ativos)
|
63 |
+
st.write("### Efeitos Visuais Avançados")
|
|
|
|
|
64 |
movimento_camera = st.selectbox("Movimento de Câmera", ["Nenhum", "Esquerda para Direita", "Direita para Esquerda"])
|
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_slow_motion = st.checkbox("Aplicar Slow Motion Inteligente aleatório", value=False)
|
|
|
|
|
|
|
68 |
|
69 |
+
# Outros efeitos simples
|
70 |
+
st.write("### Outros ajustes")
|
71 |
ativar_espelhar = st.checkbox("Espelhar vídeo", True)
|
72 |
ativar_filtro_cor = st.checkbox("Ajuste de cor", True)
|
73 |
remover_borda = st.checkbox("Remover borda do vídeo")
|
|
|
154 |
|
155 |
filtros_corte = []
|
156 |
|
157 |
+
# ✅ Movimento de Câmera (corrigido)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
if movimento_camera == "Esquerda para Direita":
|
159 |
+
filtros_corte.append("scale=800:1280,crop=720:1280:x='t*5':y=0")
|
160 |
elif movimento_camera == "Direita para Esquerda":
|
161 |
+
filtros_corte.append("scale=800:1280,crop=720:1280:x='(in_w-w)-t*5':y=0")
|
162 |
+
else:
|
163 |
+
filtros_corte.append("scale=720:1280")
|
|
|
|
|
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 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 |
filtro_final = ",".join(filtros_corte)
|
175 |
|
176 |
subprocess.run([
|
|
|
200 |
|
201 |
progresso.progress(35 + n * 5)
|
202 |
|
203 |
+
# Filtros principais sobre o vídeo principal
|
204 |
filtros_main = ["scale=720:1280:force_original_aspect_ratio=decrease"]
|
205 |
|
206 |
if zoom != 1.0:
|
|
|
227 |
"colorchannelmixer=.5:0:.5:0:.5:0:.5:0:.5:0:.5"
|
228 |
]))
|
229 |
|
230 |
+
# Garantir múltiplos de 2 no final
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
filtros_main.append("scale=trunc(iw/2)*2:trunc(ih/2)*2")
|
232 |
# Montar filter_complex
|
233 |
filtro_complex = (
|
|
|
302 |
|
303 |
progresso.progress(90)
|
304 |
# Tutorial no meio, se fornecido
|
305 |
+
video_final_raw = video_acelerado
|
306 |
if video_tutorial:
|
307 |
dur_proc = subprocess.run([
|
308 |
"ffprobe", "-v", "error", "-show_entries", "format=duration",
|
|
|
334 |
video_final_raw
|
335 |
], check=True, stderr=subprocess.PIPE)
|
336 |
|
337 |
+
# Duração real para sincronizar música
|
338 |
dur_proc = subprocess.run([
|
339 |
"ffprobe", "-v", "error", "-show_entries", "format=duration",
|
340 |
"-of", "default=noprint_wrappers=1:nokey=1", video_final_raw
|
341 |
], stdout=subprocess.PIPE)
|
342 |
dur_video_real = float(dur_proc.stdout.decode().strip())
|
343 |
|
344 |
+
# Música final
|
345 |
if musica:
|
346 |
musica_path = os.path.join(temp_dir, "musica_original.mp3")
|
347 |
with open(musica_path, "wb") as f:
|