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"drawbox=color=black@0.05: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}:c=black@0.0"
|
| 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)
|