x93 / app.py
x9393's picture
Update app.py
6acc391 verified
Raw
History Blame Contribute Delete
12.9 kB
import os
import re
import math
import shutil
import random
import subprocess
from datetime import datetime, timedelta, timezone
import gradio as gr
import spaces # ZeroGPU Desteği
def get_video_duration(input_file):
cmd = [
'ffprobe', '-v', 'error',
'-show_entries', 'format=duration',
'-of', 'default=noprint_wrappers=1:nokey=1',
input_file
]
try:
result = subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode().strip()
return float(result)
except Exception:
return None
def has_audio_stream(input_file):
cmd = [
'ffprobe', '-v', 'error',
'-select_streams', 'a',
'-show_entries', 'stream=codec_type',
'-of', 'csv=p=0',
input_file
]
try:
result = subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode().strip()
return bool(result)
except Exception:
return False
def generate_fake_metadata_args(user_date, user_loc, user_make, user_model):
if user_date:
creation_time_str = user_date
else:
days_ago = random.randint(1, 180)
hours_ago = random.randint(0, 23)
minutes_ago = random.randint(0, 59)
random_date = datetime.now() - timedelta(days=days_ago, hours=hours_ago, minutes=minutes_ago)
creation_time_str = random_date.strftime("%Y-%m-%dT%H:%M:%SZ")
lat_num, lon_num = 40.7128, -74.0060
if user_loc:
location_str = user_loc
coords = re.findall(r'[-+]?\d*\.\d+|\d+', user_loc)
if len(coords) >= 2:
try:
lat_num = float(coords[0])
lon_num = float(coords[1])
except ValueError:
pass
else:
lat_num = round(random.uniform(36.0, 42.0), 4)
lon_num = round(random.uniform(26.0, 45.0), 4)
location_str = f"{lat_num:+.4f}{lon_num:+.4f}/"
profiles = [
{
"make": "Apple", "model": "iPhone 15 Pro",
"lens": "iPhone 15 Pro back camera 6.86mm f/1.78", "software": "17.5.1",
"handler_v": "Core Media Video", "handler_a": "Core Media Audio",
"fnumber": 1.78, "focal": 6.86
},
{
"make": "Apple", "model": "iPhone 14 Pro",
"lens": "iPhone 14 Pro back camera 6.86mm f/1.78", "software": "17.4.1",
"handler_v": "Core Media Video", "handler_a": "Core Media Audio",
"fnumber": 1.78, "focal": 6.86
},
{
"make": "Samsung", "model": "SM-S928B",
"lens": "Galaxy S24 Ultra Main Camera 6.3mm f/1.7", "software": "UP1A.231005.007.S928BXXU1AXB5",
"handler_v": "VideoHandle", "handler_a": "SoundHandle",
"fnumber": 1.7, "focal": 6.3
}
]
if user_make or user_model:
selected_profile = {
"make": user_make if user_make else "Apple",
"model": user_model if user_model else "iPhone 15 Pro",
"lens": "iPhone Camera Lens 6.86mm f/1.78",
"software": "17.5.1",
"handler_v": "Core Media Video",
"handler_a": "Core Media Audio",
"fnumber": 1.78, "focal": 6.86
}
else:
selected_profile = random.choice(profiles)
selected_profile["creation_time"] = creation_time_str
selected_profile["lat_num"] = lat_num
selected_profile["lon_num"] = lon_num
selected_profile["location_str"] = location_str
metadata_args = [
'-map_metadata', '-1',
'-metadata', f'location={location_str}',
'-metadata', f'location-eng={location_str}',
'-metadata', f'make={selected_profile["make"]}',
'-metadata', f'model={selected_profile["model"]}',
'-metadata', f'software={selected_profile["software"]}',
'-metadata', f'creation_time={creation_time_str}',
'-metadata', 'encoder=',
'-metadata:s:v:0', 'encoder=',
'-metadata:s:v:0', f'handler_name={selected_profile["handler_v"]}',
'-metadata:s:a:0', 'encoder=',
'-metadata:s:a:0', f'handler_name={selected_profile["handler_a"]}',
]
return metadata_args, selected_profile
def apply_exiftool_metadata(file_path, profile):
exiftool_bin = shutil.which("exiftool")
if not exiftool_bin:
return "⚠️ UYARI: System ExifTool bulunamadı!"
try:
iso_val = random.choice([50, 64, 100, 125, 200])
lat = abs(profile.get("lat_num", 40.7128))
lat_ref = "N" if profile.get("lat_num", 40.7128) >= 0 else "S"
lon = abs(profile.get("lon_num", -74.0060))
lon_ref = "E" if profile.get("lon_num", -74.0060) >= 0 else "W"
make_val = profile.get("make", "Apple")
model_val = profile.get("model", "iPhone 15 Pro")
soft_val = profile.get("software", "17.5.1")
c_time = profile.get("creation_time", "")
exif_cmd = [
exiftool_bin,
'-overwrite_original',
'-XMP-all=',
f'-Make={make_val}',
f'-Model={model_val}',
f'-Keys:Make={make_val}',
f'-Keys:Model={model_val}',
f'-LensModel={profile.get("lens")}',
f'-Software={soft_val}',
f'-ISO={iso_val}',
f'-FNumber={profile.get("fnumber", 1.78)}',
f'-FocalLength={profile.get("focal", 6.86)} mm',
f'-CreateDate={c_time}',
f'-ModifyDate={c_time}',
f'-TrackCreateDate={c_time}',
f'-TrackModifyDate={c_time}',
f'-MediaCreateDate={c_time}',
f'-MediaModifyDate={c_time}',
f'-GPSLatitude={lat}',
f'-GPSLatitudeRef={lat_ref}',
f'-GPSLongitude={lon}',
f'-GPSLongitudeRef={lon_ref}',
'-CompressorName=H.264',
'-video:CompressorName=H.264',
'-Encoder=',
'-Keys:Encoder=',
'-UserData:Encoder=',
'-ItemList:Encoder=',
f'-HandlerName={profile.get("handler_v", "Core Media Video")}',
file_path
]
subprocess.run(exif_cmd, capture_output=True)
return "✅ ExifTool: Derin EXIF bilgileri & H.264 mühürlemesi uygulandı."
except Exception as e:
return f"⚠️ ExifTool Hatası: {e}"
@spaces.GPU # ZeroGPU Etiketi
def process_video_web(video_file, user_date, user_loc, user_make, user_model):
if video_file is None:
return None, "❌ Lütfen bir video yükleyin!"
# Gradio dosya nesnesinden dosya yolunu alma
input_file = video_file.name if hasattr(video_file, 'name') else str(video_file)
output_file = "/tmp/ozgunlestirilmis_video.mp4"
if os.path.exists(output_file):
os.remove(output_file)
logs = []
logs.append("⚡ v10.2 Anti-Detection Engine Başlatılıyor (ZeroGPU Active)...")
raw_duration = get_video_duration(input_file) or 60.0
audio_exists = has_audio_stream(input_file)
trim_start = round(random.uniform(0.3, 0.6), 3)
trim_end = round(random.uniform(0.3, 0.6), 3)
if raw_duration > (trim_start + trim_end + 3.0):
effective_dur = raw_duration - trim_start - trim_end
trim_end_pts = raw_duration - trim_end
else:
trim_start, trim_end_pts = 0.0, raw_duration
effective_dur = raw_duration
cut_duration = round(random.uniform(0.3, 0.5), 3)
cut_start_relative = round(effective_dur * random.uniform(0.4, 0.6), 3)
cut_end_relative = cut_start_relative + cut_duration
logs.append(f"✂️ Jump-Cut: {cut_start_relative}s anından {cut_duration}s kesildi.")
target_fps = random.choice([29.97, 30.0, 59.94, 60.0])
gop_size = "30" if target_fps in [29.97, 30.0] else "60"
brightness = round(random.uniform(-0.012, 0.018), 3)
contrast = round(random.uniform(1.01, 1.03), 3)
speed = round(random.uniform(0.98, 1.02), 3)
p1_start = trim_start
p1_end = trim_start + cut_start_relative
p2_start = trim_start + cut_end_relative
p2_end = trim_end_pts
filter_parts = []
filter_parts.append(f"[0:v]trim=start={p1_start:.3f}:end={p1_end:.3f},setpts=PTS-STARTPTS[v1]")
filter_parts.append(f"[0:v]trim=start={p2_start:.3f}:end={p2_end:.3f},setpts=PTS-STARTPTS[v2]")
filter_parts.append("[v1][v2]concat=n=2:v=1:a=0[v_jumped]")
cbh_val = random.choice([-1, 1])
chroma_shift = f"chromashift=cbh={cbh_val}:cbv={-cbh_val}:crh={-cbh_val}:crv={cbh_val}"
unsharp_val = round(random.uniform(0.35, 0.60), 3)
v_fx = (
f"[v_jumped]hflip[v_flipped]; "
f"[v_flipped]scale=1120:1980,rotate=0.005:c=black[v_rot]; "
f"[v_rot]crop=iw-4:ih-4:'2+1.2*sin(n*0.15)':'2+1.2*cos(n*0.15)',"
f"{chroma_shift},"
f"unsharp=luma_msize_x=5:luma_msize_y=5:luma_amount={unsharp_val},"
f"eq=brightness={brightness}:contrast={contrast}:saturation=1.01,"
f"colorbalance=rs=0.01:bs=-0.01,vignette=PI/6,"
f"crop=1080:1920:(iw-1080)/2+12*sin(n*0.025):(ih-1920)/2+12*cos(n*0.025),"
f"noise=alls=7:allf=t+u,"
f"setpts=(PTS-STARTPTS)/{speed},"
f"fps={target_fps},scale=1080:1920,setsar=1,format=yuv420p[vout_final]"
)
filter_parts.append(v_fx)
map_args = ['-map', '[vout_final]']
audio_codec_args = []
if audio_exists:
filter_parts.append(f"[0:a]atrim=start={p1_start:.3f}:end={p1_end:.3f},asetpts=PTS-STARTPTS[a1]")
filter_parts.append(f"[0:a]atrim=start={p2_start:.3f}:end={p2_end:.3f},asetpts=PTS-STARTPTS[a2]")
filter_parts.append("[a1][a2]concat=n=2:v=0:a=1[a_jumped]")
pitch_factor = round(random.choice([0.97, 0.98, 1.02, 1.03]), 3)
inv_pitch = round(1 / pitch_factor, 6)
new_rate = int(48000 * pitch_factor)
audio_delay_ms = random.randint(15, 30)
a_fx = (
f"[a_jumped]atempo={speed},"
f"asetrate={new_rate},atempo={inv_pitch},"
f"highpass=f=80,equalizer=f=850:width_type=q:width=1:g=-5,"
f"aecho=0.8:0.85:12:0.08,bass=g=2:f=80,treble=g=1.5:f=12000,"
f"adelay={audio_delay_ms}|{audio_delay_ms},volume=1.02,aresample=48000,apad[aout_final]"
)
filter_parts.append(a_fx)
map_args += ['-map', '[aout_final]']
audio_codec_args = ['-c:a', 'aac', '-b:a', '192k', '-ac', '2', '-ar', '48000']
filter_complex = "; ".join(filter_parts)
metadata_args, profile_data = generate_fake_metadata_args(user_date, user_loc, user_make, user_model)
cmd = [
'ffmpeg',
'-i', input_file,
'-filter_complex', filter_complex,
*map_args,
'-c:v', 'libx264',
'-crf', '22',
'-preset', 'fast',
'-g', gop_size,
'-bf', '0',
'-bsf:v', 'filter_units=remove_types=6',
'-brand', 'mp42',
'-color_primaries', 'bt709',
'-color_trc', 'bt709',
'-colorspace', 'bt709',
'-color_range', 'tv',
*audio_codec_args,
'-pix_fmt', 'yuv420p',
'-movflags', '+faststart',
'-shortest',
*metadata_args,
'-y',
output_file
]
res = subprocess.run(cmd, capture_output=True, text=True)
if res.returncode == 0:
exif_log = apply_exiftool_metadata(output_file, profile_data)
logs.append(exif_log)
logs.append("🎉 Video Başarıyla Özgünleştirildi!")
return output_file, "\n".join(logs)
else:
logs.append("❌ FFmpeg Hatası:")
logs.append(res.stderr[-400:])
return None, "\n".join(logs)
# Gradio Mobil Uyumlu Arayüz Tasarımı
with gr.Blocks(title="Sosyal Medya Video Özgünleştirici Pro v10.2") as demo:
gr.Markdown(
"""
# ⚡ Sosyal Medya Video Özgünleştirici Pro (v10.2 ZeroGPU)
"""
)
with gr.Row():
with gr.Column():
video_input = gr.File(label="📹 Videonuzu Yükleyin (.mp4, .mov)", file_types=[".mp4", ".mov", ".mkv"])
with gr.Accordion("📝 Özel Metadata & Cihaz Ayarları (Opsiyonel)", open=False):
user_date = gr.Textbox(label="Tarih", placeholder="YYYY-MM-DDTHH:MM:SSZ")
user_loc = gr.Textbox(label="GPS Konum", placeholder="+40.7128-74.0060/")
user_make = gr.Textbox(label="Marka", placeholder="Apple / Samsung")
user_model = gr.Textbox(label="Model", placeholder="iPhone 15 Pro")
btn_submit = gr.Button("🚀 Videoyu Özgünleştir", variant="primary")
with gr.Column():
video_output = gr.Video(label="✅ Özgünleştirilmiş Video")
log_output = gr.Textbox(label="📋 İşlem Logları", lines=8)
btn_submit.click(
fn=process_video_web,
inputs=[video_input, user_date, user_loc, user_make, user_model],
outputs=[video_output, log_output]
)
if __name__ == "__main__":
demo.queue().launch(ssr_mode=False)