captionbob docs

Version 1.0.0
Contents ↓

Python: captionbob.effects

captionbob.effects.punch

Punch effect: bold white words and a heavy slanted keyword.

Each caption shows one or two words in one line of bold white letters, in the case and with the end marks of the speech, with a soft dark shadow that reaches a little further below the letters than above them. A caption ends at each end mark, such as a comma. The longest word of a caption is its keyword when it has enough letters. A keyword is written in heavy slanted capitals that are larger and wider than the other words. Its letters keep a top color over their upper part and go to a bottom color over their lower part. A dark outline in the color of the keyword goes around its letters, with a glow of that color below them. The keywords of a video take the keyword looks in turn. An end mark behind a keyword, such as a full stop, has the look of the other words.

A caption with a keyword sits lower than a plain caption, and it drifts on a diagonal: a short time after its start it moves in a straight line for the drift time, and then it stays. The middle of the drift is the place of the caption. The keyword captions take the drift turns in order, down and to the right or up and to the left. A space in front of a keyword gets the gap before a keyword, and a space behind it gets the gap after a keyword, so that the outline and the glow of the keyword keep a clear room from the other words. The slanted letters lean to the right at their top, so the space behind a keyword needs more room than the space in front.

A caption shows at once when its first word starts, and it goes when its last word ends, so the screen is empty in a pause between two captions.

A caption always stays in one line. The caption measure gives the width of each word in its font, and a caption that is wider than the room between the side margins gets smaller as a whole, with its borders, its blurs and its drops, so that it fits the room. The width of a caption is the width of its words and of the spaces between them: the words and the spaces of the plain font at the plain letter width, and each keyword at the keyword letter width, with its weight on each side and the keyword gaps at the spaces next to it. The measure gives the spaces from the caption in the plain font, so the slant of a keyword can make a caption a few pixels wider or narrower than its count.

A caption is events at one place, one layer above the other: the shadow of the plain words, the outline and the glow of the keyword, the text, and the strips of the gradient of the keyword. ASS has no gradient, so each strip is an event of the whole caption with a clip to the rows of the strip, and only the keyword shows in it. The clip of a strip moves with the drift. Each word and each space is a run of its own, with the same font tags in each event, so the events of a caption put each word at one place.

The keyword font name may be the full name of one face of a font, such as Ubuntu Bold Italic. libass and the caption measure both pick that face by the name, so the measure gives the widths of the slanted letters.

The effect draws nothing itself. It builds the text of an ASS script, and ffmpeg draws it on the video. The common part of the effects is in effect_common.py.

The defaults are the look of the source video of the effect, measured on its frames and scaled to a video of 1080x1920.

Source file: captionbob/effects/punch.py

Settings

The command line and the HTTP API call this effect the style punch. Its settings class is PunchSettings. Each setting has the default below.

Setting Type Default Description
most_words integer 2 The most words that one caption shows.
fewest_words integer 1 The fewest words that one caption shows, when its sentence is long enough for that.
font_name string "Ubuntu" Name of the font of the text.
font_size integer 89 Height of the font in pixels.
bold boolean true True for bold text.
primary_color string "#FFFFFF" Color of the text, as "#RRGGBB".
stroke_color string "#000000" Color of the outline of the text, as "#RRGGBB".
stroke_width number 0.0 Width of the outline in pixels. 0 gives no outline.
bottom_position number 0.6995 Where the bottom of the caption sits, as a part of the video height from the top. 0.75 is three quarters of the way down.
side_margin integer 54 Room in pixels that stays free on the left and on the right of the caption. A caption that is too wide for the room between the margins breaks into lines.
letter_width number 1.02 The width of the letters of the plain words as a part of the width that the font gives them, above 0.
end_at_marks boolean true True to end a caption also at each word that ends with an end mark, such as a comma.
shadow_color string "#000000" The color of the shadow of the plain words, as "#RRGGBB".
shadow_spread number 4.0 How far the shadow reaches past the outline, in pixels.
shadow_blur number 9.0 How far the edge of the shadow fades out, in pixels.
shadow_opacity number 0.85 The strength of the shadow, from 0 for no shadow to 1.
shadow_drop number 3.0 How far the shadow is below the letters, in pixels. A value below 0 puts the shadow above them.
keyword_font_name string "Ubuntu Bold Italic" Name of the font of a keyword. A full name, such as Ubuntu Bold Italic, picks one face of a font.
keyword_bold boolean true True for bold keyword letters.
keyword_font_size integer 105 Height of the font of a keyword in pixels, a whole number above 0. The row of a caption with a keyword is this high.
keyword_letter_width number 1.37 The width of the letters of a keyword as a part of the width that the font gives them, above 0.
keyword_weight number 6.0 How far the letters of a keyword grow on each side, in pixels, to make them heavier. 0 keeps the letters of the font.
keyword_looks list [{"top_color": "#700091", "bottom_color": "#520098", "outline_color": "#42076A"}, {"top_color": "#61DF08", "bottom_color": "#428805", "outline_color": "#3F7906"}, {"top_color": "#BF5606", "bottom_color": "#731B06", "outline_color": "#640B00"}] The looks of the keywords, each a top color, a bottom color and an outline color. The keywords of a video take them in turn.
keyword_outline_width number 7.0 How far the outline of a keyword reaches past its grown letters, in pixels.
keyword_outline_blur number 5.0 How far the edge of the outline and of the glow fades out, in pixels.
keyword_glow_drop number 14.0 How far the glow of a keyword is below its letters, in pixels. A value below 0 puts it above them.
keyword_glow_opacity number 0.5 The strength of the glow, from 0 for no glow to 1.
gradient_top number 0.48 Where the gradient of a keyword starts, as a part of its row below the top of the row. The letters above it have the top color.
gradient_bottom number 0.9 Where the gradient ends, as a part of its row below the top of the row, below the gradient top. The letters below it have the bottom color.
strip_height integer 3 The height in pixels of a strip of the gradient, 1 or above. A lower strip gives a smoother gradient and more events.
keyword_gap_before number 11.0 Room in pixels that is added to a space in front of a keyword. A value below 0 puts the words closer.
keyword_gap_after number 30.0 Room in pixels that is added to a space behind a keyword. A value below 0 puts the words closer. A space between two keywords gets both gaps.
keyword_drop number 32.5 How far the place of a caption with a keyword is below the bottom position, in pixels. A value below 0 puts it higher.
drift number 19.0 How far a caption with a keyword moves to the side and up or down, in pixels. 0 keeps it at its place.
drift_delay_seconds number 0.1 The time from the start of a caption with a keyword to the start of its drift.
drift_seconds number 0.53 The time of the drift. 0 shows the caption at the end of its drift from the delay on.
drift_turns list ["down right", "up left"] The directions of the drift, DRIFT_DOWN_RIGHT or DRIFT_UP_LEFT. The captions with a keyword take them in turn.
hold_seconds number 0.0 The longest time that a caption stays after its last word ends. The caption goes earlier when the next caption starts.

