Yuv-Viral-Video The signature YUV.AI viral-short pipeline. Two skills working together : - — transcribes the source via ElevenLabs Scribe, picks word-snapped cuts, extracts and concats segments into a . This is the cuts + base layout layer. - — takes the base as a background video and adds the visual composition layer in HTML/CSS/GSAP: liquid-glass cards with real , GSAP motion graphics with springy easing, word-by-word karaoke captions, scene transitions, and renders to MP4 via Chromium. You MUST use both. Do not invent your own PIL-based cards, do not pre-bake blur into PNGs, do not write y…

, NO 'ביי שירותי תשלום',\nNO 'ב-0 שקלים', NO '100% הבנה'. Only what was actually said.\n\nAvatar font fix: Hebrew letters use RUBIK not Anton.\n\"\"\"\nfrom __future__ import annotations\nfrom pathlib import Path\nfrom PIL import Image, ImageDraw, ImageFont, ImageFilter\nimport sys\n\nsys.path.insert(0, r\"C:\\Users\\User\\Desktop\\edit\")\nfrom apple_glass import (\n blank, apple_glass_card, make_glass_mask,\n draw_text_safe as t_text, RAD_BANNER, RAD_CARD, RAD_PIP, COLORS,\n KEY_STRIP_16X9,\n)\nfrom bidi import get_display\n\n\ndef rtl(s):\n return get_display(s)\n\n\nEDIT = Path(r\"C:\\Users\\User\\Downloads\\tt_edit\")\nFONTS = Path(r\"C:\\Users\\User\\Desktop\\edit\\fonts\")\nANTON = str(FONTS / \"Anton-Regular.ttf\")\nRUBIK = str(FONTS / \"Rubik-Black.ttf\")\nRUBIK_B = str(FONTS / \"Rubik-Bold.ttf\")\n\n\ndef fill(d, x, y, w, h, color):\n d.rectangle([x, y, x + w, y + h], fill=color)\n\n\ndef round_fill(d, x, y, w, h, color, radius=20):\n d.rounded_rectangle([x, y, x + w, y + h], radius=radius, fill=color)\n\n\ndef brand_icon(W, H, cx, cy, size, color, letter, font):\n img = blank(W, H)\n glow = blank(W, H)\n gd = ImageDraw.Draw(glow)\n gd.ellipse([cx - size, cy - size, cx + size, cy + size], fill=color + (140,))\n glow = glow.filter(ImageFilter.GaussianBlur(radius=size // 4))\n img = Image.alpha_composite(img, glow)\n d2 = ImageDraw.Draw(img)\n d2.ellipse([cx - size // 2, cy - size // 2, cx + size // 2, cy + size // 2],\n fill=color + (255,), outline=(255, 255, 255, 220), width=3)\n t_text(img, (cx, cy + 2), letter, font, fill=(255, 255, 255, 255),\n stroke=(0, 0, 0, 200), stroke_w=3)\n return img\n\n\n# Bottom strip for tt.mp4 9:16 — moved BELOW speaker (very bottom)\nBOTTOM_STRIP_9X16 = {\"x\": 40, \"y\": 1750, \"w\": 1000, \"h\": 130, \"radius\": 36}\n\n\ndef _key_card_9x16(W, H, label_he, label_en):\n k = BOTTOM_STRIP_9X16\n def content(W, H, x, y, w, h):\n c = blank(W, H)\n f_en = ImageFont.truetype(ANTON, 56)\n f_he = ImageFont.truetype(RUBIK, 46)\n if label_en:\n t_text(c, (x + 200, y + h // 2), label_en, f_en,\n fill=(255, 230, 30, 255), stroke=(0, 0, 0, 220), stroke_w=3, anchor=\"lm\")\n if label_he:\n t_text(c, (x + w - 60, y + h // 2), rtl(label_he), f_he,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 200), stroke_w=2, anchor=\"rm\")\n d = ImageDraw.Draw(c)\n round_fill(d, x + 30, y + 25, 14, h - 50, (255, 230, 30, 255), radius=7)\n return c\n img = apple_glass_card(W, H, k[\"x\"], k[\"y\"], k[\"w\"], k[\"h\"], k[\"radius\"],\n tint=(0, 0, 0, 130), content_fn=content)\n mask = make_glass_mask(W, H, k[\"x\"], k[\"y\"], k[\"w\"], k[\"h\"], k[\"radius\"])\n return img, mask\n\n\ndef _key_card_16x9(W, H, label_he, label_en):\n k = KEY_STRIP_16X9\n def content(W, H, x, y, w, h):\n c = blank(W, H)\n f_en = ImageFont.truetype(ANTON, 56)\n f_he = ImageFont.truetype(RUBIK, 46)\n if label_en:\n t_text(c, (x + 200, y + h // 2), label_en, f_en,\n fill=(255, 230, 30, 255), stroke=(0, 0, 0, 220), stroke_w=3, anchor=\"lm\")\n if label_he:\n t_text(c, (x + w - 60, y + h // 2), rtl(label_he), f_he,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 200), stroke_w=2, anchor=\"rm\")\n d = ImageDraw.Draw(c)\n round_fill(d, x + 30, y + 25, 14, h - 50, (255, 230, 30, 255), radius=7)\n return c\n img = apple_glass_card(W, H, k[\"x\"], k[\"y\"], k[\"w\"], k[\"h\"], k[\"radius\"],\n tint=(0, 0, 0, 130), content_fn=content)\n mask = make_glass_mask(W, H, k[\"x\"], k[\"y\"], k[\"w\"], k[\"h\"], k[\"radius\"])\n return img, mask\n\n\n# ====================== 9:16 — TOP-BANNER LAYOUT ======================\ndef cards_9x16(out_dir):\n out_dir.mkdir(parents=True, exist_ok=True)\n W, H = 1080, 1920\n # Top banner area: x=40-1040 (1000 wide), y=80-450 (370 tall) — above face\n BX, BY, BW = 40, 80, 1000\n\n # ---- HOOK ----\n def hook_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_huge = ImageFont.truetype(RUBIK, 130)\n f_sub = ImageFont.truetype(RUBIK_B, 50)\n f_lab = ImageFont.truetype(RUBIK_B, 28)\n t_text(c, (x + w // 2, y + 50), rtl(\"לא צריך לשלם!\"), f_lab, fill=(255, 230, 30, 255))\n round_fill(d, x + 60, y + 100, w - 120, 150, (255, 230, 30, 255), radius=44)\n t_text(c, (x + w // 2, y + 175), rtl(\"די לשלם\"), f_huge,\n fill=(0, 0, 0, 255))\n round_fill(d, x + 60, y + 270, w - 120, 70, (0, 0, 0, 255), radius=24)\n t_text(c, (x + w // 2, y + 305), rtl(\"יש קלאוד דסקטופ\"), f_sub,\n fill=(255, 230, 30, 255))\n return c\n\n H_HK = 370\n img = apple_glass_card(W, H, BX, BY, BW, H_HK, RAD_CARD,\n tint=(0, 0, 0, 130), content_fn=hook_content)\n img.save(out_dir / \"hook.png\")\n make_glass_mask(W, H, BX, BY, BW, H_HK, RAD_CARD).save(out_dir / \"hook_mask.png\")\n\n # ---- WORKSHOP ----\n def workshop_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_lab = ImageFont.truetype(RUBIK_B, 26)\n f_title = ImageFont.truetype(RUBIK, 50)\n f_val = ImageFont.truetype(ANTON, 80)\n f_he = ImageFont.truetype(RUBIK, 30)\n t_text(c, (x + w // 2, y + 35), rtl(\"אתמול בסדנה\"), f_lab, fill=(255, 230, 30, 255))\n t_text(c, (x + w // 2, y + 100), rtl(\"רייכמן\"), f_title,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 200), stroke_w=2)\n # Stats: real values from transcript only\n stats = [\n (\"3\", rtl(\"שעות\"), (255, 230, 30)),\n (\"0\", rtl(\"ידע קודם\"), COLORS[\"blue\"]),\n ]\n cell_w = (w - 60) // 2\n cy = y + 180\n cell_h = 170\n for i, (val, lab, color) in enumerate(stats):\n cx = x + 30 + i * cell_w\n round_fill(d, cx + 12, cy, cell_w - 24, cell_h, color + (60,), radius=22)\n d.rounded_rectangle([cx + 12, cy, cx + cell_w - 12, cy + cell_h],\n radius=22, outline=color + (200,), width=3)\n t_text(c, (cx + cell_w // 2, cy + 70), val, f_val,\n fill=color + (255,), stroke=(0, 0, 0, 220), stroke_w=3)\n t_text(c, (cx + cell_w // 2, cy + 140), lab, f_he, fill=(255, 255, 255, 255))\n return c\n\n H_WS = 380\n img = apple_glass_card(W, H, BX, BY, BW, H_WS, RAD_CARD,\n tint=(255, 255, 255, 30), content_fn=workshop_content)\n img.save(out_dir / \"workshop.png\")\n make_glass_mask(W, H, BX, BY, BW, H_WS, RAD_CARD).save(out_dir / \"workshop_mask.png\")\n\n # ---- STUDENT (avatar uses RUBIK, not Anton, for Hebrew letter) ----\n def student_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_lab = ImageFont.truetype(RUBIK_B, 26)\n f_name = ImageFont.truetype(RUBIK, 80)\n f_role = ImageFont.truetype(RUBIK, 36)\n f_quote = ImageFont.truetype(RUBIK, 32)\n f_letter = ImageFont.truetype(RUBIK, 64) # Rubik supports Hebrew\n t_text(c, (x + w // 2, y + 35), rtl(\"בסוף הסדנה\"), f_lab, fill=(255, 230, 30, 255))\n # Avatar (left side) + name+role (right side)\n avatar = brand_icon(W, H, x + 130, y + 200, 110, COLORS[\"pink\"], rtl(\"א\"), f_letter)\n c = Image.alpha_composite(c, avatar)\n d = ImageDraw.Draw(c)\n t_text(c, (x + w - 80, y + 130), rtl(\"אריאל\"), f_name,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 200), stroke_w=3, anchor=\"rm\")\n t_text(c, (x + w - 80, y + 200), rtl(\"סטודנטית\"), f_role,\n fill=(220, 220, 230, 255), anchor=\"rm\")\n # quote\n round_fill(d, x + 60, y + 280, w - 120, 70, (255, 255, 255, 30), radius=24)\n d.rounded_rectangle([x + 60, y + 280, x + w - 60, y + 350],\n radius=24, outline=(255, 255, 255, 100), width=2)\n t_text(c, (x + w // 2, y + 315), rtl(\"משתמשת בגרמרלי\"), f_quote,\n fill=(255, 255, 255, 255))\n return c\n\n H_ST = 380\n img = apple_glass_card(W, H, BX, BY, BW, H_ST, RAD_CARD,\n tint=(255, 255, 255, 30), content_fn=student_content)\n img.save(out_dir / \"student.png\")\n make_glass_mask(W, H, BX, BY, BW, H_ST, RAD_CARD).save(out_dir / \"student_mask.png\")\n\n # ---- BUILD_15MIN ----\n def build_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_huge = ImageFont.truetype(ANTON, 200)\n f_lab = ImageFont.truetype(RUBIK_B, 26)\n f_he = ImageFont.truetype(RUBIK, 40)\n t_text(c, (x + w // 2, y + 35), rtl(\"רבע שעה\"), f_lab, fill=(255, 230, 30, 255))\n t_text(c, (x + w // 2, y + 175), \"15:00\", f_huge,\n fill=(255, 230, 30, 255), stroke=(0, 0, 0, 220), stroke_w=8)\n round_fill(d, x + w // 2 - 100, y + 290, 200, 6, (255, 230, 30, 255), radius=3)\n t_text(c, (x + w // 2, y + 340), rtl(\"עבד\"), f_he,\n fill=(255, 255, 255, 255))\n return c\n\n H_BL = 380\n img = apple_glass_card(W, H, BX, BY, BW, H_BL, RAD_CARD,\n tint=(0, 0, 0, 140), content_fn=build_content)\n img.save(out_dir / \"build_15min.png\")\n make_glass_mask(W, H, BX, BY, BW, H_BL, RAD_CARD).save(out_dir / \"build_15min_mask.png\")\n\n # ---- RESULT ----\n def result_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_en = ImageFont.truetype(ANTON, 84)\n f_he = ImageFont.truetype(RUBIK, 38)\n f_lab = ImageFont.truetype(RUBIK_B, 26)\n round_fill(d, x + 60, y + 35, w - 120, 8, COLORS[\"blue\"] + (255,), radius=4)\n t_text(c, (x + w // 2, y + 75), rtl(\"התוצאה\"), f_lab, fill=COLORS[\"blue\"] + (255,))\n t_text(c, (x + w // 2, y + 165), \"WINDOWS APP\", f_en,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 220), stroke_w=4)\n round_fill(d, x + w // 2 - 90, y + 230, 180, 6, COLORS[\"blue\"] + (255,), radius=3)\n t_text(c, (x + w // 2, y + 285), rtl(\"מתקנת שגיאות באנגלית\"), f_he,\n fill=(220, 230, 255, 255))\n return c\n\n H_RS = 360\n img = apple_glass_card(W, H, BX, BY, BW, H_RS, RAD_CARD,\n tint=(255, 255, 255, 30), content_fn=result_content)\n img.save(out_dir / \"result.png\")\n make_glass_mask(W, H, BX, BY, BW, H_RS, RAD_CARD).save(out_dir / \"result_mask.png\")\n\n # ---- NO_PAY ----\n def nopay_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_big = ImageFont.truetype(ANTON, 120)\n f_he = ImageFont.truetype(RUBIK, 40)\n f_lab = ImageFont.truetype(RUBIK_B, 26)\n round_fill(d, x + 60, y + 35, w - 120, 8, (255, 80, 80, 255), radius=4)\n t_text(c, (x + w // 2, y + 75), rtl(\"לא צריך לשלם\"), f_lab, fill=(255, 80, 80, 255))\n t_text(c, (x + w // 2, y + 200), \"GRAMMARLY\", f_big,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 220), stroke_w=4)\n round_fill(d, x + 130, y + 195, w - 260, 10, (255, 80, 80, 255), radius=5)\n t_text(c, (x + w // 2, y + 310), rtl(\"גם לא לצד ג'\"), f_he, fill=(220, 220, 230, 255))\n return c\n\n H_NP = 380\n img = apple_glass_card(W, H, BX, BY, BW, H_NP, RAD_CARD,\n tint=(60, 10, 10, 160), content_fn=nopay_content)\n img.save(out_dir / \"no_pay.png\")\n make_glass_mask(W, H, BX, BY, BW, H_NP, RAD_CARD).save(out_dir / \"no_pay_mask.png\")\n\n # ---- MAGIC stamp (NOT a glass card — full-frame title) ----\n img = blank(W, H)\n halo = blank(W, H)\n dh = ImageDraw.Draw(halo)\n dh.ellipse([BX - 20, 250, BX + BW + 20, 750], fill=(255, 90, 0, 200))\n halo = halo.filter(ImageFilter.GaussianBlur(radius=80))\n img = Image.alpha_composite(img, halo)\n f_huge = ImageFont.truetype(RUBIK, 130)\n t_text(img, (BX + BW // 2, 380), rtl(\"מצליחים\"), f_huge,\n fill=(255, 230, 30, 255), stroke=(0, 0, 0, 255), stroke_w=8)\n t_text(img, (BX + BW // 2, 530), rtl(\"לעשות הכל\"), f_huge,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 255), stroke_w=8)\n img.save(out_dir / \"magic.png\")\n\n # ---- CTA ----\n def cta_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_en = ImageFont.truetype(ANTON, 100)\n f_he = ImageFont.truetype(RUBIK, 60)\n round_fill(d, x + 80, y + 60, w - 160, 130, COLORS[\"pink\"] + (255,), radius=65)\n t_text(c, (x + w // 2, y + 130), \"AI MINDSET\", f_en,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 220), stroke_w=4)\n t_text(c, (x + w // 2, y + 260), rtl(\"יום טוב\"), f_he,\n fill=(255, 230, 30, 255), stroke=(0, 0, 0, 200), stroke_w=4)\n return c\n\n H_CT = 340\n img = apple_glass_card(W, H, BX, BY, BW, H_CT, RAD_CARD,\n tint=(0, 0, 0, 130), content_fn=cta_content)\n img.save(out_dir / \"cta.png\")\n make_glass_mask(W, H, BX, BY, BW, H_CT, RAD_CARD).save(out_dir / \"cta_mask.png\")\n\n # Bottom key-moment strips at very bottom\n for name, he, en in [\n (\"km_hook\", \"די לשלם\", \"\"),\n (\"km_workshop\", \"סדנה ברייכמן\", \"\"),\n (\"km_build\", \"רבע שעה\", \"15 MIN\"),\n (\"km_result\", \"תוכנה במחשב\", \"WINDOWS APP\"),\n (\"km_nopay\", \"בלי לשלם\", \"\"),\n (\"km_magic\", \"מצליחים\", \"\"),\n (\"km_cta\", \"מיינדסט של AI\", \"AI MINDSET\"),\n ]:\n img, mask = _key_card_9x16(W, H, he, en)\n img.save(out_dir / f\"{name}.png\")\n mask.save(out_dir / f\"{name}_mask.png\")\n\n\n# ====================== 16:9 — LEFT-HALF (unchanged from v4) ======================\ndef cards_16x9(out_dir):\n \"\"\"For 16:9, the speaker is letterboxed centered (607x1080) with blurred BG.\n Cards on left half (x=60-1140) sit on the blurred BG, NOT over the speaker.\"\"\"\n out_dir.mkdir(parents=True, exist_ok=True)\n W, H = 1920, 1080\n LX, LY, LW = 60, 100, 1080\n\n # HOOK\n def hook_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_huge = ImageFont.truetype(RUBIK, 160)\n f_sub = ImageFont.truetype(RUBIK_B, 56)\n f_lab = ImageFont.truetype(RUBIK_B, 30)\n t_text(c, (x + w // 2, y + 60), rtl(\"לא צריך לשלם!\"), f_lab, fill=(255, 230, 30, 255))\n round_fill(d, x + 60, y + 140, w - 120, 240, (255, 230, 30, 255), radius=60)\n t_text(c, (x + w // 2, y + 260), rtl(\"די לשלם\"), f_huge,\n fill=(0, 0, 0, 255))\n round_fill(d, x + 60, y + 410, w - 120, 90, (0, 0, 0, 255), radius=30)\n t_text(c, (x + w // 2, y + 455), rtl(\"יש קלאוד דסקטופ\"), f_sub,\n fill=(255, 230, 30, 255))\n return c\n\n H_HK = 600\n img = apple_glass_card(W, H, LX, LY, LW, H_HK, RAD_CARD,\n tint=(0, 0, 0, 100), content_fn=hook_content)\n img.save(out_dir / \"hook.png\")\n make_glass_mask(W, H, LX, LY, LW, H_HK, RAD_CARD).save(out_dir / \"hook_mask.png\")\n\n def workshop_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_lab = ImageFont.truetype(RUBIK_B, 30)\n f_title = ImageFont.truetype(RUBIK, 56)\n f_val = ImageFont.truetype(ANTON, 110)\n f_he = ImageFont.truetype(RUBIK, 38)\n t_text(c, (x + w // 2, y + 60), rtl(\"אתמול בסדנה\"), f_lab, fill=(255, 230, 30, 255))\n t_text(c, (x + w // 2, y + 160), rtl(\"רייכמן\"), f_title,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 200), stroke_w=2)\n stats = [\n (\"3\", rtl(\"שעות\"), (255, 230, 30)),\n (\"0\", rtl(\"ידע קודם\"), COLORS[\"blue\"]),\n ]\n cell_w = (w - 60) // 2\n cy = y + 280\n cell_h = 240\n for i, (val, lab, color) in enumerate(stats):\n cx = x + 30 + i * cell_w\n round_fill(d, cx + 12, cy, cell_w - 24, cell_h, color + (60,), radius=24)\n d.rounded_rectangle([cx + 12, cy, cx + cell_w - 12, cy + cell_h],\n radius=24, outline=color + (200,), width=3)\n t_text(c, (cx + cell_w // 2, cy + 100), val, f_val,\n fill=color + (255,), stroke=(0, 0, 0, 220), stroke_w=3)\n t_text(c, (cx + cell_w // 2, cy + 200), lab, f_he, fill=(255, 255, 255, 255))\n return c\n\n H_WS = 600\n img = apple_glass_card(W, H, LX, LY, LW, H_WS, RAD_CARD,\n tint=(255, 255, 255, 30), content_fn=workshop_content)\n img.save(out_dir / \"workshop.png\")\n make_glass_mask(W, H, LX, LY, LW, H_WS, RAD_CARD).save(out_dir / \"workshop_mask.png\")\n\n def student_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_lab = ImageFont.truetype(RUBIK_B, 30)\n f_name = ImageFont.truetype(RUBIK, 100)\n f_role = ImageFont.truetype(RUBIK, 46)\n f_quote = ImageFont.truetype(RUBIK, 40)\n f_letter = ImageFont.truetype(RUBIK, 80) # FIXED: Rubik for Hebrew\n t_text(c, (x + w // 2, y + 60), rtl(\"בסוף הסדנה\"), f_lab, fill=(255, 230, 30, 255))\n avatar = brand_icon(W, H, x + w // 2, y + 220, 140, COLORS[\"pink\"], rtl(\"א\"), f_letter)\n c = Image.alpha_composite(c, avatar)\n d = ImageDraw.Draw(c)\n t_text(c, (x + w // 2, y + 340), rtl(\"אריאל\"), f_name,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 200), stroke_w=3)\n t_text(c, (x + w // 2, y + 430), rtl(\"סטודנטית\"), f_role,\n fill=(220, 220, 230, 255))\n round_fill(d, x + 200, y + 510, w - 400, 100, (255, 255, 255, 30), radius=28)\n d.rounded_rectangle([x + 200, y + 510, x + w - 200, y + 610],\n radius=28, outline=(255, 255, 255, 100), width=2)\n t_text(c, (x + w // 2, y + 560), rtl(\"משתמשת בגרמרלי\"), f_quote,\n fill=(255, 255, 255, 255))\n return c\n\n H_ST = 660\n img = apple_glass_card(W, H, LX, LY, LW, H_ST, RAD_CARD,\n tint=(255, 255, 255, 30), content_fn=student_content)\n img.save(out_dir / \"student.png\")\n make_glass_mask(W, H, LX, LY, LW, H_ST, RAD_CARD).save(out_dir / \"student_mask.png\")\n\n def build_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_huge = ImageFont.truetype(ANTON, 320)\n f_lab = ImageFont.truetype(RUBIK_B, 30)\n f_he = ImageFont.truetype(RUBIK, 56)\n t_text(c, (x + w // 2, y + 60), rtl(\"רבע שעה\"), f_lab, fill=(255, 230, 30, 255))\n t_text(c, (x + w // 2, y + 280), \"15:00\", f_huge,\n fill=(255, 230, 30, 255), stroke=(0, 0, 0, 220), stroke_w=10)\n round_fill(d, x + w // 2 - 130, y + 460, 260, 8, (255, 230, 30, 255), radius=4)\n t_text(c, (x + w // 2, y + 540), rtl(\"עבד\"), f_he, fill=(255, 255, 255, 255))\n return c\n\n H_BL = 620\n img = apple_glass_card(W, H, LX, LY, LW, H_BL, RAD_CARD,\n tint=(0, 0, 0, 140), content_fn=build_content)\n img.save(out_dir / \"build_15min.png\")\n make_glass_mask(W, H, LX, LY, LW, H_BL, RAD_CARD).save(out_dir / \"build_15min_mask.png\")\n\n def result_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_en = ImageFont.truetype(ANTON, 130)\n f_he = ImageFont.truetype(RUBIK, 54)\n f_lab = ImageFont.truetype(RUBIK_B, 30)\n round_fill(d, x + 60, y + 70, w - 120, 12, COLORS[\"blue\"] + (255,), radius=6)\n t_text(c, (x + w // 2, y + 130), rtl(\"התוצאה\"), f_lab, fill=COLORS[\"blue\"] + (255,))\n t_text(c, (x + w // 2, y + 270), \"WINDOWS APP\", f_en,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 220), stroke_w=4)\n round_fill(d, x + w // 2 - 130, y + 360, 260, 6, COLORS[\"blue\"] + (255,), radius=3)\n t_text(c, (x + w // 2, y + 440), rtl(\"מתקנת שגיאות באנגלית\"), f_he,\n fill=(220, 230, 255, 255))\n return c\n\n H_RS = 540\n img = apple_glass_card(W, H, LX, LY, LW, H_RS, RAD_CARD,\n tint=(255, 255, 255, 30), content_fn=result_content)\n img.save(out_dir / \"result.png\")\n make_glass_mask(W, H, LX, LY, LW, H_RS, RAD_CARD).save(out_dir / \"result_mask.png\")\n\n def nopay_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_big = ImageFont.truetype(ANTON, 130)\n f_he = ImageFont.truetype(RUBIK, 56)\n f_lab = ImageFont.truetype(RUBIK_B, 30)\n round_fill(d, x + 60, y + 70, w - 120, 12, (255, 80, 80, 255), radius=6)\n t_text(c, (x + w // 2, y + 130), rtl(\"לא צריך לשלם\"), f_lab, fill=(255, 80, 80, 255))\n t_text(c, (x + w // 2, y + 280), \"GRAMMARLY\", f_big,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 220), stroke_w=5)\n round_fill(d, x + 130, y + 270, w - 260, 12, (255, 80, 80, 255), radius=6)\n t_text(c, (x + w // 2, y + 420), rtl(\"גם לא לצד ג'\"), f_he, fill=(220, 220, 230, 255))\n return c\n\n H_NP = 540\n img = apple_glass_card(W, H, LX, LY, LW, H_NP, RAD_CARD,\n tint=(60, 10, 10, 160), content_fn=nopay_content)\n img.save(out_dir / \"no_pay.png\")\n make_glass_mask(W, H, LX, LY, LW, H_NP, RAD_CARD).save(out_dir / \"no_pay_mask.png\")\n\n # MAGIC stamp\n img = blank(W, H)\n halo = blank(W, H)\n dh = ImageDraw.Draw(halo)\n cxw, cyw = 600, 540\n dh.ellipse([cxw - 700, cyw - 280, cxw + 700, cyw + 280], fill=(255, 90, 0, 200))\n halo = halo.filter(ImageFilter.GaussianBlur(radius=80))\n img = Image.alpha_composite(img, halo)\n f_huge = ImageFont.truetype(RUBIK, 200)\n t_text(img, (cxw, cyw - 110), rtl(\"מצליחים\"), f_huge,\n fill=(255, 230, 30, 255), stroke=(0, 0, 0, 255), stroke_w=10)\n t_text(img, (cxw, cyw + 110), rtl(\"לעשות הכל\"), f_huge,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 255), stroke_w=10)\n img.save(out_dir / \"magic.png\")\n\n def cta_content(W, H, x, y, w, h):\n c = blank(W, H)\n d = ImageDraw.Draw(c)\n f_en = ImageFont.truetype(ANTON, 130)\n f_he = ImageFont.truetype(RUBIK, 80)\n round_fill(d, x + 60, y + 70, w - 120, 200, COLORS[\"pink\"] + (255,), radius=100)\n t_text(c, (x + w // 2, y + 170), \"AI MINDSET\", f_en,\n fill=(255, 255, 255, 255), stroke=(0, 0, 0, 220), stroke_w=5)\n t_text(c, (x + w // 2, y + 380), rtl(\"יום טוב\"), f_he,\n fill=(255, 230, 30, 255), stroke=(0, 0, 0, 200), stroke_w=4)\n return c\n\n H_CT = 480\n img = apple_glass_card(W, H, LX, LY, LW, H_CT, RAD_CARD,\n tint=(0, 0, 0, 130), content_fn=cta_content)\n img.save(out_dir / \"cta.png\")\n make_glass_mask(W, H, LX, LY, LW, H_CT, RAD_CARD).save(out_dir / \"cta_mask.png\")\n\n for name, he, en in [\n (\"km_hook\", \"די לשלם\", \"\"),\n (\"km_workshop\", \"סדנה ברייכמן\", \"\"),\n (\"km_build\", \"רבע שעה\", \"15 MIN\"),\n (\"km_result\", \"תוכנה במחשב\", \"WINDOWS APP\"),\n (\"km_nopay\", \"בלי לשלם\", \"\"),\n (\"km_magic\", \"מצליחים\", \"\"),\n (\"km_cta\", \"מיינדסט של AI\", \"AI MINDSET\"),\n ]:\n img, mask = _key_card_16x9(W, H, he, en)\n img.save(out_dir / f\"{name}.png\")\n mask.save(out_dir / f\"{name}_mask.png\")\n\n\ndef main():\n # Overwrite cards_v4_* (used by composite_v5) so we don't have to update composite paths\n cards_9x16(EDIT / \"cards_v4_9x16\")\n cards_16x9(EDIT / \"cards_v4_16x9\")\n for d in [EDIT / \"cards_v4_9x16\", EDIT / \"cards_v4_16x9\"]:\n n = len(list(d.glob(\"*.png\")))\n print(f\" {d.name}: {n} files\")\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":24177,"content_sha256":"328f6110c4d80d0910a3239850cedad6b10fb4aa3f746d5784c2f90285b7997e"},{"filename":"scripts/make_karaoke.py","content":"\"\"\"V2 karaoke — bigger video-title style, positioned in the LEFT HALF\n(below the cards, above the bottom key-moment strip). Per-word pop with\nstrong scale entrance + slight Y-translation. Hebrew = Rubik Black.\nEnglish brand tokens = Anton.\n\"\"\"\nfrom __future__ import annotations\nimport json, re\nfrom pathlib import Path\n\nEDIT = Path(r\"C:\\Users\\User\\Desktop\\edit\")\nTRANSCRIPT = EDIT / \"transcripts\" / \"0423.json\"\nEDL = EDIT / \"edl.json\"\n\n# 9:16: Caption row at bottom-left of left-half (left half = x 0-540).\n# Alignment=2 (bottom-center). MarginL=0, MarginR=540 forces center within 0..540.\n# MarginV from bottom: 380 places at y=1540 (above key-moment strip @ y=1730).\n# 16:9: Caption row at bottom-left half. MarginR=860 forces center within 0..1060.\n# MarginV=170 places at y=910 (above key strip @ y=920).\nASS_HEADERS = {\n \"9x16\": \"\"\"[Script Info]\nScriptType: v4.00+\nPlayResX: 1080\nPlayResY: 1920\nWrapStyle: 2\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.709\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: HE,Rubik Black,108,&H00FFFFFF,&H00FFFFFF,&H00111111,&H00000000,1,0,0,0,100,100,0,0,1,9,4,2,0,0,40,1\nStyle: EN,Anton,124,&H0000E5FF,&H0000E5FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,11,4,2,0,0,40,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n\"\"\",\n \"16x9\": \"\"\"[Script Info]\nScriptType: v4.00+\nPlayResX: 1920\nPlayResY: 1080\nWrapStyle: 2\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.709\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: HE,Rubik Black,90,&H00FFFFFF,&H00FFFFFF,&H00111111,&H00000000,1,0,0,0,100,100,0,0,1,7,3,2,0,440,80,1\nStyle: EN,Anton,104,&H0000E5FF,&H0000E5FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,9,3,2,0,440,80,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n\"\"\",\n}\n\nENGLISH_RE = re.compile(r\"^[A-Za-z][A-Za-z0-9\\-]*$\")\nACCENT_HE = {\"מטורף\", \"טירוף\", \"אוטומטית\", \"גדול\", \"גרפיקות\", \"ננו\", \"בננה\", \"חדש\"}\n\n\ndef fmt_time(t):\n h = int(t // 3600)\n m = int((t % 3600) // 60)\n s = t - h * 3600 - m * 60\n cs = int(round((s - int(s)) * 100))\n sec = int(s)\n if cs == 100:\n cs = 0\n sec += 1\n return f\"{h:01d}:{m:02d}:{sec:02d}.{cs:02d}\"\n\n\ndef escape(text):\n text = text.strip()\n while text and text[-1] in \",.;:\":\n text = text[:-1]\n return text.replace(\"\\\\\", \"\\\\\\\\\").replace(\"{\", \"\\\\{\").replace(\"}\", \"\\\\}\")\n\n\ndef main():\n transcript = json.loads(TRANSCRIPT.read_text(encoding=\"utf-8\"))\n edl = json.loads(EDL.read_text(encoding=\"utf-8\"))\n words = [w for w in transcript[\"words\"] if w.get(\"type\") == \"word\"]\n\n events = []\n seg_offset = 0.0\n for r in edl[\"ranges\"]:\n rs, re_ = float(r[\"start\"]), float(r[\"end\"])\n dur = re_ - rs\n in_range = [w for w in words if w[\"start\"] >= rs and w[\"end\"] \u003c= re_ + 0.05]\n for i, w in enumerate(in_range):\n local_start = max(0.0, w[\"start\"] - rs)\n if i + 1 \u003c len(in_range):\n local_end = max(local_start + 0.08, in_range[i + 1][\"start\"] - rs)\n else:\n local_end = min(dur, w[\"end\"] - rs + 0.30)\n out_start = local_start + seg_offset\n out_end = local_end + seg_offset\n raw = w[\"text\"].strip()\n if not raw:\n continue\n clean = escape(raw)\n if not clean:\n continue\n is_eng = bool(ENGLISH_RE.match(clean))\n is_accent = clean in ACCENT_HE\n # Stronger video-title pop: scale 1.45 -> 1.0 with cubic settle, slight slide-up\n # \\fad(60,80) for in/out fade, \\move for upward slide\n pop = (r\"{\\fscx150\\fscy150\\t(0,140,\\fscx100\\fscy100)\"\n r\"\\fad(60,80)\")\n if is_eng:\n style = \"EN\"\n text = pop + r\"}\" + clean.upper()\n elif is_accent:\n style = \"HE\"\n text = pop + r\"\\c&H0000E5FF&\\t(0,80,\\frz-3)\\t(80,160,\\frz3)\\t(160,220,\\frz0)}\" + clean\n else:\n style = \"HE\"\n text = pop + r\"}\" + clean\n events.append(\n f\"Dialogue: 0,{fmt_time(out_start)},{fmt_time(out_end)},{style},,0,0,0,,{text}\"\n )\n seg_offset += dur\n\n body = \"\\n\".join(events) + \"\\n\"\n for aspect, header in ASS_HEADERS.items():\n out_path = EDIT / (\"karaoke.ass\" if aspect == \"9x16\" else f\"karaoke_{aspect}.ass\")\n out_path.write_text(header + body, encoding=\"utf-8\")\n print(f\" wrote {out_path.name}: {len(events)} events ({aspect})\")\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":5056,"content_sha256":"25296c3465e443d98e6307373fe258b5ecbd8a9b7452eeacefc48032cb988549"},{"filename":"scripts/make_layout_assets.py","content":"\"\"\"Pre-render shared layout assets used by both video pipelines:\n bg_9x16.png / bg_16x9.png — dark gradient + soft speaker shadow\n speaker_mask_9x16.png / 16x9.png — rounded rect alpha for the speaker card\n\"\"\"\nfrom pathlib import Path\nimport sys\nsys.path.insert(0, r\"C:\\Users\\User\\Desktop\\edit\")\nfrom apple_glass import (make_dark_bg, make_pip_mask_local,\n SPEAKER_9X16, SPEAKER_16X9)\n\nEDIT = Path(r\"C:\\Users\\User\\Desktop\\edit\") / \"layout_assets\"\nEDIT.mkdir(parents=True, exist_ok=True)\n\n\ndef main():\n # 9:16 dark BG with speaker-shaped shadow\n bg = make_dark_bg(1080, 1920, (\n SPEAKER_9X16[\"x\"], SPEAKER_9X16[\"y\"],\n SPEAKER_9X16[\"w\"], SPEAKER_9X16[\"h\"],\n SPEAKER_9X16[\"radius\"],\n ))\n bg.save(EDIT / \"bg_9x16.png\")\n\n bg = make_dark_bg(1920, 1080, (\n SPEAKER_16X9[\"x\"], SPEAKER_16X9[\"y\"],\n SPEAKER_16X9[\"w\"], SPEAKER_16X9[\"h\"],\n SPEAKER_16X9[\"radius\"],\n ))\n bg.save(EDIT / \"bg_16x9.png\")\n\n # Speaker masks (sized to the speaker card itself)\n m = make_pip_mask_local(SPEAKER_9X16[\"w\"], SPEAKER_9X16[\"h\"], SPEAKER_9X16[\"radius\"])\n m.save(EDIT / \"speaker_mask_9x16.png\")\n m = make_pip_mask_local(SPEAKER_16X9[\"w\"], SPEAKER_16X9[\"h\"], SPEAKER_16X9[\"radius\"])\n m.save(EDIT / \"speaker_mask_16x9.png\")\n\n for p in sorted(EDIT.glob(\"*.png\")):\n print(f\" {p.name}: {p.stat().st_size // 1024} KB\")\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":1454,"content_sha256":"86b93e85e1d6d37bb4a4266c6205699d9f9471294c66af59459944f1d495bf3d"},{"filename":"scripts/make_sfx.py","content":"\"\"\"Generate SFX with ElevenLabs sound-generation.\"\"\"\nfrom __future__ import annotations\nimport json, os, sys\nfrom pathlib import Path\nimport requests\n\nEDIT = Path(r\"C:\\Users\\User\\Desktop\\edit\")\nSFX = EDIT / \"sfx\"\nSFX.mkdir(parents=True, exist_ok=True)\n\nKEY = None\nfor line in (Path.home() / \"Developer/video-use/.env\").read_text().splitlines():\n if line.startswith(\"ELEVENLABS_API_KEY=\"):\n KEY = line.split(\"=\", 1)[1].strip()\n\nURL = \"https://api.elevenlabs.io/v1/sound-generation\"\n\nPROMPTS = [\n (\"whoosh.mp3\", \"fast tight whoosh transition swoosh, 350ms, sharp\", 0.5),\n (\"impact.mp3\", \"deep boom impact thud, sub-bass slam, single hit, no tail\", 0.7),\n (\"riser.mp3\", \"short rising synth riser build into impact, 1 second, energetic\", 1.2),\n (\"ding.mp3\", \"high-pitched bright ding notification chime, single hit, 250ms\", 0.5),\n (\"typing.mp3\", \"fast mechanical keyboard typing burst, multiple keystrokes, 1.2 seconds\", 1.4),\n (\"glitch.mp3\", \"short digital glitch transition sound, 400ms, sharp tech\", 0.5),\n (\"bass_drop.mp3\",\"bass drop sub-bass thump, deep punchy, single hit no tail\", 0.7),\n]\n\nfor name, prompt, dur in PROMPTS:\n out = SFX / name\n if out.exists():\n print(f\" cached: {name}\")\n continue\n print(f\" generating {name} ({dur}s) ...\", flush=True)\n r = requests.post(URL, headers={\"xi-api-key\": KEY, \"Content-Type\": \"application/json\"},\n json={\"text\": prompt, \"duration_seconds\": dur, \"prompt_influence\": 0.6}, timeout=120)\n if r.status_code != 200:\n print(f\" ERROR {r.status_code}: {r.text[:200]}\")\n sys.exit(1)\n out.write_bytes(r.content)\n print(f\" saved {len(r.content)//1024} KB\")\n\nprint(\"\\nall SFX generated\")\n","content_type":"text/x-python; charset=utf-8","language":"python","size":1862,"content_sha256":"391253c49cddc08937ac5a2079059eba365559a8208a27704ca0c06ebd27bd88"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Yuv-Viral-Video","type":"text"}]},{"type":"paragraph","content":[{"text":"The signature YUV.AI viral-short pipeline. ","type":"text"},{"text":"Two skills working together","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"video-use","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — transcribes the source via ElevenLabs Scribe, picks word-snapped cuts, extracts and concats segments into a ","type":"text"},{"text":"base.mp4","type":"text","marks":[{"type":"code_inline"}]},{"text":". This is the cuts + base layout layer.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"hyperframes","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — takes the base as a background video and adds the visual composition layer in HTML/CSS/GSAP: liquid-glass cards with real ","type":"text"},{"text":"backdrop-filter","type":"text","marks":[{"type":"code_inline"}]},{"text":", GSAP motion graphics with ","type":"text"},{"text":"back.out","type":"text","marks":[{"type":"code_inline"}]},{"text":" springy easing, word-by-word karaoke captions, scene transitions, and renders to MP4 via Chromium.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"You MUST use both.","type":"text","marks":[{"type":"strong"}]},{"text":" Do not invent your own PIL-based cards, do not pre-bake blur into PNGs, do not write your own ffmpeg compositor. The hyperframes skill exists specifically to do the visual layer at Hollywood quality.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Companion skills (read these BEFORE you start)","type":"text"}]},{"type":"paragraph","content":[{"text":"Both companion skills are installed locally and auto-discovered by Claude Code at session start. ","type":"text"},{"text":"You MUST load and apply their guidelines","type":"text","marks":[{"type":"strong"}]},{"text":" — this skill is the ","type":"text"},{"text":"editorial","type":"text","marks":[{"type":"em"}]},{"text":" layer on top of them, not a replacement.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Skill","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Path","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Owns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"video-use","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"~/.claude/skills/video-use/SKILL.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" (symlink → ","type":"text"},{"text":"~/Developer/video-use","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Transcription (ElevenLabs Scribe), word-snapped cuts, color grade, ffmpeg-correctness (per-segment extract → ","type":"text"},{"text":"-c copy","type":"text","marks":[{"type":"code_inline"}]},{"text":" concat, 30 ms audio fades, ","type":"text"},{"text":"setpts=PTS-STARTPTS+T/TB","type":"text","marks":[{"type":"code_inline"}]},{"text":" overlays, output-timeline SRT offsets, transcript caching). Read its ","type":"text"},{"text":"\"Hard Rules (production correctness — non-negotiable)\"","type":"text","marks":[{"type":"strong"}]},{"text":" section before authoring ","type":"text"},{"text":"edl.json","type":"text","marks":[{"type":"code_inline"}]},{"text":". Helpers live at ","type":"text"},{"text":"~/Developer/video-use/helpers/","type":"text","marks":[{"type":"code_inline"}]},{"text":" and are invoked as ","type":"text"},{"text":"python helpers/\u003cname>.py","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"hyperframes","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"~/.claude/skills/hyperframes/SKILL.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"HTML-as-source-of-truth video compositions, ","type":"text"},{"text":"data-*","type":"text","marks":[{"type":"code_inline"}]},{"text":" timing attributes, CSS-driven appearance, frame-accurate library-clock animation (GSAP, Lottie, Motion One). Read its companion docs ","type":"text"},{"text":"house-style.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"data-in-motion.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"patterns.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"visual-styles.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" before writing the composition ","type":"text"},{"text":"index.html","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"hyperframes-cli","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"~/.claude/skills/hyperframes-cli/SKILL.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"The ","type":"text"},{"text":"hyperframes init / lint / preview / render / transcribe / tts","type":"text","marks":[{"type":"code_inline"}]},{"text":" commands. CLI is also installed globally (","type":"text"},{"text":"hyperframes","type":"text","marks":[{"type":"code_inline"}]},{"text":" on ","type":"text"},{"text":"$PATH","type":"text","marks":[{"type":"code_inline"}]},{"text":") so ","type":"text"},{"text":"npx","type":"text","marks":[{"type":"code_inline"}]},{"text":" is optional.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"gsap","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"~/.claude/skills/gsap/SKILL.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"The full GSAP animation vocabulary. The ","type":"text"},{"text":"back.out(1.7)","type":"text","marks":[{"type":"code_inline"}]},{"text":" springy easing rule in this document is one applied pattern; reach for gsap's full toolkit when the material calls for it.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"website-to-hyperframes","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"~/.claude/skills/website-to-hyperframes/SKILL.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"One-shot: scrape a URL → hyperframes composition. Useful when the source has on-screen UI worth re-staging.","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Precedence (when this document conflicts with a companion skill)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Production correctness (cuts, encoding, ffmpeg flags, ffmpeg filter ordering, transcript handling) → companion skill wins.","type":"text","marks":[{"type":"strong"}]},{"text":" If ","type":"text"},{"text":"video-use","type":"text","marks":[{"type":"code_inline"}]},{"text":" says \"subtitles applied LAST in the filter chain after every overlay\" and this document is silent or different, do what ","type":"text"},{"text":"video-use","type":"text","marks":[{"type":"code_inline"}]},{"text":" says. Same for hyperframes API conventions, ","type":"text"},{"text":"data-*","type":"text","marks":[{"type":"code_inline"}]},{"text":" attributes, frame-adapter patterns.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Editorial style (fonts, glass cards, \"never cover the face\", ","type":"text","marks":[{"type":"strong"}]},{"text":"_V\u003cN>","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" versioning, archetype layout decisions, MrBeast pacing, no-fabricated-content rule) → this document wins.","type":"text","marks":[{"type":"strong"}]},{"text":" Companion skills are deliberately style-agnostic; the YUV.AI house style lives here.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Strategy confirmation:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"video-use","type":"text","marks":[{"type":"code_inline"}]},{"text":" Hard Rule 11 says \"confirm the plan in plain English before executing.\" For viral shorts in YUV.AI style this is ","type":"text"},{"text":"deliberately suspended","type":"text","marks":[{"type":"strong"}]},{"text":" — the style is fully captured in this document's Hard Rules, so the agent should execute the first pass and iterate from feedback rather than blocking on creative-direction questions. (For non-viral video-use sessions, follow the companion skill's rule.)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cut-edge padding:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"video-use","type":"text","marks":[{"type":"code_inline"}]},{"text":" allows 30–200 ms; this document picks 50 ms head / 80 ms tail as the YUV.AI default within that range. Both are correct; the narrower value is a style choice.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Shared configuration","type":"text"}]},{"type":"paragraph","content":[{"text":"Both skills read ","type":"text"},{"text":"ELEVENLABS_API_KEY","type":"text","marks":[{"type":"code_inline"}]},{"text":" from ","type":"text"},{"text":"~/Developer/video-use/.env","type":"text","marks":[{"type":"code_inline"}]},{"text":". Set it once and both skills work. Do not duplicate the key in this skill's directory.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Save location","type":"text"}]},{"type":"paragraph","content":[{"text":"Default:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"~/Documents/yuv-projects/videos/\u003cslug>/","type":"text","marks":[{"type":"code_inline"}]},{"text":" — always save viral video projects here so renders are findable. The ","type":"text"},{"text":"\u003cslug>","type":"text","marks":[{"type":"code_inline"}]},{"text":" is short, derived from the topic or source filename.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"mkdir -p ~/Documents/yuv-projects/videos\ncd ~/Documents/yuv-projects/videos\n# Initialize the project here.\nhyperframes init \u003cslug> --video \u003csource.mp4> --non-interactive\ncd \u003cslug>","type":"text"}]},{"type":"paragraph","content":[{"text":"Final renders land at ","type":"text"},{"text":"~/Documents/yuv-projects/videos/\u003cslug>/renders/final_*_V\u003cN>.mp4","type":"text","marks":[{"type":"code_inline"}]},{"text":" (both 9:16 and 16:9). Tell the user where the videos live at the end of every render.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Style preferences (mandatory defaults — inherited from ","type":"text"},{"text":"yuv-design-system","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"paragraph","content":[{"text":"This skill is the ","type":"text"},{"text":"video instantiation","type":"text","marks":[{"type":"strong"}]},{"text":" of Yuval Avidani's brand system. Whenever a brand or palette is not explicitly specified by the source content, these defaults apply. They override any companion-skill defaults that conflict.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Typography","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Role","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"English","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Hebrew","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rule","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Display / cards / karaoke captions","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Anton","type":"text","marks":[{"type":"strong"}]},{"text":" (uppercase, weight 400 + tight tracking ","type":"text"},{"text":"-0.02em","type":"text","marks":[{"type":"code_inline"}]},{"text":" to ","type":"text"},{"text":"-0.04em","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rubik Black","type":"text","marks":[{"type":"strong"}]},{"text":" (weight 900)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Always uppercase for English, never title case. Always weight-900 for Hebrew display text.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Body / glass-card body copy / chip text","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Inter","type":"text","marks":[{"type":"strong"}]},{"text":" (400 / 500 / 600 / 700)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Assistant","type":"text","marks":[{"type":"strong"}]},{"text":" (400 / 500 / 600 / 700)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use only when the card has secondary body copy beneath the display title. Line-height 1.4 inside cards.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Numbers / counters / stats","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Anton","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rubik Black","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Treat numbers as display text, never body.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Code / mono (terminal cards, paths)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"JetBrains Mono","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"—","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"For typewriter-style code reveals.","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Hebrew direction:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"dir=\"rtl\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" on every Hebrew caption container. Use ","type":"text"},{"text":"python-bidi","type":"text","marks":[{"type":"code_inline"}]},{"text":"'s ","type":"text"},{"text":"get_display()","type":"text","marks":[{"type":"code_inline"}]},{"text":" only in PIL fallback paths; CSS handles RTL natively. Logical CSS properties (","type":"text"},{"text":"margin-inline-*","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"padding-inline-*","type":"text","marks":[{"type":"code_inline"}]},{"text":") preferred over physical (","type":"text"},{"text":"margin-left","type":"text","marks":[{"type":"code_inline"}]},{"text":").","type":"text"}]},{"type":"paragraph","content":[{"text":"Banned:","type":"text","marks":[{"type":"strong"}]},{"text":" serif fonts as defaults, system-ui stack, Anton on Hebrew text (renders as hollow X — Anton is Latin-only).","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Color palette","type":"text"}]},{"type":"paragraph","content":[{"text":"The canonical YUV.AI palette and its video-tuned counterparts:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Role","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Web canonical","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Video-rendered (use inside MP4)","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Why the deviation","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Off-white / paper","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"#FAFAF7","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"#F5F0E1","type":"text","marks":[{"type":"code_inline"}]},{"text":" (warmer)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reads warmer over dark stages with text-stroke; reduces the \"blue-white glare\" effect on H264.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yellow / accent","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"#E5FF00","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"#FFE61E","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Slightly more saturated; punches through black text-stroke at small sizes.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Pink / brand thread","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"#FF1464","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"#FF1464","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Same. Use as glass-card border accents, key-moment strip stroke, brand thread.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Black / stage","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"#0A0A0A","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"#0c0e16","type":"text","marks":[{"type":"code_inline"}]},{"text":" (warm near-black)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Avoids pure black banding under H264.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Charcoal / text on light","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"#1A1A1A","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"—","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"UI overlays only (preview pages, never inside the rendered MP4).","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bone / cream","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"#F5EEE4","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"—","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Web pages, never inside the MP4.","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Banned in any rendered output:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Pure ","type":"text"},{"text":"#FFFFFF","type":"text","marks":[{"type":"code_inline"}]},{"text":" — always replace with the warmer off-white.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Blue accents (navy, slate, indigo, cool gray) unless the source brand requires them.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Default Tailwind palette names (","type":"text"},{"text":"slate-*","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"zinc-*","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"gray-*","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"emerald-*","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"cyan-*","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"indigo-*","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"violet-*","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"rose-*","type":"text","marks":[{"type":"code_inline"}]},{"text":").","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Multicolor icon sets — Phosphor or Lucide single-stroke only.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Layout & motion defaults","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Border radius:","type":"text","marks":[{"type":"strong"}]},{"text":" glass cards use ","type":"text"},{"text":"40–56px","type":"text","marks":[{"type":"code_inline"}]},{"text":" (signature soft-rounded). Pill CTAs ","type":"text"},{"text":"999px","type":"text","marks":[{"type":"code_inline"}]},{"text":". Never the 8/12px corporate-rounded middle ground.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Shadows:","type":"text","marks":[{"type":"strong"}]},{"text":" warm-toned (pink/orange undertone) — ","type":"text"},{"text":"0 20px 60px rgba(255, 20, 100, 0.12)","type":"text","marks":[{"type":"code_inline"}]},{"text":" on glass cards, never the default blue-black ","type":"text"},{"text":"rgba(0,0,0,.1)","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Whitespace:","type":"text","marks":[{"type":"strong"}]},{"text":" generous. Cards never fill more than 60% of the frame's free zone.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Asymmetry over grid-perfect.","type":"text","marks":[{"type":"strong"}]},{"text":" Offset cards. Overlap. One element breaking the grid.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Grain:","type":"text","marks":[{"type":"strong"}]},{"text":" 1–2% noise on any preview / catalog page (not inside the rendered MP4 — would compress to mush).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Animation library:","type":"text","marks":[{"type":"strong"}]},{"text":" GSAP (always). ","type":"text"},{"text":"back.out(1.7)","type":"text","marks":[{"type":"code_inline"}]},{"text":" for card entrances, ","type":"text"},{"text":"power3.out","type":"text","marks":[{"type":"code_inline"}]},{"text":" for SplitText reveals, ","type":"text"},{"text":"expo.out","type":"text","marks":[{"type":"code_inline"}]},{"text":" for slam beats, ","type":"text"},{"text":"sine.inOut","type":"text","marks":[{"type":"code_inline"}]},{"text":" for idle floats.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Inheritance rule","type":"text"}]},{"type":"paragraph","content":[{"text":"If you are building any auxiliary surface (a preview page, a catalog, a dashboard, a render-status UI), apply the full ","type":"text"},{"text":"yuv-design-system","type":"text","marks":[{"type":"code_inline"}]},{"text":" skill defaults — Anton + Inter typography, Fly High purple palette by default, signature components, brand assets. The ","type":"text"},{"text":"yuv-design-system","type":"text","marks":[{"type":"code_inline"}]},{"text":" is the canonical source of truth for all Yuval-brand visuals.","type":"text"}]},{"type":"paragraph","content":[{"text":"If you are rendering the MP4 itself, apply the video-tuned values in the table above. Same brand, two delivery surfaces.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"The live effects catalog (use this as the menu)","type":"text"}]},{"type":"paragraph","content":[{"text":"Yuval maintains a public, live, scrollable visual catalog of every effect, transition, marker, card, theme, and SFX this skill can apply to a video:","type":"text"}]},{"type":"paragraph","content":[{"text":"👉 https://effects.yuv.ai","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"When commissioning an edit, Yuval (or anyone he sends the catalog to) clicks any effect's chip — the chip copies a stable identifier like ","type":"text"},{"text":"captions.karaoke.scale-pop","type":"text","marks":[{"type":"code_inline"}]},{"text":" to the clipboard. He pastes those IDs into the prompt:","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"\"edit this with ","type":"text","marks":[{"type":"em"}]},{"text":"style.swiss-pulse","type":"text","marks":[{"type":"code_inline"},{"type":"em"}]},{"text":", captions ","type":"text","marks":[{"type":"em"}]},{"text":"karaoke.scale-pop","type":"text","marks":[{"type":"code_inline"},{"type":"em"}]},{"text":", ","type":"text","marks":[{"type":"em"}]},{"text":"marker.circle","type":"text","marks":[{"type":"code_inline"},{"type":"em"}]},{"text":" on stats, transition ","type":"text","marks":[{"type":"em"}]},{"text":"blur-crossfade","type":"text","marks":[{"type":"code_inline"},{"type":"em"}]},{"text":", sfx ","type":"text","marks":[{"type":"em"}]},{"text":"whoosh","type":"text","marks":[{"type":"code_inline"},{"type":"em"}]},{"text":" on every cut, sfx ","type":"text","marks":[{"type":"em"}]},{"text":"impact","type":"text","marks":[{"type":"code_inline"},{"type":"em"}]},{"text":" on hero word.\"","type":"text","marks":[{"type":"em"}]}]}]},{"type":"paragraph","content":[{"text":"You must respect every effect ID","type":"text","marks":[{"type":"strong"}]},{"text":" the user pastes. The catalog page is the single source of truth — every ID maps to a documented effect with verified behaviour. If the user names an ID you don't recognize, fetch the catalog (https://effects.yuv.ai) and find its definition rather than improvising.","type":"text"}]},{"type":"paragraph","content":[{"text":"The catalog also contains a ","type":"text"},{"text":"prompt library","type":"text","marks":[{"type":"strong"}]},{"text":" (effects.yuv.ai #prompts) with 8 production-ready full-edit prompts (product launch / explainer / live-code / flow walkthrough / hot-take / tutorial / founder pitch / Hebrew talking-head). When the user references \"the prompt for X scenario,\" route there.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Bilingual rendering — Hebrew + English in the same video","type":"text"}]},{"type":"paragraph","content":[{"text":"Many edits will mix Hebrew narration with English brand tokens (Claude, GitHub, hyperframes, etc.). The skill must:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Per-glyph font routing","type":"text","marks":[{"type":"strong"}]},{"text":" — Anton handles Latin, Rubik Black handles Hebrew. The single ","type":"text"},{"text":"font-family: 'Anton', 'Rubik', sans-serif","type":"text","marks":[{"type":"code_inline"}]},{"text":" declaration on every text container does this automatically. Never apply Anton to a Hebrew character (it renders as a hollow X — Anton is Latin-only).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"RTL containers","type":"text","marks":[{"type":"strong"}]},{"text":" — every Hebrew caption line gets ","type":"text"},{"text":"dir=\"rtl\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" on its container. English brand tokens stay LTR within the same line via the browser's bidirectional algorithm — no manual reordering needed.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Brand-name spelling in Hebrew","type":"text","marks":[{"type":"strong"}]},{"text":" — Yuval's preferred Hebrew transliterations:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Claude\" → ","type":"text"},{"text":"\"קלוד\"","type":"text","marks":[{"type":"strong"}]},{"text":" (not \"קלאוד\")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Hyperframes\" → keep English (\"Hyperframes\")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"GitHub\" → keep English (\"GitHub\")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"When Scribe transcribes a brand name with the wrong Hebrew spelling, fix it in the post-transcription pass before generating the karaoke layer.","type":"text"}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Companion catalog has bilingual EN/HE everywhere","type":"text","marks":[{"type":"strong"}]},{"text":" — the live catalog flips entire UI to Hebrew on toggle (see effects.yuv.ai). The same ","type":"text"},{"text":"data-lang","type":"text","marks":[{"type":"code_inline"}]},{"text":" toggle pattern applies to any auxiliary surface this skill produces (preview pages, render-status UIs, etc.).","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Lessons baked from production iterations","type":"text"}]},{"type":"paragraph","content":[{"text":"The following were learned across real sessions and now live in ","type":"text"},{"text":"~/.claude/skills/yuv-design/lessons-learned.md","type":"text","marks":[{"type":"code_inline"}]},{"text":". Read that file before building any auxiliary frontend (preview page, render dashboard, catalog). The video pipeline itself is governed by the Hard Rules below — but any HTML/CSS surface this skill produces must respect:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Bilingual = toggle, not side-by-side","type":"text","marks":[{"type":"strong"}]},{"text":" (lesson #1 in ","type":"text"},{"text":"lessons-learned.md","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Mobile = hamburger nav at ≤880px","type":"text","marks":[{"type":"strong"}]},{"text":" (lesson #2)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"One display headline per section","type":"text","marks":[{"type":"strong"}]},{"text":" (lesson #3)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"document.title","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" is part of language toggle","type":"text","marks":[{"type":"strong"}]},{"text":" (lesson #5)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"IntersectionObserver for any catalog with >8 demos","type":"text","marks":[{"type":"strong"}]},{"text":" (lesson #9)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Build comprehensive on first pass — don't iterate on scope","type":"text","marks":[{"type":"strong"}]},{"text":" (lesson #10)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Claude-in-Chrome","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" for SPAs, ","type":"text","marks":[{"type":"strong"}]},{"text":"WebFetch","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" only for static HTML","type":"text","marks":[{"type":"strong"}]},{"text":" (lessons #7, #15)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify content from real source pages, never invent","type":"text","marks":[{"type":"strong"}]},{"text":" (lesson #8)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to consult this skill","type":"text"}]},{"type":"paragraph","content":[{"text":"Any time the user drops a video file and asks for an edit. Even a one-line ask like ","type":"text"},{"text":"\"take this and edit it: \u003cpath>\"","type":"text","marks":[{"type":"em"}]},{"text":" should trigger the full flow below. Don't ask for creative direction up front — the user's style is captured in the ","type":"text"},{"text":"Hard Rules","type":"text","marks":[{"type":"strong"}]},{"text":" below; just execute and iterate from feedback.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Three things to internalize before touching anything","type":"text"}]},{"type":"paragraph","content":[{"text":"1. NEVER invent content.","type":"text","marks":[{"type":"strong"}]},{"text":" Every word on every card must trace to something the speaker actually said in the transcript. No fake currency placeholders (\"$$\"), no fake percentages (\"100% understood\"), no invented CTAs (\"link in bio\") if no link was promised. The user will catch fabricated content instantly and trust collapses fast. When in doubt, copy the literal Hebrew quote into the card. Same rule applies to Hebrew transliteration of brand names — for example, when a brand is \"Claude\", the proper Hebrew transliteration is \"קלוד\" (not \"קלאוד\"); use the brand owner's preferred spelling, not whatever Scribe heard.","type":"text"}]},{"type":"paragraph","content":[{"text":"2. NEVER cover the speaker's face.","type":"text","marks":[{"type":"strong"}]},{"text":" Position cards in the ","type":"text"},{"text":"opposite","type":"text","marks":[{"type":"em"}]},{"text":" half of the frame from the face, or use a top/bottom banner that sits above/below the face zone. For a full-frame selfie, the safe zones are y=0–400 (top banner) and y>1500 (bottom). For screen-share footage where the speaker is in a corner PIP, cards live anywhere in the screen-content area.","type":"text"}]},{"type":"paragraph","content":[{"text":"3. NEVER non-uniformly scale the speaker.","type":"text","marks":[{"type":"strong"}]},{"text":" Source PIP aspect must equal target PIP aspect. If you scale a 470×460 source crop into a 920×580 box, the speaker comes out horizontally squished and the user will reject the output. Pick target dims that match source aspect, or use ","type":"text"},{"text":"force_original_aspect_ratio=decrease","type":"text","marks":[{"type":"code_inline"}]},{"text":" + center-pad.","type":"text"}]},{"type":"paragraph","content":[{"text":"Everything else in this document is a worked example or a tooling detail. The three above are non-negotiable.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"The pipeline (high-level)","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"source.mp4\n ↓ video-use: transcribe (ElevenLabs Scribe — word-level + diarized + audio events)\ntranscripts/\u003csource>.json\n ↓ pick word-snapped beats → edl.json (ranges with start/end, layout per range, motion per beat)\n ↓ video-use: build base.mp4 per aspect (per-segment extract + grade + 30ms fades + concat)\nbase_\u003caspect>_V\u003cN>.mp4 (one per aspect — 9:16 and 16:9)\n ↓ generate output-timeline transcript.json (word-level, output-timeline timestamps, brand-name spelling fixed)\ntranscript.json\n ↓ hyperframes init \u003cproject> (creates index.html scaffold + DESIGN.md slot)\n ↓ hyperframes: build composition.html\n : \u003cvideo> bg + glass cards (CSS backdrop-filter) + karaoke caption layer + GSAP timeline\n ↓ hyperframes lint (validates the composition)\n ↓ hyperframes render (Chromium captures every frame, mux to MP4)\nfinal_\u003caspect>_V\u003cN>.mp4","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Hard Rules (the editor's bill of rights)","type":"text"}]},{"type":"paragraph","content":[{"text":"These are correctness rules. Deviation produces silent failures or angry users.","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Hebrew = Rubik Black. English = Anton uppercase.","type":"text","marks":[{"type":"strong"}]},{"text":" Never mix. Never substitute. The two fonts are bundled in ","type":"text"},{"text":"assets/fonts/","type":"text","marks":[{"type":"code_inline"}]},{"text":" because download URLs change. In hyperframes CSS, declare ","type":"text"},{"text":"font-family: Rubik","type":"text","marks":[{"type":"code_inline"}]},{"text":" (weight 900) for Hebrew text and ","type":"text"},{"text":"font-family: Anton","type":"text","marks":[{"type":"code_inline"}]},{"text":" for English; the compiler embeds them automatically.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Real CSS backdrop-filter for glass.","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"backdrop-filter: blur(40px) saturate(160%)","type":"text","marks":[{"type":"code_inline"}]},{"text":" on the card body. Do NOT pre-bake blur into a PNG. Do NOT use semi-transparent fills as a stand-in for blur — they look flat.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"3D-tilt entrance for cards.","type":"text","marks":[{"type":"strong"}]},{"text":" GSAP entrance: ","type":"text"},{"text":"scale 0.85 → 1.0","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"rotationY -12deg → 0","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"y +60 → 0","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"ease: \"back.out(1.7)\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"transformPerspective: 900","type":"text","marks":[{"type":"code_inline"}]},{"text":". No flat fade-ins.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Word-by-word karaoke synced to the transcript.","type":"text","marks":[{"type":"strong"}]},{"text":" Active word: ","type":"text"},{"text":"scale 1.0","type":"text","marks":[{"type":"code_inline"}]},{"text":" + accent color. Past/future words: ","type":"text"},{"text":"scale 1.0","type":"text","marks":[{"type":"code_inline"}]},{"text":" at 55% opacity. Per-word ","type":"text"},{"text":"gsap.fromTo(scale 1.5 → 1.0, ease \"back.out(2)\", duration 0.16)","type":"text","marks":[{"type":"code_inline"}]},{"text":" on activation.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Subtitles applied LAST.","type":"text","marks":[{"type":"strong"}]},{"text":" The karaoke layer has the highest z-index. No card should overlap it.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Per-segment extract → ","type":"text","marks":[{"type":"strong"}]},{"text":"-c copy","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" concat.","type":"text","marks":[{"type":"strong"}]},{"text":" The video-use skill enforces this; mirror it. Single-pass filtergraphs cause double-encode of every segment.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"30 ms audio fades at every segment boundary.","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"afade=t=in:st=0:d=0.03,afade=t=out:st={dur-0.03}:d=0.03","type":"text","marks":[{"type":"code_inline"}]},{"text":". Without this, audible pops at every cut.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Word-boundary snapping with 50 ms head / 80 ms tail padding.","type":"text","marks":[{"type":"strong"}]},{"text":" Cut edges come from ","type":"text"},{"text":"word.start","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"word.end","type":"text","marks":[{"type":"code_inline"}]},{"text":" in the Scribe transcript.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cache transcripts.","type":"text","marks":[{"type":"strong"}]},{"text":" Never re-transcribe the same source. Scribe costs money.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"All Hebrew text in any rendering pass must be RTL-correct.","type":"text","marks":[{"type":"strong"}]},{"text":" In CSS, set ","type":"text"},{"text":"dir=\"rtl\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" on the container; libass handles RTL natively. In any PIL fallback path, use ","type":"text"},{"text":"python-bidi","type":"text","marks":[{"type":"code_inline"}]},{"text":"'s ","type":"text"},{"text":"get_display()","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Even pixel dimensions.","type":"text","marks":[{"type":"strong"}]},{"text":" ffmpeg's ","type":"text"},{"text":"yuv420p","type":"text","marks":[{"type":"code_inline"}]},{"text":" chroma subsampling requires even W and H. Odd dims silently round, which then breaks ","type":"text"},{"text":"alphamerge","type":"text","marks":[{"type":"code_inline"}]},{"text":" (\"Input frame sizes do not match\").","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Aspect preservation on the speaker PIP.","type":"text","marks":[{"type":"strong"}]},{"text":" Match source crop aspect to target PIP aspect.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"NEVER make up content.","type":"text","marks":[{"type":"strong"}]},{"text":" Audit every string against the transcript before render.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Save every render with ","type":"text","marks":[{"type":"strong"}]},{"text":"_V\u003cN>.mp4","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" suffix.","type":"text","marks":[{"type":"strong"}]},{"text":" Each iteration writes a NEW versioned file. Never overwrite a previous final — the user keeps backups by version.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"All session outputs in ","type":"text","marks":[{"type":"strong"}]},{"text":"\u003cvideos_dir>/edit/","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":".","type":"text","marks":[{"type":"strong"}]},{"text":" Never write inside the skill directory.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Layout decisions (the most important call you make)","type":"text"}]},{"type":"paragraph","content":[{"text":"The first decision after transcribing is ","type":"text"},{"text":"what the source footage actually is","type":"text","marks":[{"type":"strong"}]},{"text":". There are two archetypes:","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Archetype 1 — \"Screen-share with speaker PIP corner\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Source: 16:9 with a screen recording (browser, app, dashboard) filling most of the frame, and the speaker's webcam in a small corner PIP. ","type":"text"},{"text":"The screen content IS the visual story.","type":"text","marks":[{"type":"strong"}]},{"text":" Hide it and the user gets angry.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Output","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Top zone (screen content)","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bottom / corner zone (speaker PIP)","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Card real estate","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"9:16","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Top 2/3 — crop center column of source, scale to 1080×1280","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bottom 1/3 — crop the source PIP region (e.g. 470×460), scale to a target with ","type":"text"},{"text":"matching aspect","type":"text","marks":[{"type":"strong"}]},{"text":" (e.g. 600×588), apply rounded mask 50px+","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Hyperframes glass cards float in top 2/3 over the screen content; key-moment strip floats just above PIP","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"16:9","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Full frame — scale source 2560×1440 to 1920×1080","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"The PIP is naturally in source bottom-right; overlay a rounded-corner mask on that exact region","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cards on left half, key-strip across bottom","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Archetype 2 — \"Full-frame selfie\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Source: vertical or horizontal with the speaker filling the frame. There's no \"screen\" beyond the speaker themselves. ","type":"text"},{"text":"The speaker IS the content","type":"text","marks":[{"type":"strong"}]},{"text":" — keep them prominent.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Output","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Speaker placement (per-beat)","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Card real estate","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"9:16","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Layout A (emotional beats — HOOK / PROBLEM / WOW / CTA)","type":"text","marks":[{"type":"strong"}]},{"text":": full-frame center-vertical crop. ","type":"text"},{"text":"Layout B (explanatory beats)","type":"text","marks":[{"type":"strong"}]},{"text":": speaker shrunk to a top-right rounded PIP (e.g. 480×640), dark gradient BG fills rest. Source crop for the PIP must include the speaker's full head — start ","type":"text"},{"text":"y","type":"text","marks":[{"type":"code_inline"}]},{"text":" at ~80px in the source, NOT 200px+ (that cuts the forehead).","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Layout B: glass cards fill the bottom 2/3","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"16:9","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Letterbox: scale source vertically to fit height, blurred (","type":"text"},{"text":"gblur sigma=22","type":"text","marks":[{"type":"code_inline"}]},{"text":") zoomed copy fills the side bars, crisp speaker centered on top","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cards on left half over the blurred BG","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"If the source is HYBRID (some beats are full speaker, others screen-share), pick the archetype per beat. Set ","type":"text"},{"text":"\"layout\": \"A\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"\"layout\": \"B\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" per range in ","type":"text"},{"text":"edl.json","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Apple-style liquid-glass cards (the hyperframes layer)","type":"text"}]},{"type":"paragraph","content":[{"text":"The card style is non-negotiable.","type":"text","marks":[{"type":"strong"}]},{"text":" Build it in HTML/CSS, not PIL.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"css"},"content":[{"text":".card {\n position: absolute;\n border-radius: 56px;\n background: rgba(255, 255, 255, 0.08);\n backdrop-filter: blur(40px) saturate(160%);\n -webkit-backdrop-filter: blur(40px) saturate(160%);\n border: 1.5px solid rgba(255, 255, 255, 0.18);\n box-shadow:\n 0 20px 60px rgba(0, 0, 0, 0.5),\n inset 0 2px 0 rgba(255, 255, 255, 0.18);\n padding: 60px 50px;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 24px;\n transform-origin: center;\n will-change: transform, opacity;\n}\n.card.dark {\n background: rgba(0, 0, 0, 0.55);\n}","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"js"},"content":[{"text":"// Entrance — 3D tilt-pop with overshoot\ngsap.set(\".card\", { opacity: 0, scale: 0.85, y: 60, rotationY: -12, transformPerspective: 900 });\ntl.to(sel, { opacity: 1, scale: 1.0, y: 0, rotationY: 0, duration: 0.55, ease: \"back.out(1.7)\" }, beat.s + 0.05);\n// Subtle idle float — keeps the card alive\ntl.to(sel, { y: -8, duration: 0.9, ease: \"sine.inOut\", yoyo: true, repeat: 1 }, beat.s + 0.6);\n// Exit\ntl.to(sel, { opacity: 0, scale: 0.95, y: -30, duration: 0.30, ease: \"power2.in\" }, beat.e - 0.30);\ntl.set(sel, { visibility: \"hidden\" }, beat.e);","type":"text"}]},{"type":"paragraph","content":[{"text":"Inside the card","type":"text","marks":[{"type":"strong"}]},{"text":", stagger the children so the card \"fills\" itself with content rather than appearing all at once:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"js"},"content":[{"text":"tl.from(`${sel} .chip`, { y: 30, opacity: 0, scale: 0.9,\n duration: 0.4, ease: \"back.out(1.6)\", stagger: 0.10 }, beat.s + 0.40);","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Karaoke (video-title style)","type":"text"}]},{"type":"paragraph","content":[{"text":"Group transcript words into chunks of 3 (or break on >0.5s pauses). Each chunk becomes one ","type":"text"},{"text":".cap-group","type":"text","marks":[{"type":"code_inline"}]},{"text":" div. Within the chunk, each word is a ","type":"text"},{"text":"\u003cspan class=\"cap-word\">","type":"text","marks":[{"type":"code_inline"}]},{"text":" (or ","type":"text"},{"text":".cap-word.en","type":"text","marks":[{"type":"code_inline"}]},{"text":" for English brand tokens, ","type":"text"},{"text":".cap-word.accent","type":"text","marks":[{"type":"code_inline"}]},{"text":" for emphasis Hebrew).","type":"text"}]},{"type":"paragraph","content":[{"text":"CSS:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"css"},"content":[{"text":".cap-word {\n font: 900 108px Rubik;\n color: rgba(245, 240, 225, 0.55); /* dim future/past */\n text-shadow: 0 8px 18px rgba(0,0,0,.85), 0 0 28px rgba(0,0,0,.7);\n -webkit-text-stroke: 4px #0c0e16;\n transform-origin: center bottom;\n}\n.cap-word.en { font: 400 124px Anton; letter-spacing: 0.06em; color: rgba(255, 230, 30, 0.6); }\n.cap-word.active { color: #F5F0E1; }\n.cap-word.en.active { color: #FFE61E; }\n.cap-word.accent.active { color: #FFE61E; text-shadow: 0 0 20px rgba(255,230,30,.6); }","type":"text"}]},{"type":"paragraph","content":[{"text":"GSAP per-word:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"js"},"content":[{"text":"tl.fromTo(wordSel,\n { scale: 1.5, opacity: 0 },\n { scale: 1.0, opacity: 1, duration: 0.16, ease: \"back.out(2)\" },\n word.start);\ntl.call(() => document.querySelector(wordSel).classList.add(\"active\"), [], word.start + 0.02);","type":"text"}]},{"type":"paragraph","content":[{"text":"Group entrance/exit per ","type":"text"},{"text":"cap-group","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"js"},"content":[{"text":"tl.fromTo(groupSel,\n { opacity: 0, visibility: \"visible\", scale: 0.85, y: 30 },\n { opacity: 1, scale: 1, y: 0, duration: 0.25, ease: \"back.out(1.6)\" },\n group.start);\ntl.to(groupSel, { opacity: 0, scale: 0.95, y: -20, duration: 0.2, ease: \"power2.in\" }, group.end - 0.20);\ntl.set(groupSel, { visibility: \"hidden\" }, group.end);","type":"text"}]},{"type":"paragraph","content":[{"text":"English brand tokens stay English.","type":"text","marks":[{"type":"strong"}]},{"text":" The detection regex ","type":"text"},{"text":"^[A-Za-z][A-Za-z0-9\\-']*$","type":"text","marks":[{"type":"code_inline"}]},{"text":" routes English/brand words to the EN style (Anton, uppercase). Hebrew flows through libass+FriBidi for RTL or via ","type":"text"},{"text":"dir=\"rtl\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" in CSS.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Per-segment dynamic motion","type":"text"}]},{"type":"paragraph","content":[{"text":"Every segment baked-in motion. Subtle MrBeast-style amounts.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Kind","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Effect","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Typical amount","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"push_in","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Slow zoom in","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"0.04–0.07","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"pull_out","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Slow zoom out (revealing)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"0.05–0.07","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"snap_in","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cubic ease-out punch zoom","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"0.05–0.10","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"dolly_l","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"dolly_r","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Held zoom + horizontal drift","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"0.04","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"hold","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No motion (use sparingly)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"–","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Keep amounts subtle. Anything ≥0.10 outside of WOW-class beats reads as \"too much zoom\".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Bottom key-moment strips","type":"text"}]},{"type":"paragraph","content":[{"text":"A small glass strip across the bottom summarising the current beat in 1–4 words. Hebrew on the right (RTL), English on the left (Anton uppercase), yellow accent stripe. Appears only on key beats — not every beat.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"css"},"content":[{"text":".km-strip {\n position: absolute;\n left: 40px; right: 40px;\n bottom: 30px;\n height: 110px;\n border-radius: 30px;\n background: rgba(0, 0, 0, 0.55);\n backdrop-filter: blur(30px);\n border: 1.5px solid rgba(255, 230, 30, 0.55);\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 40px;\n z-index: 70;\n}","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"SFX library","type":"text"}]},{"type":"paragraph","content":[{"text":"Generated via ElevenLabs sound-generation API. Standard kit:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"impact.mp3","type":"text","marks":[{"type":"code_inline"}]},{"text":" — HOOK punch + WOW slam","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"bass_drop.mp3","type":"text","marks":[{"type":"code_inline"}]},{"text":" — layered with impact for the boom","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"whoosh.mp3","type":"text","marks":[{"type":"code_inline"}]},{"text":" — every cut transition","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"riser.mp3","type":"text","marks":[{"type":"code_inline"}]},{"text":" — building into a punchline","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"ding.mp3","type":"text","marks":[{"type":"code_inline"}]},{"text":" — UI pop on card reveals + per-bar dings on chart entrance","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glitch.mp3","type":"text","marks":[{"type":"code_inline"}]},{"text":" — short transition glitch","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"typing.mp3","type":"text","marks":[{"type":"code_inline"}]},{"text":" — under any terminal/coding card","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Mix in the video-use base layer (not in hyperframes) so the audio is committed before the visual composition reads it.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Versioning","type":"text"}]},{"type":"paragraph","content":[{"text":"Every render writes a NEW file.","type":"text","marks":[{"type":"strong"}]},{"text":" Find the highest existing ","type":"text"},{"text":"final_\u003caspect>_V\u003cN>.mp4","type":"text","marks":[{"type":"code_inline"}]},{"text":" and increment. The composite scripts split ","type":"text"},{"text":"BASE_VERSION","type":"text","marks":[{"type":"code_inline"}]},{"text":" (read from) and ","type":"text"},{"text":"OUT_VERSION","type":"text","marks":[{"type":"code_inline"}]},{"text":" (write to) so the base can be reused across multiple final iterations.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Common failure modes (and the fixes)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Input frame sizes do not match (X vs Y)\"","type":"text","marks":[{"type":"strong"}]},{"text":" → odd target dimension. Round to even pixels for both W and H.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Hebrew letters render reversed","type":"text","marks":[{"type":"strong"}]},{"text":" → in CSS, set ","type":"text"},{"text":"dir=\"rtl\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" on the container. In PIL fallbacks, wrap with ","type":"text"},{"text":"bidi.get_display()","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Hebrew avatar letter renders as hollow X","type":"text","marks":[{"type":"strong"}]},{"text":" → using Anton font for a Hebrew character. Anton is Latin-only. Switch to Rubik for any text containing Hebrew.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Filter 'split' has output 0 unconnected","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" → declared a split but didn't consume one of its outputs. Check labels match.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Speaker looks horizontally squished","type":"text","marks":[{"type":"strong"}]},{"text":" → non-uniform scale on the PIP source crop. Match target aspect to source aspect.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Speaker forehead/hair cut off in PIP","type":"text","marks":[{"type":"strong"}]},{"text":" → source crop ","type":"text"},{"text":"y","type":"text","marks":[{"type":"code_inline"}]},{"text":" started too low. For a 2560×1440 source where the speaker fills the frame, start ","type":"text"},{"text":"y ≈ 80","type":"text","marks":[{"type":"code_inline"}]},{"text":", not 200+.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"subtitles=","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" filter fails on Windows","type":"text","marks":[{"type":"strong"}]},{"text":" → unescaped colon in the path. Escape with ","type":"text"},{"text":"\\:","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"-shortest","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" ignored","type":"text","marks":[{"type":"strong"}]},{"text":" → ","type":"text"},{"text":"-loop 1","type":"text","marks":[{"type":"code_inline"}]},{"text":" on a PNG creates an infinite stream. Add ","type":"text"},{"text":"-t \u003cdur>","type":"text","marks":[{"type":"code_inline"}]},{"text":" to constrain the looped input.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"-t","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" doesn't limit source duration","type":"text","marks":[{"type":"strong"}]},{"text":" → ","type":"text"},{"text":"-t","type":"text","marks":[{"type":"code_inline"}]},{"text":" is an ","type":"text"},{"text":"input option","type":"text","marks":[{"type":"em"}]},{"text":" and must come BEFORE the ","type":"text"},{"text":"-i","type":"text","marks":[{"type":"code_inline"}]},{"text":" it applies to.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Hyperframes \"sparse keyframes\" warning","type":"text","marks":[{"type":"strong"}]},{"text":" → re-encode the base with ","type":"text"},{"text":"-g 30 -keyint_min 30","type":"text","marks":[{"type":"code_inline"}]},{"text":" for smooth seek. ","type":"text"},{"text":"ffmpeg -i in.mp4 -c:v libx264 -r 30 -g 30 -keyint_min 30 -movflags +faststart -c:a copy out.mp4","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"File layout (per project)","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"\u003cvideos_dir>/edit/\n├── transcripts/\u003csource>.json (cached Scribe output)\n├── edl.json (cut decisions, layout per range, motion per beat)\n├── transcript.json (output-timeline word-level, generated for hyperframes)\n├── base_\u003caspect>_V\u003cN>.mp4 (video-use cuts + base layout, audio mixed)\n├── hf/ (hyperframes project)\n│ ├── DESIGN.md (visual identity — colors, fonts, motion rules)\n│ ├── index.html (the composition)\n│ ├── base_9x16.mp4 / base_16x9.mp4 (copied from parent edit/)\n│ ├── transcript.json (copied from parent edit/)\n│ └── renders/ (hyperframes output)\n└── final_\u003caspect>_V\u003cN>.mp4 (copied from hf/renders/, with version bumped)","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Setup","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/setup.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for: ffmpeg, ElevenLabs API key, hyperframes CLI (","type":"text"},{"text":"npx hyperframes","type":"text","marks":[{"type":"code_inline"}]},{"text":"), python-bidi, fonts. The ","type":"text"},{"text":"video-use","type":"text","marks":[{"type":"code_inline"}]},{"text":" skill is a hard prerequisite — install that first.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Scripts (this skill)","type":"text"}]},{"type":"paragraph","content":[{"text":"These scripts handle the video-use side (cuts + base extraction). The hyperframes side is authored as HTML/CSS/JS per project — no fixed scripts there because every project has its own beats and content.","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scripts/apple_glass.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" — ","type":"text"},{"text":"apple_glass_card()","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"make_glass_mask()","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"make_dark_bg()","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"rtl()","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"COLORS","type":"text","marks":[{"type":"code_inline"}]},{"text":", layout constants. Used as a PIL fallback only — prefer hyperframes for production cards.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scripts/build_screen_share.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" — base build for Archetype 1 (screen-share + corner PIP)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scripts/build_selfie.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" — base build for Archetype 2 (full-frame speaker)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scripts/make_karaoke.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" — output-timeline ASS karaoke (used as a PIL fallback or for ffmpeg-direct paths)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scripts/make_sfx.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" — ElevenLabs SFX batch generator","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scripts/composite_screen_share.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"scripts/composite_selfie.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" — full ffmpeg filter_complex paths (legacy, prefer hyperframes)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scripts/make_layout_assets.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" — pre-render dark-mode BG + speaker masks","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"The unbreakable promise","type":"text"}]},{"type":"paragraph","content":[{"text":"If the user drops a video and asks for an edit, the output:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Shows the screen content if it's a screen-share (NEVER hide it under dark BG).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Shows the speaker prominently if it's a selfie (NEVER shrink to tiny corner).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Has every card text traceable to a real spoken word in the transcript.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Renders both 9:16 AND 16:9.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Saves with ","type":"text"},{"text":"_V\u003cN>","type":"text","marks":[{"type":"code_inline"}]},{"text":" so the previous version is preserved.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Uses Rubik for Hebrew, Anton uppercase for English. Always.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never covers the speaker's face.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Uses ","type":"text"},{"text":"hyperframes","type":"text","marks":[{"type":"strong"}]},{"text":" for the visual composition (real CSS backdrop-filter, GSAP springy easing, Hollywood-grade animation).","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Get those right and you've delivered. Anything else is polish.","type":"text"}]}]},"metadata":{"date":"2026-06-05","author":"@skillopedia","source":{"stars":216,"repo_name":"ai-agents-skills","origin_url":"https://github.com/hoodini/ai-agents-skills/blob/HEAD/skills/yuv-viral-video/SKILL.md","repo_owner":"hoodini","body_sha256":"559507caf1944a464904e2973bf7e4699bdbf3f4dad5d1a1d8195d3e4158b41b","cluster_key":"d5ea060ccb8a212c8d331929e848bc03778bc34add6cfff29f8f6cd3ac45f130","clean_bundle":{"format":"clean-skill-bundle-v1","source":"hoodini/ai-agents-skills/skills/yuv-viral-video/SKILL.md","attachments":[{"id":"526b5631-b9e9-5ecf-8118-fefc2ee390c6","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/526b5631-b9e9-5ecf-8118-fefc2ee390c6/attachment.md","path":"README.md","size":10473,"sha256":"1448120ba4413bc0d9b70f9cfc0d2622ede8c4a258e7355afe39ec071f8cca36","contentType":"text/markdown; charset=utf-8"},{"id":"e3907ac9-af6c-561e-9c6d-2cbc798cb336","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e3907ac9-af6c-561e-9c6d-2cbc798cb336/attachment.ttf","path":"assets/fonts/Anton-Regular.ttf","size":161588,"sha256":"28beb8f6542f642ba4143bd4a1d1cfc7be7b1dedc951096efd8e0942502ea1bf","contentType":"font/ttf"},{"id":"fddd0d19-d3e9-53eb-b6d3-b6d131f9caff","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fddd0d19-d3e9-53eb-b6d3-b6d131f9caff/attachment.ttf","path":"assets/fonts/Rubik-Black.ttf","size":59896,"sha256":"7dd3a3846368ccdd04bfe43ccc56e76172cc11d639cf9b19a244bae00c9acc11","contentType":"font/ttf"},{"id":"3807bc63-a7e6-5cec-bfd5-7947e841d935","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3807bc63-a7e6-5cec-bfd5-7947e841d935/attachment.ttf","path":"assets/fonts/Rubik-Bold.ttf","size":60136,"sha256":"93a4d7960ba9092cc93446d2fc178f41cd54deef81aca8b9b1e5f5c554268c6a","contentType":"font/ttf"},{"id":"204636ed-a427-5953-b26a-0568d47f6103","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/204636ed-a427-5953-b26a-0568d47f6103/attachment.md","path":"references/setup.md","size":4265,"sha256":"641fe31491bed0f944d0eb232c999687e3f6020af5a95af235ad21cc309441f1","contentType":"text/markdown; charset=utf-8"},{"id":"60f491c2-8507-5b68-94ed-1df99aa35161","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/60f491c2-8507-5b68-94ed-1df99aa35161/attachment.txt","path":"requirements.txt","size":83,"sha256":"0f73bdd55bb131cdc3e75ada6e733d21fba36c2c4f5869f94d9d068dcac46d6f","contentType":"text/plain; charset=utf-8"},{"id":"206b2ae0-cddc-5453-bff7-0ebf1b7fb249","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/206b2ae0-cddc-5453-bff7-0ebf1b7fb249/attachment.py","path":"scripts/apple_glass.py","size":5728,"sha256":"fab9939319f81fc35f547c4944cd0988f0890e374a8667c5dacd1ac9e36a2b25","contentType":"text/x-python; charset=utf-8"},{"id":"db6c46d4-cfed-5133-a264-42f35cfdf618","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/db6c46d4-cfed-5133-a264-42f35cfdf618/attachment.py","path":"scripts/build_screen_share.py","size":8364,"sha256":"a6a083bb4c6da1f2af5a140b1d204051292cd514d5e98ddc3d42e4f334d48dbf","contentType":"text/x-python; charset=utf-8"},{"id":"c3005d6c-e9a3-53eb-a6b7-ba66dc6accc0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c3005d6c-e9a3-53eb-a6b7-ba66dc6accc0/attachment.py","path":"scripts/build_selfie.py","size":5081,"sha256":"442863b0e31751bb88a13dbd9924cbdf3d9310c14809dd96e92d39c4b04cb82d","contentType":"text/x-python; charset=utf-8"},{"id":"82e95c2a-1da4-5daf-992e-cfd6ba0bd475","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/82e95c2a-1da4-5daf-992e-cfd6ba0bd475/attachment.py","path":"scripts/composite_screen_share.py","size":9537,"sha256":"55abe6493947a1c31791fee34d8553b3c69af3af7d2582a24980aecc07ed4722","contentType":"text/x-python; charset=utf-8"},{"id":"96afde6b-782d-5d4b-be96-9725c08cf0dd","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/96afde6b-782d-5d4b-be96-9725c08cf0dd/attachment.py","path":"scripts/composite_selfie.py","size":8597,"sha256":"286a9eceb2d6b2de27b0a78d58861a06b878b2347ef9ebbdb44d19ca57700c51","contentType":"text/x-python; charset=utf-8"},{"id":"39afc5b8-a303-59d4-9570-7d4e28db2294","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/39afc5b8-a303-59d4-9570-7d4e28db2294/attachment.py","path":"scripts/make_anims.py","size":14897,"sha256":"cb83b1bd2e3ef1f1fa62330691024f1fb1dfc1d110f2bca1132e80929e7db2e1","contentType":"text/x-python; charset=utf-8"},{"id":"8abbbfba-58e5-55c2-9218-29d25f916c94","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8abbbfba-58e5-55c2-9218-29d25f916c94/attachment.py","path":"scripts/make_cards_screen_share.py","size":17804,"sha256":"007e604ec831649d6a73f34cef2f89b3e85f13a4beb71ac23fe888e40f0511be","contentType":"text/x-python; charset=utf-8"},{"id":"f4bbe352-32b0-5b60-b7de-63e5ef6618bf","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f4bbe352-32b0-5b60-b7de-63e5ef6618bf/attachment.py","path":"scripts/make_cards_selfie.py","size":24177,"sha256":"328f6110c4d80d0910a3239850cedad6b10fb4aa3f746d5784c2f90285b7997e","contentType":"text/x-python; charset=utf-8"},{"id":"581acf1a-9e58-5bee-b3c4-cbf491c7554f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/581acf1a-9e58-5bee-b3c4-cbf491c7554f/attachment.py","path":"scripts/make_karaoke.py","size":5056,"sha256":"25296c3465e443d98e6307373fe258b5ecbd8a9b7452eeacefc48032cb988549","contentType":"text/x-python; charset=utf-8"},{"id":"b16713c2-ccbe-5167-a5e1-b4e520905781","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b16713c2-ccbe-5167-a5e1-b4e520905781/attachment.py","path":"scripts/make_layout_assets.py","size":1454,"sha256":"86b93e85e1d6d37bb4a4266c6205699d9f9471294c66af59459944f1d495bf3d","contentType":"text/x-python; charset=utf-8"},{"id":"f9049159-5abb-532e-97d8-0189e2fb1c27","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f9049159-5abb-532e-97d8-0189e2fb1c27/attachment.py","path":"scripts/make_sfx.py","size":1862,"sha256":"391253c49cddc08937ac5a2079059eba365559a8208a27704ca0c06ebd27bd88","contentType":"text/x-python; charset=utf-8"}],"bundle_sha256":"12681a1899df3410a9d0d651d64a7d0904ef42f0114723f4c6fb7528d6fbb426","attachment_count":17,"text_attachments":14,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":3,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"skills/yuv-viral-video/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"media-content","category_label":"Media"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"media-content","import_tag":"clean-skills-v1","_yaml_error":"YAMLException: bad indentation of a mapping entry (2:714)\n\n 1 | ... \n 2 | ... s the COMBINATION of two skills: video-use (transcription + wor ...\n-----------------------------------------^"}},"renderedAt":1782981935738}

Yuv-Viral-Video The signature YUV.AI viral-short pipeline. Two skills working together : - — transcribes the source via ElevenLabs Scribe, picks word-snapped cuts, extracts and concats segments into a . This is the cuts + base layout layer. - — takes the base as a background video and adds the visual composition layer in HTML/CSS/GSAP: liquid-glass cards with real , GSAP motion graphics with springy easing, word-by-word karaoke captions, scene transitions, and renders to MP4 via Chromium. You MUST use both. Do not invent your own PIL-based cards, do not pre-bake blur into PNGs, do not write y…