Update app.py
Browse files
app.py
CHANGED
@@ -1,164 +1,176 @@
|
|
1 |
import streamlit as st
|
2 |
import subprocess
|
3 |
import os
|
|
|
4 |
import random
|
5 |
-
import tempfile
|
6 |
import shutil
|
7 |
-
|
8 |
-
|
9 |
-
st.
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
st.
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
st.
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
st.
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
st.
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
if
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
import subprocess
|
3 |
import os
|
4 |
+
import uuid
|
5 |
import random
|
|
|
6 |
import shutil
|
7 |
+
|
8 |
+
st.set_page_config(page_title="Anti-Flop PRO MAX", layout="centered")
|
9 |
+
st.title("🚀 Anti-Flop PRO MAX – Gerador com Fingerprint Invisível")
|
10 |
+
|
11 |
+
uploaded_file = st.file_uploader("📤 Envie seu vídeo (MP4)", type=["mp4"])
|
12 |
+
|
13 |
+
if uploaded_file:
|
14 |
+
raw_input_filename = f"raw_{uuid.uuid4().hex}.mp4"
|
15 |
+
with open(raw_input_filename, "wb") as f:
|
16 |
+
f.write(uploaded_file.read())
|
17 |
+
|
18 |
+
input_filename = f"cleaned_{uuid.uuid4().hex}.mp4"
|
19 |
+
subprocess.run(['ffmpeg', '-i', raw_input_filename, '-map_metadata', '-1', '-c', 'copy', input_filename])
|
20 |
+
os.remove(raw_input_filename)
|
21 |
+
|
22 |
+
st.video(input_filename)
|
23 |
+
st.success("🎥 Vídeo carregado e metadados limpos!")
|
24 |
+
|
25 |
+
st.subheader("🎛️ Ajustes Visuais e Áudio (padrão)")
|
26 |
+
|
27 |
+
if st.button("🎲 RANDOMIZAR TUDO"):
|
28 |
+
st.session_state.zoom_default = random.uniform(1.00, 1.05)
|
29 |
+
st.session_state.brilho_default = random.uniform(-0.05, 0.05)
|
30 |
+
st.session_state.contraste_default = random.uniform(0.95, 1.05)
|
31 |
+
st.session_state.saturacao_default = random.uniform(0.95, 1.05)
|
32 |
+
st.session_state.ruido_default = random.randint(3, 15)
|
33 |
+
st.session_state.rotacao_default = random.uniform(0.2, 1.5)
|
34 |
+
st.session_state.pitch_default = random.uniform(1.00, 1.08)
|
35 |
+
st.session_state.fps_val = random.choice([30, 29.97, 25])
|
36 |
+
st.session_state.bitrate_default = random.randint(900, 1500)
|
37 |
+
st.session_state.velocidade_default = random.uniform(1.00, 1.03)
|
38 |
+
st.rerun()
|
39 |
+
|
40 |
+
zoom_default = st.slider("Zoom (%)", 100, 105, int(st.session_state.get('zoom_default', 1.01) * 100)) / 100
|
41 |
+
brilho_default = st.slider("Brilho", -0.1, 0.1, st.session_state.get('brilho_default', 0.01))
|
42 |
+
contraste_default = st.slider("Contraste", 0.9, 1.1, st.session_state.get('contraste_default', 1.01))
|
43 |
+
saturacao_default = st.slider("Saturação", 0.9, 1.1, st.session_state.get('saturacao_default', 1.01))
|
44 |
+
ruido_default = st.slider("Ruído Visual (0-20)", 0, 20, st.session_state.get('ruido_default', 5))
|
45 |
+
rotacao_default = st.slider("Rotação (graus)", 0.0, 2.0, st.session_state.get('rotacao_default', 0.5))
|
46 |
+
pitch_default = st.slider("Pitch do Áudio (%)", 100, 110, int(st.session_state.get('pitch_default', 1.01) * 100)) / 100
|
47 |
+
fps = st.selectbox("FPS Final", [30, 29.97, 25], index=[30, 29.97, 25].index(st.session_state.get('fps_val', 30)))
|
48 |
+
bitrate_default = st.slider("Bitrate (kbps)", 800, 2000, st.session_state.get('bitrate_default', 1100))
|
49 |
+
velocidade_default = st.slider("Velocidade do Vídeo (%)", 100, 103, int(st.session_state.get('velocidade_default', 1.01) * 100)) / 100
|
50 |
+
|
51 |
+
st.subheader("🧩 Extras Anti-Detecção")
|
52 |
+
usar_marca = st.checkbox("Marca d’água Fantasma com perfil", value=True)
|
53 |
+
usar_glitch = st.checkbox("Inserir Frame Preto Aleatório", value=True)
|
54 |
+
res_random = st.checkbox("Resolução Aleatória", value=True)
|
55 |
+
cortar = st.checkbox("Cortar trecho aleatório do vídeo", value=True)
|
56 |
+
embaralhar = st.checkbox("Embaralhar trechos do vídeo", value=True)
|
57 |
+
|
58 |
+
st.subheader("🎨 Avançado")
|
59 |
+
lote_efeitos = st.checkbox("🎨 Aplicar efeitos por lote (aleatórios)", value=True)
|
60 |
+
transicoes = st.checkbox("🔄 Transições visuais aleatórias", value=True)
|
61 |
+
|
62 |
+
st.subheader("🕵️♂️ Perfil Fingerprint")
|
63 |
+
fingerprint = st.selectbox("Escolha o Perfil", ["Android", "iPhone", "Câmera", "CapCut", "Samsung", "Xiaomi", "LG"])
|
64 |
+
|
65 |
+
qtd_videos = st.number_input("Quantidade de vídeos únicos:", min_value=1, max_value=10, value=3)
|
66 |
+
|
67 |
+
if st.button("🎬 Gerar Vídeos Únicos"):
|
68 |
+
st.info("Processando vídeos... aguarde!")
|
69 |
+
output_files = []
|
70 |
+
|
71 |
+
if embaralhar:
|
72 |
+
temp_dir = f"temp_{uuid.uuid4().hex}"
|
73 |
+
os.makedirs(temp_dir, exist_ok=True)
|
74 |
+
subprocess.run(['ffmpeg', '-i', input_filename, '-c', 'copy', '-f', 'segment', '-segment_time', '2', f'{temp_dir}/out%03d.mp4'])
|
75 |
+
files = os.listdir(temp_dir)
|
76 |
+
files.sort()
|
77 |
+
random.shuffle(files)
|
78 |
+
concat_list = f"{temp_dir}/list.txt"
|
79 |
+
with open(concat_list, 'w') as f:
|
80 |
+
for file in files:
|
81 |
+
f.write(f"file '{os.path.join(temp_dir, file)}'\n")
|
82 |
+
shuffled_input = f"shuffled_{uuid.uuid4().hex}.mp4"
|
83 |
+
subprocess.run(['ffmpeg', '-f', 'concat', '-safe', '0', '-i', concat_list, '-c', 'copy', shuffled_input])
|
84 |
+
shutil.rmtree(temp_dir)
|
85 |
+
base_video = shuffled_input if os.path.exists(shuffled_input) else input_filename
|
86 |
+
else:
|
87 |
+
base_video = input_filename
|
88 |
+
|
89 |
+
for _ in range(qtd_videos):
|
90 |
+
encoder_name = f"{fingerprint}Cam_{random.randint(1000,9999)}"
|
91 |
+
final_out = f"{encoder_name}_video_{uuid.uuid4().hex}.mp4"
|
92 |
+
|
93 |
+
if lote_efeitos:
|
94 |
+
zoom_r = random.uniform(1.00, 1.05)
|
95 |
+
brilho_r = random.uniform(-0.05, 0.05)
|
96 |
+
contraste_r = random.uniform(0.95, 1.05)
|
97 |
+
saturacao_r = random.uniform(0.95, 1.05)
|
98 |
+
ruido_r = random.randint(3, 15)
|
99 |
+
rot_r = random.uniform(0.2, 1.5) * 0.01745
|
100 |
+
pitch_r = random.uniform(1.00, 1.08)
|
101 |
+
velocidade_r = random.uniform(1.00, 1.03)
|
102 |
+
bitrate_r = f"{random.randint(900, 1500)}k"
|
103 |
+
else:
|
104 |
+
zoom_r = zoom_default
|
105 |
+
brilho_r = brilho_default
|
106 |
+
contraste_r = contraste_default
|
107 |
+
saturacao_r = saturacao_default
|
108 |
+
ruido_r = ruido_default
|
109 |
+
rot_r = rotacao_default * 0.01745
|
110 |
+
pitch_r = pitch_default
|
111 |
+
velocidade_r = velocidade_default
|
112 |
+
bitrate_r = f"{bitrate_default}k"
|
113 |
+
|
114 |
+
vf = (
|
115 |
+
f"scale=iw*{zoom_r}:ih*{zoom_r},"
|
116 |
+
f"crop=iw/{zoom_r}:ih/{zoom_r},"
|
117 |
+
f"[email protected]:t=fill,"
|
118 |
+
f"eq=brightness={brilho_r}:contrast={contraste_r}:saturation={saturacao_r},"
|
119 |
+
f"noise=alls={ruido_r}:allf=t,"
|
120 |
+
f"rotate={rot_r}:[email protected]"
|
121 |
+
)
|
122 |
+
|
123 |
+
if usar_marca:
|
124 |
+
vf += f",drawtext=text='{encoder_name}':fontcolor=white@0.005:x=10:y=10:fontsize=24"
|
125 |
+
if usar_glitch:
|
126 |
+
vf += ",blackframe=1:0"
|
127 |
+
if res_random:
|
128 |
+
w = random.choice([720, 960, 1080])
|
129 |
+
h = random.choice([1280, 1440, 1920])
|
130 |
+
vf += f",scale={w}:{h}"
|
131 |
+
if transicoes:
|
132 |
+
effects = [
|
133 |
+
"fade=t=in:st=0:d=0.5",
|
134 |
+
"fade=t=out:st=3:d=0.5",
|
135 |
+
"zoompan=z='min(pzoom+0.0015,1.5)':d=1",
|
136 |
+
"drawbox=x=0:y=0:w=iw:h=ih:color=white@0.02:t=fill"
|
137 |
+
]
|
138 |
+
vf += "," + random.choice(effects)
|
139 |
+
|
140 |
+
af = f"asetrate=44100*{pitch_r},aresample=44100"
|
141 |
+
profile = "baseline" if fingerprint in ["Android", "Xiaomi"] else "main"
|
142 |
+
if fingerprint == "iPhone":
|
143 |
+
profile = "high"
|
144 |
+
level = "4.0" if fingerprint == "Samsung" else "3.1"
|
145 |
+
ar = "44100" if fingerprint in ["iPhone", "Xiaomi"] else "48000"
|
146 |
+
|
147 |
+
codec_cmd = ['-c:v', 'libx264', '-profile:v', profile, '-level', level]
|
148 |
+
audio_cmd = ['-ar', ar]
|
149 |
+
filters = ['-vf', vf, '-af', af, '-r', str(fps)]
|
150 |
+
speed_filter = ['-filter:v', f"setpts={1/velocidade_r}*PTS"]
|
151 |
+
speed_audio = ['-filter:a', f"atempo={velocidade_r}"]
|
152 |
+
duration_cmd = ['-ss', str(random.uniform(0, 1))] if cortar else []
|
153 |
+
|
154 |
+
subprocess.run([
|
155 |
+
'ffmpeg', '-i', base_video, *duration_cmd,
|
156 |
+
*filters, *speed_filter, *speed_audio,
|
157 |
+
*codec_cmd, '-b:v', bitrate_r,
|
158 |
+
*audio_cmd,
|
159 |
+
'-preset', 'fast', '-tune', 'zerolatency',
|
160 |
+
'-movflags', '+faststart',
|
161 |
+
final_out
|
162 |
+
])
|
163 |
+
|
164 |
+
output_files.append(final_out)
|
165 |
+
|
166 |
+
if base_video != input_filename and os.path.exists(base_video):
|
167 |
+
os.remove(base_video)
|
168 |
+
os.remove(input_filename)
|
169 |
+
|
170 |
+
st.success(f"✅ {qtd_videos} vídeos gerados com fingerprint invisível!")
|
171 |
+
|
172 |
+
for file in output_files:
|
173 |
+
st.video(file)
|
174 |
+
with open(file, "rb") as f:
|
175 |
+
st.download_button(f"📥 Baixar {file}", data=f, file_name=file, mime="video/mp4")
|
176 |
+
os.remove(file)
|