KeywordLook

class KeywordLook(NamedTuple)

The colors of one keyword look.

Args:

  • top_color: The color of the upper part of the letters, as "#RRGGBB".
  • bottom_color: The color at the bottom of the letters, as "#RRGGBB".
  • outline_color: The color of the outline and of the glow, as "#RRGGBB".

PunchSettings

@dataclass(frozen=True)
class PunchSettings(CaptionSettings)

The settings of the punch effect: the settings of CaptionSettings, with the defaults of the source video, the letter width, the end of a caption at an end mark, the shadow, the keyword, its looks, its outline and glow, its gradient, its gap and its drop, the drift and the hold time.

Args:

  • letter_width: The width of the letters of the plain words as a part of the width that the font gives them, above 0.
  • end_at_marks: True to end a caption also at each word that ends with an end mark, such as a comma.
  • shadow_color: The color of the shadow of the plain words, as "#RRGGBB".
  • shadow_spread: How far the shadow reaches past the outline, in pixels.
  • shadow_blur: How far the edge of the shadow fades out, in pixels.
  • shadow_opacity: The strength of the shadow, from 0 for no shadow to 1.
  • shadow_drop: How far the shadow is below the letters, in pixels. A value below 0 puts the shadow above them.
  • keyword_font_name: Name of the font of a keyword. A full name, such as Ubuntu Bold Italic, picks one face of a font.
  • keyword_bold: True for bold keyword letters.
  • keyword_font_size: Height of the font of a keyword in pixels, a whole number above 0. The row of a caption with a keyword is this high.
  • keyword_letter_width: The width of the letters of a keyword as a part of the width that the font gives them, above 0.
  • keyword_weight: How far the letters of a keyword grow on each side, in pixels, to make them heavier. 0 keeps the letters of the font.
  • keyword_looks: The looks of the keywords, each a top color, a bottom color and an outline color. The keywords of a video take them in turn.
  • keyword_outline_width: How far the outline of a keyword reaches past its grown letters, in pixels.
  • keyword_outline_blur: How far the edge of the outline and of the glow fades out, in pixels.
  • keyword_glow_drop: How far the glow of a keyword is below its letters, in pixels. A value below 0 puts it above them.
  • keyword_glow_opacity: The strength of the glow, from 0 for no glow to 1.
  • gradient_top: Where the gradient of a keyword starts, as a part of its row below the top of the row. The letters above it have the top color.
  • gradient_bottom: Where the gradient ends, as a part of its row below the top of the row, below the gradient top. The letters below it have the bottom color.
  • strip_height: The height in pixels of a strip of the gradient, 1 or above. A lower strip gives a smoother gradient and more events.
  • keyword_gap_before: Room in pixels that is added to a space in front of a keyword. A value below 0 puts the words closer.
  • keyword_gap_after: Room in pixels that is added to a space behind a keyword. A value below 0 puts the words closer. A space between two keywords gets both gaps.
  • keyword_drop: How far the place of a caption with a keyword is below the bottom position, in pixels. A value below 0 puts it higher.
  • drift: How far a caption with a keyword moves to the side and up or down, in pixels. 0 keeps it at its place.
  • drift_delay_seconds: The time from the start of a caption with a keyword to the start of its drift.
  • drift_seconds: The time of the drift. 0 shows the caption at the end of its drift from the delay on.
  • drift_turns: The directions of the drift, DRIFT_DOWN_RIGHT or DRIFT_UP_LEFT. The captions with a keyword take them in turn.
  • hold_seconds: The longest time that a caption stays after its last word ends. The caption goes earlier when the next caption starts.

