Skip to content

ΣΑ #882

Description

@SALIMARIA

import os, subprocess, random
from PIL import Image, ImageDraw, ImageFont, ImageFilter

--------- ΡΥΘΜΙΣΕΙΣ ---------

INPUT_SUBJECT = "horror_girl_logo_PRINTED_move_480x854_10s.mp4" # το 10s σου
OUT_VIDEO = "final_10s_athens_riot.mp4"
W, H = 1080, 1920
DUR, FPS = 10, 30

colorkey για να “κόψει” μαύρο φόντο (αν χρειαστεί, παίξε με αυτά)

COLORKEY_HEX = "0x000000" # key κοντά σε μαύρο
SIMILARITY = 0.25 # 0..1 (μεγαλύτερο = πιο επιθετικό key)
BLEND = 0.05 # 0..1 (μαλάκωμα ακμών alpha)

zoom προς το τέλος (0.0 = καθόλου, 0.18 ≈ +18% μέγεθος στο τέλος)

SUBJ_ZOOM_END = 0.18

ελαφρά ανύψωση προς το τέλος (σε px) για να “πάει” σε κοντινό πρόσωπο

SUBJ_Y_LIFT = 120

από ποιο δευτ. “μπαίνει” το ροζ φως από αριστερά (fade-in)

PINK_LIGHT_FADE_START = 6
PINK_LIGHT_FADE_DUR = 4

--------- ΑΡΧΕΙΑ ΠΟΥ ΘΑ ΦΤΙΑΞΟΥΜΕ ---------

BG_PNG = "athens_graffiti_bg.png"
SMOKE_GRAY_PNG = "smoke_gray.png"
SMOKE_PINK_PNG = "smoke_pink.png"
FIRE_PNG = "fire_orange.png"
LEFT_LIGHT_PNG = "left_pink_light.png"
BG_VID = "bg_10s.mp4"

--------- ΦΟΝΤΟ ΑΘΗΝΑ + GRAFFITI ---------

def make_bg():
img = Image.new("RGBA", (W, H), (6,8,16,255))
d = ImageDraw.Draw(img)

# night gradient
for y in range(H):
    t = y / H
    r = int(12 + 8 * (1 - t))
    g = int(16 + 10 * (1 - t))
    b = int(30 + 38 * (1 - t))
    d.line([(0, y), (W, y)], fill=(r,g,b,255))

# skyline
random.seed(33)
ground_y = int(H*0.58)
for _ in range(46):
    bw = random.randint(44, 150)
    bh = random.randint(140, 460)
    x  = random.randint(-40, W-20)
    y  = ground_y - bh + random.randint(-50, 50)
    d.rectangle([x, y, x+bw, ground_y], fill=(10,12,24,255))

# windows
for _ in range(1400):
    bw = random.randint(6, 11)
    bh = random.randint(6, 11)
    x  = random.randint(0, W-1)
    y  = random.randint(int(H*0.20), ground_y-10)
    if random.random() < 0.22:
        col = random.choice([(255,230,150,255),(230,245,255,255),(255,185,100,255)])
        d.rectangle([x, y, x+bw, y+bh], fill=col)

# wall
wall_top = ground_y + 18
d.rectangle([0, wall_top, W, H], fill=(14,14,16,255))

# font
font = None
for p in ["/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
          "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"]:
    if os.path.exists(p):
        font = p; break

def stamp(text, x, y, size, angle, color):
    fnt = ImageFont.truetype(font, size) if font else None
    tmp = Image.new("RGBA", (1,1), (0,0,0,0))
    td  = ImageDraw.Draw(tmp)
    bbox= td.textbbox((0,0), text, font=fnt)
    tw, th = bbox[2]-bbox[0], bbox[3]-bbox[1]
    pad = 10
    tile = Image.new("RGBA", (tw+2*pad, th+2*pad), (0,0,0,0))
    tdraw= ImageDraw.Draw(tile)
    tdraw.text((pad, pad), text, font=fnt, fill=color)
    tile = tile.rotate(angle, expand=True, resample=Image.Resampling.BICUBIC)
    img.alpha_composite(tile, (x, y))

# graffiti bombs SALIMARIA 013
for _ in range(220):
    size  = random.randint(30, 160)
    angle = random.randint(-20, 20)
    col   = random.choice([(255, 90,160,255),(255,120, 40,255),(255,255,255,255),
                           (240, 60,120,255),(180,255,120,255)])
    x     = random.randint(-70, W-70)
    y     = random.randint(wall_top-50, H-60)
    stamp("SALIMARIA 013", x, y, size, angle, col)

img.save(BG_PNG, "PNG")

--------- SMOKE / FIRE / LIGHT PNGs ---------

def make_smoke(path, base_color, blobs=30, max_r=320, alpha=150, y_min=0.45, y_max=1.05):
img = Image.new("RGBA", (W, H), (0,0,0,0))
dr = ImageDraw.Draw(img)
for _ in range(blobs):
r = random.randint(100, max_r)
cx = random.randint(-120, W+120)
cy = random.randint(int(Hy_min), int(Hy_max))
for k in range(6,0,-1):
rr = int(r*(1+0.16k))
aa = max(25, int(alpha
(k/7)))
dr.ellipse([cx-rr, cy-rr, cx+rr, cy+rr], fill=(base_color[0],base_color[1],base_color[2],aa))
img = img.filter(ImageFilter.GaussianBlur(radius=32))
img.save(path, "PNG")

