The PyonFX Library Documentation¶
“PyonFX is an easy way to do KFX (Karaoke Effects) and complex typesetting based on subtitle format ASS (Advanced Substation Alpha).”
PyonFX is a Python library that helps you to combine tags, text and shapes in ASS format, eventually changing times and layers, with the help of all the automatically extracted data from an input file in ASS format.
That’s not all, it also offers some special functions to help you in some tricky tasks, for example frame per frame operations, shape manipulations or working pixel by pixel, so it’s easier to create impressive visual 2D effects.
In comparison to other karaoke effect programs, PyonFX is written in Python3, which means that you will have all the advantages provided by this modern scripting language, constantly updated and perfect for both beginner and advanced users.
You can learn on how to start using the library on the Quick Start Guide section.
Quick Start Guide¶
First of all, you need to know how you’re creating what. You will need to learn (if you’ve not already) the following:
- ASS format. PyonFX is still an advanced tool for typesetter and karaokers, it is meant to be used by experienced typesetters that knows all the tags rendered by Libass. Check the footnote [1] for a complete list of all the tags.
- Python3 scripting language. A programming language like Python offers you to define what you want in which case, how often, attended to this or that… Basically you’re more free. You’re not limited to buttons, sliders or text fields with just a few commands in a completely graphical interface. The basics are enough. Variables, functions, conditions, loops, comparisons, string formatting, list and dictionaries… You can find the link to some good tutorials in the footnote [2].
To start generating, you will only have to write a script in Python3, which will describes the process of your KFX or advanced typesetting creation.
If you have trouble with the installation of Python, you can check some online guide, like https://realpython.com/installing-python/.
Windows¶
So, if you’ve not installed it before, you will have to install Python3. You can download it from the official website. Just be sure to check the box that says “Add Python 3.x to PATH”. This is really important to avoid some extra steps that would make Python callable in every directory from the command prompt.
Run this command below, which will use pip to install and eventually update the library:
pip install --upgrade https://github.com/CoffeeStraw/PyonFX/zipball/master
That’s all. Nothing else is needed, every time you will have to update, just run again this command.
Ubuntu/Debian¶
Warning: The first of the following commands is not well tested. If you run into any problems, please create an issue or refer to the official installation guide.
sudo apt install python3 python3-pip libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev gir1.2-gtk-3.0 python3-gi python3-gi-cairo
python3 -m pip install --upgrade https://github.com/CoffeeStraw/PyonFX/zipball/master
Fedora¶
Warning: The first of the following commands is not well tested. If you run into any problems, please create an issue or refer to the official installation guide.
sudo dnf install python3 python3-pip gcc gobject-introspection-devel cairo-devel pkg-config python3-devel python3-gobject gtk3
python3 -m pip install --upgrade https://github.com/CoffeeStraw/PyonFX/zipball/master
Arch Linux¶
Warning: The first of the following commands is not well tested. If you run into any problems, please create an issue or refer to the official installation guide.
sudo pacman -S python python-pip cairo pkgconf gobject-introspection python-gobject gtk3
python3 -m pip install --upgrade https://github.com/CoffeeStraw/PyonFX/zipball/master
openSUSE¶
Warning: The first of the following commands is not well tested. If you run into any problems, please create an issue or refer to the official installation guide.
sudo zypper install python3 python3-pip cairo-devel pkg-config python3-devel gcc gobject-introspection-devel python3-gobject python3-gobject-Gdk typelib-1_0-Gtk-3_0 libgtk-3-0
python3 -m pip install --upgrade https://github.com/CoffeeStraw/PyonFX/zipball/master
macOS¶
You may need to install Homebrew first.
Warning: The first of the following commands is not well tested. If you run into any problems, please create an issue or refer to the official installation guide.
brew install pygobject3 gtk+3 cairo py3cairo pkg-config
python3 -m pip install --upgrade https://github.com/CoffeeStraw/PyonFX/zipball/master
Warning: If you experience output not rendered correctly, you might need to change the PangoCairo backend to fontconfig.
PANGOCAIRO_BACKEND=fc python3 namefile.py
Installation - Extra Step¶
This step is not needed to start working with the library, but personally I consider Aegisub quite old and heavy, so I needed a more comfortable way to work.
That’s why PyonFX integrates an additional way to reproduce your works in softsub faster after each generation, using the MPV player. Installing it should be enough to make everything work if your’re NOT on Windows.
If you’re on Windows, all you need to do once you have installed it (check the website for that), is to add it to the PATH, so that the library will be able to utilize it. There are several guide for that, here you can find one.
You need to add the folder that contains the .exe of mpv, generally C:\Program Files\mpv.
Starting¶
You may want to check if everything is working nicely now. For that, I suggest you to try running some of the examples in the GitHub official repository of the project.
To run a script in python, all you need to do is run the following command:
python namefile.py
Or if this is not working for some reason (like you’re not on Windows and both Python2 and Python3 are installed):
python3 namefile.py
I highly suggest you to generate and study every single example in this examples folder (download always up-to-date here). These are meant for absolute beginners until advanced users and explain in detail the usage of all the relevant functions of the library.
Tips¶
- Don’t make a KFX in one go. Make pauses, go for a walk, collect ideas from your surroundings;
- Pick elements of the video. Your effect should merge with the background in some manner;
- Consider human recognition. Mostly we notice motion, then contrasts, then colors. Too much can give a headache, too less is boring;
- Use modern styles to impress (light, curves, particles, gradients) and old ones for readability (solid colors, thick borders, static positions);
- When background is too flashy, try to insert a panel shape to put your text on ‘safe terrain’;
- Adjust to karaoke times and voice. Fast sung lines haven’t syllable durations for effects which need some time to get seen.
Footnotes
| [1] | List of all ASS tags with usage explanation: http://docs.aegisub.org/3.2/ASS_Tags/ |
| [2] | Suggested tutorials for learning Python3: |
The PyonFX Library Reference¶
For ASS parsing functions and object’s classes, you can go on Ass Core section.
For Convert functions usefull to convert everything based on ASS format to something more comfortable (and the other way around), you can go on Convert Functions section.
For Shape functions that will let you do complex calculations with shapes in ASS format, you can go on Shape Functions section.
For general utility functions, you can go on Utils section.
Ass Core¶
-
class
pyonfx.ass_core.Meta¶ Meta object contains informations about the Ass.
More info about each of them can be found on http://docs.aegisub.org/manual/Styles
-
wrap_style¶ Determines how line breaking is applied to the subtitle line
Type: int
-
scaled_border_and_shadow¶ Determines if it has to be used script resolution (True) or video resolution (False) to scale border and shadow
Type: bool
-
play_res_x¶ Video Width
Type: int
-
play_res_y¶ Video Height
Type: int
-
audio¶ Loaded audio path (absolute)
Type: str
-
video¶ Loaded video path (absolute)
Type: str
-
-
class
pyonfx.ass_core.Style¶ Style object contains a set of typographic formatting rules that is applied to dialogue lines.
More info about styles can be found on http://docs.aegisub.org/3.2/ASS_Tags/.
-
fontname¶ Font name
Type: str
-
fontsize¶ Font size in points
Type: float
-
color1¶ Primary color (fill)
Type: str
-
alpha1¶ Trasparency of color1
Type: str
-
color2¶ Secondary color (secondary fill, for karaoke effect)
Type: str
-
alpha2¶ Trasparency of color2
Type: str
-
color3¶ Outline (border) color
Type: str
-
alpha3¶ Trasparency of color3
Type: str
-
color4¶ Shadow color
Type: str
-
alpha4¶ Trasparency of color4
Type: str
-
bold¶ Font with bold
Type: bool
-
italic¶ Font with italic
Type: bool
-
underline¶ Font with underline
Type: bool
-
strikeout¶ Font with strikeout
Type: bool
-
scale_x¶ Text stretching in the horizontal direction
Type: float
-
scale_y¶ Text stretching in the vertical direction
Type: float
-
spacing¶ Horizontal spacing between letters
Type: float
-
angle¶ Rotation of the text
Type: float
-
border_style¶ True for opaque box, False for standard outline
Type: bool
-
outline¶ Border thickness value
Type: float
-
shadow¶ How far downwards and to the right a shadow is drawn
Type: float
-
alignment¶ Alignment of the text
Type: int
-
margin_l¶ Distance from the left of the video frame
Type: int
-
margin_r¶ Distance from the right of the video frame
Type: int
-
margin_v¶ Distance from the bottom (or top if alignment >= 7) of the video frame
Type: int
-
encoding¶ Codepage used to map codepoints to glyphs
Type: int
-
-
class
pyonfx.ass_core.Char¶ Char object contains informations about a single char of a line in the Ass.
A char is defined by some text between two karaoke tags (k, ko, kf).
-
i¶ Char index number
Type: int
-
word_i¶ Char word index (e.g.: In line text
Hello PyonFX users!, letter “u” will have word_i=2).Type: int
-
syl_i¶ Char syl index (e.g.: In line text
{\k0}Hel{\k0}lo {\k0}Pyon{\k0}FX {\k0}users!, letter “F” will have syl_i=3).Type: int
-
syl_char_i¶ Char invidual syl index (e.g.: In line text
{\k0}Hel{\k0}lo {\k0}Pyon{\k0}FX {\k0}users!, letter “e” of “users” will have syl_char_i=2).Type: int
-
start_time¶ Char start time (in milliseconds).
Type: int
-
end_time¶ Char end time (in milliseconds).
Type: int
-
duration¶ Char duration (in milliseconds).
Type: int
-
styleref¶ Reference to the Style object of this object original line.
Type: obj
-
text¶ Char text.
Type: str
-
inline_fx¶ Char inline effect (marked as -EFFECT in karaoke-time).
Type: str
-
prespace¶ Char free space before text.
Type: int
-
postspace¶ Char free space after text.
Type: int
-
width¶ Char text width.
Type: float
-
height¶ Char text height.
Type: float
-
x¶ Char text position horizontal (depends on alignment).
Type: float
-
y¶ Char text position vertical (depends on alignment).
Type: float
-
left¶ Char text position left.
Type: float
-
center¶ Char text position center.
Type: float
-
right¶ Char text position right.
Type: float
-
top¶ Char text position top.
Type: float
-
middle¶ Char text position middle.
Type: float
-
bottom¶ Char text position bottom.
Type: float
-
-
class
pyonfx.ass_core.Syllable¶ Syllable object contains informations about a single syl of a line in the Ass.
A syl can be defined as some text after a karaoke tag (k, ko, kf) (e.g.: In
{\k0}Hel{\k0}lo {\k0}Pyon{\k0}FX {\k0}users!, “Pyon” and “FX” are distinct syllables),-
i¶ Syllable index number
Type: int
-
word_i¶ Syllable word index (e.g.: In line text
{\k0}Hel{\k0}lo {\k0}Pyon{\k0}FX {\k0}users!, syl “Pyon” will have word_i=1).Type: int
-
start_time¶ Syllable start time (in milliseconds).
Type: int
-
end_time¶ Syllable end time (in milliseconds).
Type: int
-
duration¶ Syllable duration (in milliseconds).
Type: int
-
styleref¶ Reference to the Style object of this object original line.
Type: obj
-
text¶ Syllable text.
Type: str
All the remaining tags before syl text apart k ones.
Type: str
-
inline_fx¶ Syllable inline effect (marked as -EFFECT in karaoke-time).
Type: str
-
prespace¶ Syllable free space before text.
Type: int
-
postspace¶ Syllable free space after text.
Type: int
-
width¶ Syllable text width.
Type: float
-
height¶ Syllable text height.
Type: float
-
x¶ Syllable text position horizontal (depends on alignment).
Type: float
-
y¶ Syllable text position vertical (depends on alignment).
Type: float
-
left¶ Syllable text position left.
Type: float
-
center¶ Syllable text position center.
Type: float
-
right¶ Syllable text position right.
Type: float
-
top¶ Syllable text position top.
Type: float
-
middle¶ Syllable text position middle.
Type: float
-
bottom¶ Syllable text position bottom.
Type: float
-
-
class
pyonfx.ass_core.Word¶ Word object contains informations about a single word of a line in the Ass.
A word can be defined as some text with some optional space before or after (e.g.: In the string “What a beautiful world!”, “beautiful” and “world” are both distinct words).
-
i¶ Word index number
Type: int
-
start_time¶ Word start time (same as line start time) (in milliseconds).
Type: int
-
end_time¶ Word end time (same as line end time) (in milliseconds).
Type: int
-
duration¶ Word duration (same as line duration) (in milliseconds).
Type: int
-
styleref¶ Reference to the Style object of this object original line.
Type: obj
-
text¶ Word text.
Type: str
-
prespace¶ Word free space before text.
Type: int
-
postspace¶ Word free space after text.
Type: int
-
width¶ Word text width.
Type: float
-
height¶ Word text height.
Type: float
-
x¶ Word text position horizontal (depends on alignment).
Type: float
-
y¶ Word text position vertical (depends on alignment).
Type: float
-
left¶ Word text position left.
Type: float
-
center¶ Word text position center.
Type: float
-
right¶ Word text position right.
Type: float
-
top¶ Word text position top.
Type: float
-
middle¶ Word text position middle.
Type: float
-
bottom¶ Word text position bottom.
Type: float
-
-
class
pyonfx.ass_core.Line¶ Line object contains informations about a single line in the Ass.
Note
(*) = This field is available only if
extended= True-
i¶ Line index number
Type: int
-
comment¶ If True, this line will not be displayed on the screen.
Type: bool
-
layer¶ Layer for the line. Higher layer numbers are drawn on top of lower ones.
Type: int
-
start_time¶ Line start time (in milliseconds).
Type: int
-
end_time¶ Line end time (in milliseconds).
Type: int
-
duration¶ Line duration (in milliseconds) (*).
Type: int
-
leadin¶ Time between this line and the previous one (in milliseconds; first line = 1000.1) (*).
Type: float
-
leadout¶ Time between this line and the next one (in milliseconds; first line = 1000.1) (*).
Type: float
-
style¶ Style name used for this line.
Type: str
-
styleref¶ Reference to the Style object of this line (*).
Type: obj
-
actor¶ Actor field.
Type: str
-
margin_l¶ Left margin for this line.
Type: int
-
margin_r¶ Right margin for this line.
Type: int
-
margin_v¶ Vertical margin for this line.
Type: int
-
effect¶ Effect field.
Type: str
-
raw_text¶ Line raw text.
Type: str
-
text¶ Line stripped text (no tags).
Type: str
-
width¶ Line text width (*).
Type: float
-
height¶ Line text height (*).
Type: float
-
ascent¶ Line font ascent (*).
Type: float
-
descent¶ Line font descent (*).
Type: float
-
internal_leading¶ Line font internal lead (*).
Type: float
-
external_leading¶ Line font external lead (*).
Type: float
-
x¶ Line text position horizontal (depends on alignment) (*).
Type: float
-
y¶ Line text position vertical (depends on alignment) (*).
Type: float
-
left¶ Line text position left (*).
Type: float
-
center¶ Line text position center (*).
Type: float
-
right¶ Line text position right (*).
Type: float
-
top¶ Line text position top (*).
Type: float
-
middle¶ Line text position middle (*).
Type: float
-
bottom¶ Line text position bottom (*).
Type: float
-
copy()¶ Returns: A deep copy of this object (line)
-
-
class
pyonfx.ass_core.Ass(path_input='', path_output='Output.ass', keep_original=True, extended=True, vertical_kanji=True)¶ Contains all the informations about a file in the ASS format and the methods to work with it for both input and output.
Usually you will create an Ass object and use it for input and output (see example section).PyonFX set automatically an absolute path for all the info in the output, so that wherever you will put your generated file, it should always load correctly video and audio.Parameters: - path_input (str) – Path for the input file (either relative to your .py file or absolute).
- path_output (str) – Path for the output file (either relative to your .py file or absolute) (DEFAULT: “Output.ass”).
- keep_original (bool) – If True, you will find all the lines of the input file commented before the new lines generated.
- extended (bool) – Calculate more informations from lines (usually you will not have to touch this).
- vertical_kanji (bool) – If True, line text with alignment 4, 5 or 6 will be positioned vertically.
-
path_input¶ Path for input file (absolute).
Type: str
-
path_output¶ Path for output file (absolute).
Type: str
Example
io = Ass("in.ass") meta, styles, lines = io.get_data()
-
get_data()¶ Utility function to retrieve easily meta styles and lines.
Returns: meta,stylesandlines
-
write_line(line)¶ Appends a line to the output list (which is private) that later on will be written to the output file when calling save().
Use it whenever you’ve prepared a line, it will not impact performance since you will not actually write anything until
save()will be called.Parameters: line ( Line) – A line object. If not valid, TypeError is raised.
-
save(quiet=False)¶ Write everything inside the private output list to a file.
Parameters: quiet (bool) – If True, you will not get printed any message.
-
open_aegisub()¶ Open the output (specified in self.path_output) with Aegisub.
This can be usefull if you don’t have MPV installed or you want to look at your output in detailed.
Returns: 0 if success, -1 if the output couldn’t be opened.
-
open_mpv(video_path='', video_start='', full_screen=False)¶ Open the output (specified in self.path_output) in softsub with the MPV player. To utilize this function, MPV player is required. Additionally if you’re on Windows, MPV must be in the PATH (check https://pyonfx.readthedocs.io/en/latest/quick%20start.html#installation-extra-step).
This is one of the fastest way to reproduce your output in a comfortable way.
Parameters: - video_path (string) – The video file path (absolute) to reproduce. If not specified, meta.video is automatically taken.
- video_start (string) – The start time for the video (more info: https://mpv.io/manual/master/#options-start). If not specified, 0 is automatically taken.
- full_screen (bool) – If True, it will reproduce the output in full screen. If not specified, False is automatically taken.
Convert Functions¶
-
class
pyonfx.convert.Convert¶ This class is a collection of static methods that will help the user to convert everything needed to the ASS format.
-
static
time(ass_ms)¶ Converts between milliseconds and ASS timestamp.
You can probably ignore that function, you will not make use of it for KFX or typesetting generation.
Parameters: ass_ms (either int or str) – If int, than milliseconds are expected, else ASS timestamp as str is expected. Returns: If milliseconds -> ASS timestamp, else if ASS timestamp -> milliseconds, else ValueError will be raised.
-
static
coloralpha(ass_r_a, g='', b='', a='')¶ Converts between rgb color &/+ alpha numeric and ASS color &/+ alpha.
- Passing a string to this function, you want a conversion from ASS color+alpha, ASS color or ASS alpha to integer values;
- Passing a single number, you want a conversion from ASS alpha value to ASS alpha string;
- Passing 3 or 4 numbers, you want a conversion from rgb (or rgba) values to ASS color (or ASS color+alpha) string.
Parameters: - ass_r_a (int or str) – If a str is given, either an ASS color+alpha, ASS color, an ASS alpha string is expected; if an int is given, a value between 0 and 255 (inclusive) is expected.
- g (int, optional) – If given, a value between 0 and 255 (inclusive) is expected.
- b (int, optional) – If given, a value between 0 and 255 (inclusive) is expected.
- a (int, optional) – If given, a value between 0 and 255 (inclusive) is expected.
Returns: According to the parameters, either a tuple containing rgb (or rgba) integer values or a str containing an ASS color+alpha, an ASS color or an ASS alpha.
Examples
print( Convert.coloralpha(0) ) print( Convert.coloralpha("&HFF&") ) print( Convert.coloralpha("&H0000FF&") ) print( Convert.coloralpha(255, 0, 0) ) print( Convert.coloralpha("&HFF00FF00") ) print( Convert.coloralpha(0, 255, 0, 255) )
>>> &H00& >>> 255 >>> (255, 0, 0) >>> &H0000FF& >>> (0, 255, 0, 255) >>> &HFF00FF00
-
static
text_to_shape(obj, fscx=None, fscy=None)¶ Converts text with given style information to an ASS shape.
Tips: You can easily create impressive deforming effects.
Parameters: Returns: A Shape object, representing the text with the style format values of the object.
Examples
line = Line.copy(lines[1]) line.text = "{\\an7\\pos(%.3f,%.3f)\\p1}%s" % (line.left, line.top, convert.text_to_shape(line)) io.write_line(line)
-
static
text_to_clip(obj, an=5, fscx=None, fscy=None)¶ Converts text with given style information to an ASS shape, applying some translation/scaling to it since it is not possible to position a shape with pos() once it is in a clip.
This is an high level function since it does some additional operations, check text_to_shape for further infromations.
Tips: You can easily create text masks even for growing/shrinking text without too much effort.
Parameters: Returns: A Shape object, representing the text with the style format values of the object.
Examples
line = Line.copy(lines[1]) line.text = "{\\an5\\pos(%.3f,%.3f)\\clip(%s)}%s" % (line.center, line.middle, convert.text_to_clip(line), line.text) io.write_line(line)
-
static
text_to_pixels(obj, supersampling=8)¶ - Converts text with given style information to a list of pixel data.A pixel data is a dictionary containing ‘x’ (horizontal position), ‘y’ (vertical position) and ‘alpha’ (alpha/transparency).
It is highly suggested to create a dedicated style for pixels, because you will write less tags for line in your pixels, which means less size for your .ass file.
The style suggested is:- an=7 (very important!);- bord=0;- shad=0;- For Font informations leave whatever the default is;Tips: It allows easy creation of text decaying or light effects.
Parameters: Returns: A list of dictionaries representing each individual pixel of the input text styled.
Examples
line = lines[2].copy() line.style = "p" p_sh = Shape.rectangle() for pixel in Convert.text_to_pixels(line): x, y = math.floor(line.left) + pixel['x'], math.floor(line.top) + pixel['y'] alpha = "\alpha" + Convert.coloralpha(pixel['alpha']) if pixel['alpha'] != 255 else "" line.text = "{\p1\pos(%d,%d)%s}%s" % (x, y, alpha, p_sh) io.write_line(line)
-
static
shape_to_pixels(shape, supersampling=8)¶ - Converts a Shape object to a list of pixel data.A pixel data is a dictionary containing ‘x’ (horizontal position), ‘y’ (vertical position) and ‘alpha’ (alpha/transparency).
It is highly suggested to create a dedicated style for pixels, because you will write less tags for line in your pixels, which means less size for your .ass file.
The style suggested is:- an=7 (very important!);- bord=0;- shad=0;- For Font informations leave whatever the default is;Tips: As for text, even shapes can decay!
Parameters: - shape (Shape) – An object of class Shape.
- supersampling (int) – Value used for supersampling. Higher value means smoother and more precise anti-aliasing (and more computational time for generation).
Returns: A list of dictionaries representing each individual pixel of the input shape.
Examples
line = lines[2].copy() line.style = "p" p_sh = Shape.rectangle() for pixel in Convert.shape_to_pixels(Shape.heart(100)): # Random circle to pixel effect just to show x, y = math.floor(line.left) + pixel['x'], math.floor(line.top) + pixel['y'] alpha = "\alpha" + Convert.coloralpha(pixel['alpha']) if pixel['alpha'] != 255 else "" line.text = "{\p1\pos(%d,%d)%s\fad(0,%d)}%s" % (x, y, alpha, l.dur/4, p_sh) io.write_line(line)
-
static
Shape Functions¶
-
class
pyonfx.shape.Shape(drawing_cmds)¶ This class can be used to define a Shape object (by passing its drawing commands) and then apply functions to it in order to accomplish some tasks, like analyzing its bounding box, apply transformations, splitting curves into segments…
Parameters: drawing_cmds (str) – The shape’s drawing commands in ASS format as a string. -
has_error()¶ Utility function that checks if the shape is valid.
Returns: False if no error has been found, else a string with the first error encountered.
-
map(fun)¶ Sends every point of a shape through given transformation function to change them.
Tips: Working with outline points can be used to deform the whole shape and make f.e. a wobble effect.
Parameters: fun (function) – A function with two (or optionally three) parameters. It will define how each coordinate will be changed. The first two parameters represent the x and y coordinates of each point. The third optional it represents the type of each point (move, line, bezier…). Returns: A pointer to the current object. Examples
original = Shape("m 0 0 l 20 0 20 10 0 10") print ( original.map(lambda x, y: (x+10, y+5) ) )
>>> m 10 5 l 30 5 30 15 10 15
-
bounding()¶ Calculates shape bounding box.
Tips: Using this you can get more precise information about a shape (width, height, position).
Returns: A tuple (x0, y0, x1, y1) containing coordinates of the bounding box. Examples
print("Left-top: %d %d\nRight-bottom: %d %d" % ( Shape("m 10 5 l 25 5 25 42 10 42").bounding() ) )
>>> Left-top: 10 5 >>> Right-bottom: 25 42
-
move(x=None, y=None)¶ Moves shape coordinates in given direction.
If neither x and y are passed, it will automatically center the shape to the origin (0,0).This function is an high level function, it just uses Shape.map, which is more advanced. Additionally, it is an easy way to center a shape.Parameters: - x (int or float) – Displacement along the x-axis.
- y (int or float) – Displacement along the y-axis.
Returns: A pointer to the current object.
Examples
print( Shape("m 0 0 l 30 0 30 20 0 20").move(-5, 10) )
>>> m -5 10 l 25 10 25 30 -5 30
-
flatten(tolerance=1.0)¶ Splits shape’s bezier curves into lines.
This is a low level function. Instead, you should usesplit()which already calls this function.Parameters: tolerance (float) – Angle in degree to define a curve as flat (increasing it will boost performance during reproduction, but lower accuracy) Returns: A pointer to the current object. Returns: The shape as a string, with bezier curves converted to lines.
-
split(max_len=16, tolerance=1.0)¶ Splits shape bezier curves into lines and splits lines into shorter segments with maximum given length.
Tips: You can call this before using :func:`map` to work with more outline points for smoother deforming.
Parameters: - tolerance (float) – Angle in degree to define a bezier curve as flat (increasing it will boost performance during reproduction, but lower accuracy)
- max_len (int or float) – The max length that you want all the lines to be
Returns: A pointer to the current object.
Examples
print( Shape("m -100.5 0 l 100 0 b 100 100 -100 100 -100.5 0 c").split() )
>>> m -100.5 0 l -100 0 -90 0 -80 0 -70 0 -60 0 -50 0 -40 0 -30 0 -20 0 -10 0 0 0 10 0 20 0 30 0 40 0 50 0 60 0 70 0 80 0 90 0 100 0 l 99.964 2.325 99.855 4.614 99.676 6.866 99.426 9.082 99.108 11.261 98.723 13.403 98.271 15.509 97.754 17.578 97.173 19.611 96.528 21.606 95.822 23.566 95.056 25.488 94.23 27.374 93.345 29.224 92.403 31.036 91.405 32.812 90.352 34.552 89.246 36.255 88.086 37.921 86.876 39.551 85.614 41.144 84.304 42.7 82.945 44.22 81.54 45.703 80.088 47.15 78.592 48.56 77.053 49.933 75.471 51.27 73.848 52.57 72.184 53.833 70.482 55.06 68.742 56.25 66.965 57.404 65.153 58.521 63.307 59.601 61.427 60.645 59.515 61.652 57.572 62.622 55.599 63.556 53.598 64.453 51.569 65.314 49.514 66.138 47.433 66.925 45.329 67.676 43.201 68.39 41.052 69.067 38.882 69.708 36.692 70.312 34.484 70.88 32.259 71.411 27.762 72.363 23.209 73.169 18.61 73.828 13.975 74.341 9.311 74.707 4.629 74.927 -0.062 75 -4.755 74.927 -9.438 74.707 -14.103 74.341 -18.741 73.828 -23.343 73.169 -27.9 72.363 -32.402 71.411 -34.63 70.88 -36.841 70.312 -39.033 69.708 -41.207 69.067 -43.359 68.39 -45.49 67.676 -47.599 66.925 -49.683 66.138 -51.743 65.314 -53.776 64.453 -55.782 63.556 -57.759 62.622 -59.707 61.652 -61.624 60.645 -63.509 59.601 -65.361 58.521 -67.178 57.404 -68.961 56.25 -70.707 55.06 -72.415 53.833 -74.085 52.57 -75.714 51.27 -77.303 49.933 -78.85 48.56 -80.353 47.15 -81.811 45.703 -83.224 44.22 -84.59 42.7 -85.909 41.144 -87.178 39.551 -88.397 37.921 -89.564 36.255 -90.68 34.552 -91.741 32.812 -92.748 31.036 -93.699 29.224 -94.593 27.374 -95.428 25.488 -96.205 23.566 -96.92 21.606 -97.575 19.611 -98.166 17.578 -98.693 15.509 -99.156 13.403 -99.552 11.261 -99.881 9.082 -100.141 6.866 -100.332 4.614 -100.452 2.325 -100.5 0
-
static
ring(out_r, in_r)¶ Returns a shape object of a ring with given inner and outer radius, centered around (0,0).
Tips: A ring with increasing inner radius, starting from 0, can look like an outfading point.
Parameters: - out_r (int or float) – The outer radius for the ring.
- in_r (int or float) – The inner radius for the ring.
Returns: A shape object representing a ring.
-
static
ellipse(w, h)¶ Returns a shape object of an ellipse with given width and height, centered around (0,0).
Tips: You could use that to create rounded stribes or arcs in combination with blurring for light effects.
Parameters: - w (int or float) – The width for the ellipse.
- h (int or float) – The height for the ellipse.
Returns: A shape object representing an ellipse.
-
static
heart(size, offset=0)¶ Returns a shape object of a heart object with given size (width&height) and vertical offset of center point, centered around (0,0).
Tips: An offset=size*(2/3) results in a splitted heart.
Parameters: - size (int or float) – The width&height for the heart.
- offset (int or float) – The vertical offset of center point.
Returns: A shape object representing an heart.
-
static
star(edges, inner_size, outer_size)¶ Returns a shape object of a star object with given number of outer edges and sizes, centered around (0,0).
Tips: Different numbers of edges and edge distances allow individual n-angles.
Parameters: - edges (int) – The number of edges of the star.
- inner_size (int or float) – The inner edges distance from center.
- outer_size (int or float) – The outer edges distance from center.
Returns: A shape object as a string representing a star.
-
static
glance(edges, inner_size, outer_size)¶ Returns a shape object of a glance object with given number of outer edges and sizes, centered around (0,0).
Tips: Glance is similar to Star, but with curves instead of inner edges between the outer edges.
Parameters: - edges (int) – The number of edges of the star.
- inner_size (int or float) – The inner edges distance from center.
- outer_size (int or float) – The control points for bezier curves between edges distance from center.
Returns: A shape object as a string representing a glance.
-
static
rectangle(w=1, h=1)¶ Returns a shape object of a rectangle with given width and height, centered around (0,0).
Tips: A rectangle with width=1 and height=1 is a pixel.
Parameters: - w (int or float) – The width for the rectangle.
- h (int or float) – The height for the rectangle.
Returns: A shape object representing an rectangle.
-
static
triangle(size)¶ Returns a shape object of an equilateral triangle with given side length, centered around (0,0).
Parameters: size (int or float) – The side length for the triangle. Returns: A shape object representing an triangle.
-
Utils¶
-
class
pyonfx.utils.Utils¶ This class is a collection of static methods that will help the user in some tasks.
-
static
all_non_empty(lines_chars_syls_or_words)¶ Helps to not check everytime for text containing only spaces or object’s duration equals to zero.
Parameters: lines_chars_syls_or_words (list of Line,Char,SyllableorWord) –Returns: A list containing lines_chars_syls_or_words without objects with duration equals to zero or blank text (no text or only spaces).
-
static
interpolate(pct, val1, val2, acc=1.0)¶ - Interpolates 2 given values (ASS colors, ASS alpha channels or numbers) by percent value as decimal number.You can also provide a http://cubic-bezier.com to accelerate based on bezier curves. (TO DO)You could use that for the calculation of color/alpha gradients.
Parameters: - pct (float) – Percent value of the interpolation.
- val1 (int, float or str) – First value to interpolate (either string or number).
- val2 (int, float or str) – Second value to interpolate (either string or number).
- acc (float, optional) – Optional acceleration that influences final percent value.
Returns: Interpolated value of given 2 values (so either a string or a number).
Examples
print( Utils.interpolate(0.5, 10, 20) ) print( Utils.interpolate(0.9, "&HFFFFFF&", "&H000000&") )
>>> 15 >>> &HE5E5E5&
-
static
-
class
pyonfx.utils.FrameUtility(start_time, end_time, fr=41.71)¶ This class helps in the stressfull calculation of frames per frame.
Parameters: - start_time (positive float) – Initial time
- end_time (positive float) – Final time
- fr (positive float, optional) – Frame Duration
Returns: Returns a Generator containing start_time, end_time, index and total number of frames for each step.
Examples
FU = FrameUtility(0, 100) for s, e, i, n in FU: print(f"Frame {i}/{n}: {s} - {e}")
>>> Frame 1/3: 0 - 41.71 >>> Frame 2/3: 41.71 - 83.42 >>> Frame 3/3: 83.42 - 100
-
add(start_time, end_time, end_value, accelerator=1.0)¶ - This function makes a lot easier the calculation of tags value.You can see this as a “t” tag usable in frame per frame operations.Use it in a for loop which iterates a FrameUtility object, as you can see in the example.
Examples
FU = FrameUtility(0, 105, 40) for s, e, i, n in FU: fsc = 100 fsc += FU.add(0, 50, 50) fsc += FU.add(50, 100, -50) print(f"Frame {i}/{n}: {s} - {e}; fsc: {fsc}")
>>> Frame 1/3: 0 - 40; fsc: 140.0 >>> Frame 2/3: 40 - 80; fsc: 120.0 >>> Frame 3/3: 80 - 105; fsc: 100
-
class
pyonfx.utils.ColorUtility(lines, offset=0)¶ This class helps to obtain all the color transformations written in a list of lines (usually all the lines of your input .ass) to later retrieve all of those transformations that fit between the start_time and end_time of a line passed, without having to worry about interpolating times or other stressfull tasks.
It is highly suggested to create this object just one time in your script, for performance reasons.
Note
A few notes about the color transformations in your lines:
- Every color-tag has to be in the format of
c&Hxxxxxx&, do not forget the last &; - You can put color changes without using transformations, like
{\1c&HFFFFFF&\3c&H000000&}Test, but those will be interpreted as{\t(0,0,\1c&HFFFFFF&\3c&H000000&)}Test; - For an example of how color changes should be put in your lines, check this.
Also, it is important to remember that color changes in your lines are treated as if they were continuous.
For example, let’s assume we have two lines:
{\1c&HFFFFFF&\t(100,150,\1c&H000000&)}Line1, starting at 0ms, ending at 100ms;{}Line2, starting at 100ms, ending at 200ms.
Even if the second line doesn’t have any color changes and you would expect to have the style’s colors, it will be treated as it has
\1c&H000000&. That could seem strange at first, but thinking about your generated lines, the majority will have start_time and end_time different from the ones of your original file.Treating transformations as if they were continous, ColorUtility will always know the right colors to pick for you. Also, remember that even if you can’t always see them directly on Aegisub, you can use transformations with negative times or with times that exceed line total duration.
Parameters: - lines (list of Line) – List of lines to be parsed
- offset (integer, optional) – Milliseconds you may want to shift all the color changes
Returns: Returns a ColorUtility object.
Examples
# Parsing all the lines in the file CU = ColorUtility(lines) # Parsing just a single line (the first in this case) in the file CU = ColorUtility([ line[0] ])
-
get_color_change(line, c1=None, c3=None, c4=None)¶ Returns all the color_changes in the object that fit (in terms of time) between line.start_time and line.end_time.
Parameters: - line (Line object) – The line of which you want to get the color changes
- c1 (bool, optional) – If False, you will not get color values containing primary color
- c3 (bool, optional) – If False, you will not get color values containing border color
- c4 (bool, optional) – If False, you will not get color values containing shadow color
Returns: A string containing color changes interpolated.
Note
If c1, c3 or c4 is/are None, the script will automatically recognize what you used in the color changes in the lines and put only the ones considered essential.
Examples
# Assume that we have l as a copy of line and we're iterating over all the syl in the current line # All the fun stuff of the effect creation... l.start_time = line.start_time + syl.start_time l.end_time = line.start_time + syl.end_time l.text = "{\\an5\\pos(%.3f,%.3f)\\fscx120\\fscy120%s}%s" % (syl.center, syl.middle, CU.get_color_change(l), syl.text)
-
get_fr_color_change(line, c1=None, c3=None, c4=None)¶ Returns the single color(s) in the color_changes that fit the current frame (line.start_time) in your frame loop.
Note
If you get errors, try either modifying your \t values or set your fr parameter in FU object to 10.
Parameters: - line (Line object) – The line of which you want to get the color changes
- c1 (bool, optional) – If False, you will not get color values containing primary color.
- c3 (bool, optional) – If False, you will not get color values containing border color.
- c4 (bool, optional) – If False, you will not get color values containing shadow color.
Returns: A string containing color changes interpolated.
Examples
# Assume that we have l as a copy of line and we're iterating over all the syl in the current line and we're iterating over the frames l.start_time = s l.end_time = e l.text = "{\\an5\\pos(%.3f,%.3f)\\fscx120\\fscy120%s}%s" % (syl.center, syl.middle, CU.get_fr_color_change(l), syl.text)
- Every color-tag has to be in the format of