🗝 KeyzHub
19Keys · community archive
1826 bytes raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/env python3
"""quotecard_render.py — premium HIGH LVL quote card (1080x1350) from a video frame + a quote."""
import argparse, json, subprocess, tempfile, urllib.parse
from pathlib import Path
HERE = Path(__file__).resolve().parent; STUDIO = HERE.parent
TPL = STUDIO / "dashboard" / "styles" / "quotecard.html"
FF = "/opt/homebrew/opt/ffmpeg-full/bin/ffmpeg"

def render(video, t, quote, out, by="19 KEYS", kick="MASTERCLASS · LONDON"):
    out = Path(out); out.parent.mkdir(parents=True, exist_ok=True)
    from playwright.sync_api import sync_playwright
    with tempfile.TemporaryDirectory() as td:
        frame = Path(td) / "f.jpg"
        subprocess.run([FF, "-y", "-ss", str(float(t)), "-i", str(video), "-frames:v", "1",
                        "-vf", "scale=1080:1350:force_original_aspect_ratio=increase,crop=1080:1350",
                        "-q:v", "3", str(frame)], capture_output=True)
        params = {"q": quote, "by": by, "kick": kick, "bg": frame.as_uri()}
        url = TPL.as_uri() + "?" + urllib.parse.urlencode(params)
        with sync_playwright() as pw:
            b = pw.chromium.launch()
            pg = b.new_page(viewport={"width": 1080, "height": 1350}, device_scale_factor=1)
            pg.goto(url, wait_until="networkidle"); pg.wait_for_timeout(550)
            pg.screenshot(path=str(out), clip={"x": 0, "y": 0, "width": 1080, "height": 1350})
            b.close()
    if not out.exists():
        raise RuntimeError("card render failed")
    return str(out)

if __name__ == "__main__":
    a = argparse.ArgumentParser()
    for x in ("video", "out", "quote"): a.add_argument("--" + x, required=True)
    a.add_argument("--t", type=float, required=True); a.add_argument("--by", default="19 KEYS")
    p = a.parse_args(); print(render(p.video, p.t, p.quote, p.out, p.by))