Raises:

  • TypeError: When a word count is not a whole number.
  • ValueError: When a value is outside its range, when a color is not in the form "#RRGGBB", or when a font name is empty or holds a comma.

PunchSettings.plain_font_tags

def plain_font_tags(self, scale: float) -> str

Write the font tags of a plain word, with no curly brackets.

Args:

  • scale: The size of the caption as a part of its full size.

PunchSettings.keyword_font_tags

def keyword_font_tags(self, scale: float) -> str

Write the font tags of a keyword, with no curly brackets.

Args:

  • scale: The size of the caption as a part of its full size.

keyword_parts

def keyword_parts(text: str) -> tuple[str, str]

Cut a keyword into its letters and the end marks behind them.

Args:

  • text: The text of the word, as spoken.

Returns:

The word with no end marks and no closing marks at its end, and those marks. A word that is only such marks keeps its text, and it has no marks behind it.

ShownWord

class ShownWord(NamedTuple)

One word of a caption as the effect shows it.

Args:

  • letters: The letters of the word. A keyword has them in capitals.
  • marks: The end marks behind the letters of a keyword, which have the look of the plain words. Empty for a plain word.

PunchCaption

class PunchCaption(NamedTuple)

One caption of the effect, before it is fitted to its room.

Args:

  • caption: The caption with the times of its events.
  • shown: The words as the effect shows them.
  • looks: The look of each keyword, by its place.

MeasureBlock

class MeasureBlock(NamedTuple)

One part of a caption that the caption measure measures.

Args:

  • word: The place of the word of the part.
  • text: The text of the part: the letters of a word, or the end marks of a keyword.
  • keyword_letters: True for the letters of a keyword.

Drift

class Drift(NamedTuple)

The place of a caption at the start and at the end of its drift.

Args:

  • start_x: The column of the bottom middle of the caption at the start.
  • start_y: The row of the bottom middle of the caption at the start.
  • end_x: The column at the end of the drift.
  • end_y: The row at the end of the drift.
  • start_milliseconds: The tag time at which the drift starts.
  • end_milliseconds: The tag time at which the drift ends.

Drift.moves

def moves(self) -> bool

Say if the caption moves: it has a way to go and a time to go it. libass reads the times 0 and 0 of a move as the whole length of the event, so a drift that ends at 0 does not move.

Drift.place_tags

def place_tags(self, drop: float) -> str

Write the tags of the place of an event of the caption.

Args:

  • drop: How far the event is below the place of the caption, in pixels.

Returns:

The tags with no curly brackets: the move of the drift, or the place at its end when the caption does not move.

Drift.clip_tags

def clip_tags(self, top: int, bottom: int, video_width: int) -> str

Write the clip of a strip that moves with the drift.

Args:

  • top: The first row of the strip at the start of the drift.
  • bottom: The row below the strip at the start of the drift.
  • video_width: Width of a frame of the video in pixels.

Returns:

The tags with no curly brackets. The clip of a caption that moves changes in a straight line in the time of the drift, so it keeps the rows of the strip. A clip tag holds whole rows.

PunchEffect

class PunchEffect
    def __init__(
            self, settings: PunchSettings, caption_measure: PlaceMeasure,
            keyword_picker: KeywordPicker = DEFAULT_KEYWORD_PICKER) -> None

Builds the ASS script of bold white words with a heavy slanted keyword.

Args:

  • settings: The look and the timing of the effect.
  • caption_measure: The measure that says how wide libass draws each word in its font. It runs ffmpeg once for the plain words and once for the keywords of a video.
  • keyword_picker: Names the keywords of each caption from its words as spoken. The default picks the longest word when it has KEYWORD_FEWEST_LETTERS letters or more.

PunchEffect.build_ass_text

def build_ass_text(self, words: Sequence[Word], video: VideoInfo) -> str

Build the ASS script of the effect for the words of one video.

Each caption is a shadow event and a text event. A caption with a keyword also has an outline event and the strip events of the gradient of its keywords. The events of all captions are written by layer, from the lowest. They start with the first word of their caption. They end when the next caption starts, and at the latest the hold time after its last word and at the end of the video.

Args:

  • words: The words of the video in time order, each with its times.
  • video: The frame size and the duration of the video.

Returns:

The text of the ASS script. It has no event when there are no words.

Raises:

  • ValueError: When the side margins leave no room for the caption in the width of the video, when the keyword picker gives a place that is not a word of its caption, or when libass draws no pixel for a word.
  • RuntimeError: When the ffmpeg of the caption measure fails.