File size: 2,469 Bytes
ab4b623 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | """
Base Template Class
كل تمبلت جديد بيرث من الكلاس ده
"""
from abc import ABC, abstractmethod
from PIL import Image
from dataclasses import dataclass
from typing import Optional
@dataclass
class RenderRequest:
"""البيانات اللي بتيجي من n8n"""
title: str
discount: str = ""
badge: str = ""
phone: str = ""
website: str = ""
image_path: str = ""
music_path: str = ""
output_path: str = "/tmp/output.mp4"
# إضافات اختيارية
bg_left: str = ""
bg_right: str = ""
duration: int = 6
fps: int = 30
width: int = 1280
height: int = 720
music_volume: float = 0.20
class BaseTemplate(ABC):
"""
الكلاس الأساسي — كل تمبلت بيرث منه
عشان تعمل تمبلت جديد:
1. عمل ملف في templates/
2. ترث من BaseTemplate
3. تعمل make_frame بتاعك
"""
NAME = "base"
DESCRIPTION = "Base template"
AUTHOR = ""
def ease_out(self, t: float) -> float:
return 1 - (1 - t) ** 3
def ease_in_out(self, t: float) -> float:
return t * t * (3 - 2 * t)
def load_font(self, size: int):
from PIL import ImageFont
candidates = [
'/tmp/arabic.ttf',
'/usr/share/fonts/truetype/noto/NotoNaskhArabic-Bold.ttf',
'/usr/share/fonts/truetype/noto/NotoSansArabic-Bold.ttf',
'/usr/share/fonts/opentype/noto/NotoNaskhArabic-Bold.otf',
'C:/Windows/Fonts/arial.ttf',
]
for path in candidates:
import os
if os.path.exists(path):
try:
return ImageFont.truetype(path, size)
except:
continue
return ImageFont.load_default()
def parse_color(self, s: str, default: tuple) -> tuple:
try:
return tuple(int(x) for x in s.split(','))
except:
return default
@abstractmethod
def make_frame(self, t: float, req: RenderRequest, product_img, logo_img) -> Image.Image:
"""
ارسم frame واحد
t = الوقت الحالي بالثواني
يرجع PIL Image RGB
"""
pass
@property
def info(self) -> dict:
return {
"name": self.NAME,
"description": self.DESCRIPTION,
"author": self.AUTHOR,
}
|