def make_fire(path, base_color=(255,120,40), blobs=28, max_r=240):
img = Image.new("RGBA", (W, H), (0,0,0,0))
dr = ImageDraw.Draw(img)
for _ in range(blobs):
r = random.randint(80, max_r)
cx = random.randint(-60, W+60)
cy = random.randint(int(H0.70), int(H0.95))
for k in range(6,0,-1):
rr = int(r*(1+0.18k))
aa = max(30, int(180
(k/7)))
dr.ellipse([cx-rr, cy-rr, cx+rr, cy+rr], fill=(base_color[0],base_color[1],base_color[2],aa))
img = img.filter(ImageFilter.GaussianBlur(radius=26))
img.save(path, "PNG")

def make_left_light(path):
grad = Image.new("RGBA", (W, H), (0,0,0,0))
gd = ImageDraw.Draw(grad)
for x in range(int(W0.45)):
t = 1 - x/(W
0.45)
a = int(200 * (t**1.6))
gd.line([(x,0),(x,H)], fill=(255,100,180,a))
grad = grad.filter(ImageFilter.GaussianBlur(radius=22))
grad.save(path, "PNG")

--------- RUN HELPERS ---------

def run_ffmpeg(cmd):
p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if p.returncode != 0:
print(p.stderr)
raise RuntimeError("ffmpeg failed")

def main():
if not os.path.exists(INPUT_SUBJECT):
raise FileNotFoundError(f"Δεν βρέθηκε το subject video: {INPUT_SUBJECT}")

make_bg()
make_smoke(SMOKE_GRAY_PNG, (180,180,185), blobs=34, max_r=340, alpha=150, y_min=0.40, y_max=1.02)
make_smoke(SMOKE_PINK_PNG, (255,105,180), blobs=26, max_r=300, alpha=160, y_min=0.50, y_max=1.05)
make_fire(FIRE_PNG, (255,120,40), blobs=28, max_r=240)
make_left_light(LEFT_LIGHT_PNG)

# 10s background video
run_ffmpeg([
    "ffmpeg","-y",
    "-loop","1","-t", str(DUR), "-i", BG_PNG,
    "-vf", f"scale={W}:{H},format=yuv420p",
    "-r", str(FPS), "-pix_fmt","yuv420p",
    BG_VID
])

# Compose όλα μαζί (χωρίς glitch). Zoom στο subject & ροζ φως από αριστερά στο τέλος.
filtergraph = (
    "[0:v]format=rgba[bg];"
    "[1:v]format=rgba,scale=1080:1920[sgray];"
    "[bg][sgray]overlay=x='20*sin(0.3*t)':y='H-900-30*t':eval=frame:shortest=1[lay1];"
    "[2:v]format=rgba,scale=1080:1920[spink];"
    "[lay1][spink]overlay=x='-120+40*t':y='H-800-25*t':eval=frame:shortest=1[lay2];"
    "[3:v]format=rgba,scale=1080:1920,fps=30[fire];"
    "[fire]eq=brightness='0.06*sin(15*t)'[firef];"
    "[lay2][firef]overlay=x='0':y='0':shortest=1[lay3];"
    f"[4:v]format=rgba,scale=1080:1920,fade=t=in:st={PINK_LIGHT_FADE_START}:d={PINK_LIGHT_FADE_DUR}:alpha=1[leftlight];"
    "[lay3][leftlight]overlay=x='0':y='0':shortest=1[base];"
    # Subject zoom over time + ελαφρά άνοδος προς τα πάνω (για κοντινό)
    f"[5:v]scale='trunc(iw*(1+{SUBJ_ZOOM_END}*(t/{DUR}))/2)*2':'trunc(ih*(1+{SUBJ_ZOOM_END}*(t/{DUR}))/2)*2':eval=frame,"
    f"format=rgba,colorkey={COLORKEY_HEX}:{SIMILARITY}:{BLEND},boxblur=2:2:cr=1:ar=1[subj];"
    f"[base][subj]overlay=x='(W-w)/2':y='(H-h)/2-{SUBJ_Y_LIFT}*(t/{DUR})':shortest=1[comp];"
    "[comp]format=yuv420p[v]"
)

run_ffmpeg([
    "ffmpeg","-y",
    "-i", BG_VID,
    "-stream_loop","-1","-t", str(DUR), "-i", SMOKE_GRAY_PNG,
    "-stream_loop","-1","-t", str(DUR), "-i", SMOKE_PINK_PNG,
    "-stream_loop","-1","-t", str(DUR), "-i", FIRE_PNG,
    "-stream_loop","-1","-t", str(DUR), "-i", LEFT_LIGHT_PNG,
    "-i", INPUT_SUBJECT,
    "-filter_complex", filtergraph,
    "-map","[v]","-t", str(DUR), "-r", str(FPS), "-pix_fmt","yuv420p",
    "-c:v","libx264","-crf","20","-preset","veryfast",
    OUT_VIDEO
])

print(f"\n✅ Exported: {OUT_VIDEO}")

if name == "main":
main()

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions