Skip to content

Commit fcf4796

Browse files
committed
feat: add caption asset
1 parent ac78d55 commit fcf4796

File tree

1 file changed

+167
-1
lines changed

1 file changed

+167
-1
lines changed

videodb/timeline_v2.py

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class AssetType(str, Enum):
77
image = "image"
88
audio = "audio"
99
text = "text"
10+
caption = "caption"
1011

1112

1213
class Fit(str, Enum):
@@ -62,6 +63,40 @@ class HorizontalAlignment(str, Enum):
6263
right = "right"
6364

6465

66+
class CaptionBorderStyle(int, Enum):
67+
"""Border style properties for caption assets."""
68+
69+
no_border = 1
70+
opaque_box = 3
71+
outline = 4
72+
73+
74+
class CaptionAlignment(int, Enum):
75+
"""Caption alignment properties for caption assets."""
76+
77+
bottom_left = 1
78+
bottom_center = 2
79+
bottom_right = 3
80+
middle_left = 9
81+
middle_center = 10
82+
middle_right = 11
83+
top_left = 5
84+
top_center = 6
85+
top_right = 7
86+
87+
88+
class CaptionAnimation(str, Enum):
89+
"""Caption animation properties for caption assets."""
90+
91+
float_in_bottom = "float_in_bottom"
92+
box_highlight = "box_highlight"
93+
color_highlight = "color_highlight"
94+
reveal = "reveal"
95+
karioke = "karioke"
96+
impact = "impact"
97+
supersize = "supersize"
98+
99+
65100
class VerticalAlignment(str, Enum):
66101
"""Vertical text alignment options."""
67102

@@ -378,7 +413,138 @@ def to_json(self):
378413
return data
379414

380415

381-
AnyAsset = Union[VideoAsset, ImageAsset, AudioAsset, TextAsset]
416+
class FontStyling:
417+
"""Font styling properties for caption assets."""
418+
419+
def __init__(
420+
self,
421+
name: str = "Clear Sans",
422+
size: int = 30,
423+
bold: bool = False,
424+
italic: bool = False,
425+
underline: bool = False,
426+
strikeout: bool = False,
427+
scale_x: float = 1.0,
428+
scale_y: float = 1.0,
429+
spacing: float = 0.0,
430+
angle: float = 0.0,
431+
):
432+
self.name = name
433+
self.size = size
434+
self.bold = bold
435+
self.italic = italic
436+
self.underline = underline
437+
self.strikeout = strikeout
438+
self.scale_x = scale_x
439+
self.scale_y = scale_y
440+
self.spacing = spacing
441+
self.angle = angle
442+
443+
def to_json(self):
444+
return {
445+
"font_name": self.name,
446+
"font_size": self.size,
447+
"bold": self.bold,
448+
"italic": self.italic,
449+
"underline": self.underline,
450+
"strikeout": self.strikeout,
451+
"scale_x": self.scale_x,
452+
"scale_y": self.scale_y,
453+
"spacing": self.spacing,
454+
"angle": self.angle,
455+
}
456+
457+
458+
class BorderAndShadow:
459+
"""Border and shadow properties for caption assets."""
460+
461+
def __init__(
462+
self,
463+
style: CaptionBorderStyle = CaptionBorderStyle.no_border,
464+
outline: int = 1,
465+
outline_color: str = "&H00000000",
466+
shadow: int = 0,
467+
):
468+
self.style = style
469+
self.outline = outline
470+
self.outline_color = outline_color
471+
self.shadow = shadow
472+
473+
def to_json(self):
474+
return {
475+
"style": self.style.value,
476+
"outline": self.outline,
477+
"outline_color": self.outline_color,
478+
"shadow": self.shadow,
479+
}
480+
481+
482+
class Positioning:
483+
"""Positioning properties for caption assets."""
484+
485+
def __init__(
486+
self,
487+
alignment: CaptionAlignment = CaptionAlignment.bottom_center,
488+
margin_l: int = 30,
489+
margin_r: int = 30,
490+
margin_v: int = 30,
491+
):
492+
self.alignment = alignment
493+
self.margin_l = margin_l
494+
self.margin_r = margin_r
495+
self.margin_v = margin_v
496+
497+
def to_json(self):
498+
return {
499+
"alignment": self.alignment.value,
500+
"margin_l": self.margin_l,
501+
"margin_r": self.margin_r,
502+
"margin_v": self.margin_v,
503+
}
504+
505+
506+
class CaptionAsset(BaseAsset):
507+
"""The CaptionAsset is used to create captions from text strings with full styling and ass support."""
508+
509+
type = AssetType.caption
510+
511+
def __init__(
512+
self,
513+
src: str = "auto",
514+
font: Optional[FontStyling] = None,
515+
primary_color: str = "&H00FFFFFF",
516+
secondary_color: str = "&H000000FF",
517+
back_color: str = "&H00000000",
518+
border: Optional[BorderAndShadow] = None,
519+
position: Optional[Positioning] = None,
520+
animation: Optional[CaptionAnimation] = None,
521+
):
522+
self.src = src
523+
self.font = font if font is not None else FontStyling()
524+
self.primary_color = primary_color
525+
self.secondary_color = secondary_color
526+
self.back_color = back_color
527+
self.border = border if border is not None else BorderAndShadow()
528+
self.position = position if position is not None else Positioning()
529+
self.animation = animation
530+
531+
def to_json(self):
532+
data = {
533+
"type": self.type,
534+
"src": self.src,
535+
"font": self.font.to_json(),
536+
"primary_color": self.primary_color,
537+
"secondary_color": self.secondary_color,
538+
"back_color": self.back_color,
539+
"border": self.border.to_json(),
540+
"position": self.position.to_json(),
541+
}
542+
if self.animation:
543+
data["animation"] = self.animation.value
544+
return data
545+
546+
547+
AnyAsset = Union[VideoAsset, ImageAsset, AudioAsset, TextAsset, CaptionAsset]
382548

383549

384550
class Clip:

0 commit comments

Comments
 (0)