- TOC
- Purpose
- Use Cases
- Operations
- Interfaces
- Entities
- Configuration
- Using Transitions
- Transition Tester
- TODO
The purpose of voctomix transitions is to implement an easy way to semi-automatize fading from one video mixing scenario to another. We call those scenarios composites. A composite in voctomix traditionally consists of up to two mixed video sources A and B whose representation parameters we call frames.
So far voctomix was capable of using the following preset composites:
- single source c(A)
- single source full screen (fs)
- two sources c(A,B)
- side-by-side (sbs)
- picture-in-picture (pip)
- side-by-side-preview (sbsp)
Until transitions existed in voctomix, switching between any of these compositing scenarios was made rapidly from one frame to the next. The idea of transitions is to fade between composites by doing an animation and/or alpha (transparency) blending. With voctomix transitions we like to produce the most expected result for every possible scenario and give the user also the ability to create new composites and adjust or improve existing ones or even invent new transitions.
A composite is a mix of multiple source images sources into a single destination image. The voctomix project was previously using four fixed composites called fullscreen, picture-in-picture (pip), side-by-side and side-by-sidepreview. We can divide these transitions into the following categories. Voctomix also uses a background source image which will not be discussed here because it is just irrelevant for handling transitions.
The images below show source A in red and source B in blue.
We name these kind of composites c(A) or c(B).
We name these kind of composites c(A,B).
We later also differ between overlapping and non-overlapping composites. pip for example is an overlapping composite because the image of source B overlaps that of source A.
Generally we can differ between the following transition cases.
First case is to switch from one full screen source to another by switching A ↔ B. The most common method here is to blend transparency of both sources from one to the other.
Switch from full screen to a composite of both sources can be done by blending the alpha channel of the added source from transparent to opaque or by an animation of the incoming source or both.
To switch between A and B within a composite an animation is preferable. In some composites like picture-in-picture (see in the middle) the second source (B) is overlapping the first one (A) and so the z-order (order in which the frames have to be drawn) has to be flipped within a transition to get a proper effect.
To guarantee that this is possible transitions can be improved by inserting so-called intermediate composites which add key frames for both sources in which they do not overlap and so bring a chance to do the z-order swap. voctomix transitions is then using B-Splines to interpolate a smooth motion between c(A,B) ↔ t'(A,B) ↔ c(B,A). You even can use multiple intermediate composites within the same transition, if you like.
Switching the composite while leaving the sources A and B untouched is similar to the previous case c(A,B) ↔ c(B,A) except that there is usually no need to have intermediate composites to switch the z-order because A and B remain unswapped.
Switching a source of one frame within a composite to another (external) source leads to a three-sources transition because three sources have to be mixed together simultaneously. To avoid the complexity of transitions of such a higher grade we like to stay with the real use cases which occur when working with voctomix. We exclude all three sources transitions except those of one type.
When you start with a single source composite and you switch that one input source to another one which is not the hidden source B, you just have to switch source B to A2 first and then do a two source transition c(A1) ↔ c(B) which is then equivalent to c(A1) ↔ c(A2).
We easily can cover this one with the same switching maneuver as in the previous case.
The remaining one is different: If you want to switch one of the sources within a two source composite to a new (external) source you need a real three sources transition to animate that case.
Again we like to restrict that issue to the real use case where we use just one type of three source transition which is based on a two source transitions and just mixes one source to another external by transparency fading.
This case is currently out of scope for transitions and is solved within the mixer.
To minimize the amount of composites and transitions which must be configured, missing composites and transitions shall be auto-generated. The rules to do that are listed below.
Mostly these operations are inserted automatically. They are described here for better understanding of how voctomix transitions work and to understand the debugging output of the resulting code.
A frame of empty size is invisible like one which is fully transparent but has an extent. Also a composite of two frames where one is opaque and overlapping the other completely includes one invisible frame. So those kind of composites may be treated as equivalent if one frame differs in both composites by some properties but is overall still invisible in both.
So when voctomix-transitions is looking for a matching composite it uses this rule which shortens the list of necessary manual transition definitions.
A composite of source A and B c(A,B) can be swapped by simply swapping A and B like in this example:
We mark that swap operation with a ^
sign.
Put into a formula we can write this as
The gamma operation is used for that one remaining three sources transition case when you switch one of the sources to another input within a two source composite.
Taking a two source composite c(A,B) and a third source C this operation has a transition T as result.
We describe that with the upper case Greek letter Γ as:
*T* = Γ(*c*,C) = Γ(*c*(A,B),C) = *c*(A,B) → *c*(A,C) or *T* = Γ(C,*c*) = Γ(C,*c*(A,B)) = *c*(A,B) → *c*(C,B)Where T is the resulting transition, c is the current composite and A,B and C the related sources.
Because voctomix transitions are focusing on two sources composites and translations we will integrate that case in separately into the mixer.
A transition T from composite c1 to composite c2 written as...
T = c1 → c2
...can be reversed.
We mark that reverse operation with an exponent of -1
:
T-1 = (c1(A,B) → c2(A,B))-1 = c2(A,B) → c1(A,B)
Or shorter:
T-1 = (c1 → c2)-1 = c2 → c1
This operation is needed to handle some transitions between overlay composites. It works different because it does not change a transition but it's processing. We call that operation Φ().
Overlay composites have a so-called z-order which defines that B is drawn above A. If you take an overlay composite like picture-in-picture, generating an animation for swapping both sources must include a switch of this z-order.
This is done with the Φ() operation which finds the first composite within a transition where source B do not even partially cover the image of source A. To profit by this operation one must specialize this transition an put a non-overlaying composite between the target composites.
So to get a proper picture-in-picture &arr; picture-in-picture transition we can put a side-by-side composite between:
Φ(*pip* ↔ *sbs* ↔ *pip*)The result with a side-by-side composite in the middle looks like:
On the left you can see the added side-by-side composite as rectangles and you can see that A and B are swapping somewhere within the animation.
Without side-by-side in the middle it would look like:
...which is worse than a hard cut.
To use the following code you first need to import some stuff.
from transitions import Transitions, Composites
Maybe importing L
, T
, R
and B
is a good idea too because it can be helpful when accessing the coordinates of the resulting animation frames.
X
and Y
can be used to access width and height in size
.
Composites
(plural) is a python class of the preferred interface to voctomix composites and includes the following function:
Reads a configuration and returns all included composites.
Take that return value and give it to Transitions.configure()
to load the transitions configuration.
You may also use the included composites to set up your compositor's switching capabilities - for example in the user interface.
def configure(cfg, size):
Additionally you have to give size
which must be a list including width and height in pixels of both source frames.
It is an external parameter and should be given by your compositor configuration.
size
will be used to calculate coordinates from any proportional floating point values inside the configuration and for calculating source related coordinates of any cropping.
The return value is a dictionary of string
→ Composite
.
configure()
may throw an RuntimeError
exception when parsing the syntax causes problems.
In future development this could also take different size
values for each source too.
Transitions
holds a transition table from all configured target composites to each other.
Reads a configuration and returns all included transitions.
Take that return value and give it to find()
to fetch a specific transition.
def configure(cfg, composites, fps=25):
Generates all transitions configured by the list of named configuration values in dictionary cfg
(string
→ string
) by using the given composites
and fps
(frames per second) and return them in a dictionary of string
→ Transition
.
configure()
may throw an RuntimeError
exception when parsing the syntax causes problems.
This method is mainly used internally by config()
but you also can use it to add transitions manually to the transition table.
def add(self, transition, frames, overwrite=False):
transition
is added to at all position in the table where it matches.
frames
is the number of frames the (re-)calculated transition shall last.
When overwrite
is False
existing transitions will not be overwritten.
Fetch a transition whose beginning and ending is matching the given composites.
def find(begin, end):
Searches in the given dictionary transitions
for a transition that fades begin
to end
.
In a second step also checks if reversed versions transitions match.
If a transition was found a tuple of it's name and the transition will be returned - otherwise None
.
Returns a list of pairs of composites along all possible transitions between all given composites
by walking the tree of all combinations recursively.
def travel(composites, previous=None):
Parameter previous
shall always be the default None
and must only be used internally for recursion.
This method is just a tool to walk all possible transitions in one animation and so concatenate existing transitions.
Currently it is only used within the Transition Tester to generate test output but could be also subject of future development to generate more complex animations by concatenation.
A transition consists of a list of composites. These composites can be either:
- two or more in a list of key composites to generate an animation for
- or a list of composites which describe an already generated animation and so a ready-to-go transition.
Returns the number of composites stored in this transition.
def frames(self):
The return value can be either the number of key frames or the number frames of an animation depending on if this transition instance is meant to be used as a parameter to calculate an animation or as return value of that calculation.
Returns one frame of the sources A or B which shall be realized within your compositor.
def A(self, n):
def B(self, n):
Precisely returns Frame
number n
of source A or B of the Transtition
.
Return the index of the frame preferred to flip both sources (and the scenario) to get a proper z-order behavior.
def flip(self):
Using this information is strongly recommended to get smooth results, when using transitions of type c(A,B) ↔ c(B,A).
Returns the begin or end composite of that transition.
def begin(self):
def end(self):
Returns the name of that transition.
def name(self):
A Composite
instance includes two frames for source A and B and includes no functions you need to know about to use voctomix transitions.
Marks intermediate composites if True
.
self.inter = False
Intermediate composites can be marked by this flag to avoid their appearance in an UI selection for example.
A Frame includes all the information necessary to set up a single source in your compositor:
Returns the dimensions in pixels of this frame.
self.rect = [0, 0, 0, 0]
The value is a list of coordinates of the left, top, right and bottom of the frame.
Use imported constants L
, T
, R
and B
to access these list elements.
The default is an empty rectangle in the upper-left corner.
The transparency value of this frame.
self.alpha = 255
A value between 0
and 255
where 0
means invisible, 255
means opaque and values between describe the corresponding semi-transparency.
The source's cropping values which may change within a transition animation.
self.crop = [0, 0, 0, 0]
The values are the left, top, right and bottom cropping meant as distance from the frame's originally borders.
Because cropping is a property of the video source these values will be related to the source size given to Composites.configure()
.
This member is True
if this is a key frame loaded from the configuration or False
if it was generated by interpolation.
self.key = False
Returns the cropped rectangle of the frame related to the current size of the frame.
def cropped(self):
Use this to get the resulting frame's extent which will be visible in the image mixed by your compositor.
Configuration is done with an INI file like all the other voctomix configuration.
Additionally we like to leave the configuration as easy and compatible as possible to former configurations. Because we also like to increase the flexibility, any unification of the composites does indeed lead to a quite different configuration format. To keep migration easy the basic options and values are mostly just reordered or renamed.
List of configurations of custom named composites for mixing video sources A and B.
Attribute | Format | Default | Description |
---|---|---|---|
name.a |
RECT | no output | position and size of frame A |
name.b |
RECT | no output | position and size of frame B |
name.crop-a |
CROP | no cropping | cropping borders of frame A |
name.crop-b |
CROP | no cropping | cropping borders of frame B |
name.alpha-a |
ALPHA | opaque | opacity of frame A |
name.alpha-b |
ALPHA | opaque | opacity of frame B |
name.noswap |
BOOL | swap | prevents to target swapped composite |
So a default frame without any attributes is invisible by his zero extent.
All attributes begin with the composite's name followed by a dot .
and the attribute's name.
A composite can be freely named but name must be unique.
In RECT and CROP you may decide if you like to use absolute pixel coordinates or proportional floating point values. Using proportional values is often an advantage because you can easily change the full screen size once and all other pixel values will be automatically calculated with that size. This enables you to use the same composites configuration with different resolutions but similar aspect ratio.
Rectangular coordinates are given in different formats like: X/Y WxH
, POS WxH
, X/Y SIZE
, POS SIZE
or *
.
Whereat X
,Y
,W
,H
can be mixed integer pixel coordinates or float proportions.
POS
and SIZE
need to be float proportions.
*
stands for full screen and inserts the size
which was once given to Composites.configure()
.
c.a = 10/10 100x100 ; source A pixel dimensions with format 'X/Y WxH'
c.a = 0.4 0.2 ; source A float proportions with format 'XY WH'
c.a = 0.1/10 0.9 ; stupid mixup with format 'X/Y WH'
c.b = * ; source B becomes full screen
Cropping borders which are given by either L/T/R/B
, LR/TB
or LRTB
L
,T
,R
,B
, LR
,TB
and LRTB
can be mixed integer absolute coordinates or float
proportions.
c.crop-a = 0/100/0/100 ; source A pixel cropping borders with format 'L/T/R/B'
c.crop-a = 0.0/0.2 ; source A float proportional borders with format 'LR/TB'
c.crop-b = 0.1 ; source B 10% from each border in format 'LRTB'
Integer value in the range between 0
(invisible) and 255
(opaque) or float value between 0.0
(invisible) and 1.0
(opaque) or *
(also opaque).
Any value is true but false if empty.
c.alpha-a = * ; opaque source A using '*'
c.alpha-b = 0.5 ; 50% semitransparent source B as float
The configuration of a transition is more easy.
List all transitions in an ini section like [transitions]
.
Each one can be freely named and describes a timespan and a list of composites which will be processed into an animation. Interpolation will be linear with two composites and B-Splines for more.
my_transition = 1000, pip / sidebyside
This generates a linear transition from composite pip
to composite sidebyside
lasting one second (1000
milliseconds).
my_transition = 1500, pip / sidebyside / pip
This generates a B-Spline transition from composite pip
to composite sidebyside
to composite pip
(with A and B automatically swapped) with a duration of one and a half seconds (1500
milliseconds).
from transitions import Composites, Transitions, L, T, R, B
from configparser import SafeConfigParser
from out_of_scope import update_my_compositor
# set frame size
size = [1920, 1080]
# set frames per second
fps = 25
# load INI files
config = SafeConfigParser()
config.read(filename)
# read composites config section
composites = Composites.configure(config.itemc('composites'), size)
# read transitions config section
transitions = Transitions.configure(config.itemc('transitions'), composites, fps)
# search for a transitions that does a fade between fullscreen and sidebyside composites
t_name, t = Transitions.find(composites["fullscreen"], composites["sidebyside"], transitions)
# stupid loop through all frames of the animation
for i in range(t.framec()):
# access current frame in animation to update compositing scenario
update_my_compositor( t.A(i), t.B(i) )
The transitions tester lists information about what composites and transitions are defined in a configuration called composite.ini
and generates PNG files or animated GIF for each listed transition.
You may also select additional drawing of cropping, key frames or a title by command line option or take a further look into the calculations by using verbose mode.
▶ python3 testtransition.py -h
usage: testtransition.py [-h] [-m] [-l] [-g] [-t] [-k] [-c] [-C] [-r] [-n]
[-P] [-L] [-G] [-v]
[composite [composite ...]]
transition - tool to generate voctomix transition animations for testing
positional arguments:
composite list of composites to generate transitions between (use all
available if not given)
optional arguments:
-h, --help show this help message and exit
-m, --map print transition table
-l, --list list available composites
-g, --generate generate animation
-t, --title draw composite names and frame count
-k, --keys draw key frames
-c, --corners draw calculated interpolation corners
-C, --cross draw image cross through center
-r, --crop draw image cropping border
-n, --number when using -g: use consecutively numbers as file names
-P, --nopng when using -g: do not write PNG files (forces -G)
-L, --leave when using -g: do not delete temporary PNG files
-G, --nogif when using -g: do not generate animated GIFS
-v, --verbose also print WARNING (-v), INFO (-vv) and DEBUG (-vvv)
messages
▶ python3 testtransition.py -lvgCctk pip
1 targetable composite(s):
pip
1 intermediate composite(s):
fullscreen-pip
saving transition animation file 'pip-pip.gif' (pip-pip, 37 frames)...
1 transitions available:
pip-pip
This call generates the following animated GIF:
You can see the key frames of pip
A.0
=B.2
and B.0
=A.2
of the start and end composite. In the vertical center you can see the key frames A.1
and B.1
given by sidebyside
to produce a moment of non-overlapping. At the first time when the blue frame B
is not overlapping the red one A
the flipping point is reached and sources A
/B
can be flipped without side effects.
The following configuration file was used to generate that animation:
[output]
; full screen size in pixels
size = 960x540
; frames per second to render
fps = 25
[composites]
; Frame A full screen
pip.a = *
; frame B lower-right corner with 16% size
pip.b = 0.83/0.82 0.16
; left-middle nearly half size
sidebyside.a = 0.008/0.25 0.49
; right-middle nearly half size
sidebyside.b = 0.503/0.25 0.49
[transitions]
; transition from pip to pip (swapped) over sidebyside within 1.5 seconds
pip-pip = 1500, pip / sidebyside / pip
In verbose mode you can see more information about how a transition will be found and what it's data looks like:
▶ python3 testtransition.py -vvv pip
reading composites from configuration...
read 2 composites:
sbs
pip
reading transitions from configuration...
adding transition pip-pip = pip -> pip
pip-pip = pip -> pip:
No. Key A( L, T R, B alpha LCRP,TCRP,RCRP,BCRP XZOM,YZOM) B( L, T R, B alpha LCRP,TCRP,RCRP,BCRP XZOM,YZOM) Name
0 * A( 0, 0 240, 135 255 0, 0, 0, 0 0.00,0.00) B( 199, 110 237, 131 255 0, 0, 0, 0 0.00,0.00) pip
1 * A( 1, 33 118, 99 255 0, 0, 0, 0 0.00,0.00) B( 120, 33 237, 99 255 0, 0, 0, 0 0.00,0.00) sbs
2 * A( 0, 0 240, 135 255 0, 0, 0, 0 0.00,0.00) B( 199, 110 237, 131 255 0, 0, 0, 0 0.00,0.00) pip
calculating transition pip-pip = pip/sbs/pip
read 1 transition(s):
pip-pip
using 1 target composite(s):
pip
generated sequence (2 items):
pip
pip
request transition (1/1): pip → pip
transition found: Φ(pip-pip)
Φ(pip-pip) = pip -> pip:
No. Key A( L, T R, B alpha LCRP,TCRP,RCRP,BCRP XZOM,YZOM) B( L, T R, B alpha LCRP,TCRP,RCRP,BCRP XZOM,YZOM) Name
0 * A( 0, 0 240, 135 255 0, 0, 0, 0 0.00,0.00) B( 199, 110 237, 131 255 0, 0, 0, 0 0.00,0.00) pip
1 A( 0, 0 239, 135 255 0, 0, 0, 0 0.00,0.00) B( 199, 110 237, 131 255 0, 0, 0, 0 0.00,0.00) ...
2 A( 0, 0 238, 134 255 0, 0, 0, 0 0.00,0.00) B( 198, 108 238, 130 255 0, 0, 0, 0 0.00,0.00) ...
3 A( 4, 0 234, 130 255 0, 0, 0, 0 0.00,0.00) B( 196, 106 240, 131 255 0, 0, 0, 0 0.00,0.00) ...
4 A( 9, 0 228, 123 255 0, 0, 0, 0 0.00,0.00) B( 193, 101 245, 130 255 0, 0, 0, 0 0.00,0.00) ...
5 A( 15, 1 219, 116 255 0, 0, 0, 0 0.00,0.00) B( 188, 95 249, 129 255 0, 0, 0, 0 0.00,0.00) ...
6 A( 21, 2 208, 107 255 0, 0, 0, 0 0.00,0.00) B( 182, 87 254, 127 255 0, 0, 0, 0 0.00,0.00) ...
7 A( 24, 4 194, 100 255 0, 0, 0, 0 0.00,0.00) B( 175, 79 258, 126 255 0, 0, 0, 0 0.00,0.00) ...
8 A( 27, 6 180, 92 255 0, 0, 0, 0 0.00,0.00) B( 167, 70 261, 123 255 0, 0, 0, 0 0.00,0.00) ...
9 A( 26, 9 164, 87 255 0, 0, 0, 0 0.00,0.00) B( 157, 60 260, 118 255 0, 0, 0, 0 0.00,0.00) ...
10 A( 20, 13 147, 84 255 0, 0, 0, 0 0.00,0.00) B( 145, 50 256, 112 255 0, 0, 0, 0 0.00,0.00) ...
----------------------------------------------------------- FLIP SOURCES ------------------------------------------------------------
11 B( 11, 20 130, 87 255 0, 0, 0, 0 0.00,0.00) A( 133, 41 248, 106 255 0, 0, 0, 0 0.00,0.00) ...
12 * B( 1, 33 118, 99 255 0, 0, 0, 0 0.00,0.00) A( 120, 33 237, 99 255 0, 0, 0, 0 0.00,0.00) sbs
13 B( 1, 32 118, 98 255 0, 0, 0, 0 0.00,0.00) A( 119, 32 236, 98 255 0, 0, 0, 0 0.00,0.00) ...
14 B( 10, 51 125, 116 255 0, 0, 0, 0 0.00,0.00) A( 104, 24 223, 91 255 0, 0, 0, 0 0.00,0.00) ...
15 B( 30, 64 141, 126 255 0, 0, 0, 0 0.00,0.00) A( 88, 17 215, 88 255 0, 0, 0, 0 0.00,0.00) ...
16 B( 55, 74 158, 132 255 0, 0, 0, 0 0.00,0.00) A( 72, 11 210, 89 255 0, 0, 0, 0 0.00,0.00) ...
17 B( 80, 83 174, 136 255 0, 0, 0, 0 0.00,0.00) A( 57, 7 210, 93 255 0, 0, 0, 0 0.00,0.00) ...
18 B( 106, 90 189, 137 255 0, 0, 0, 0 0.00,0.00) A( 43, 4 213, 100 255 0, 0, 0, 0 0.00,0.00) ...
19 B( 131, 96 203, 136 255 0, 0, 0, 0 0.00,0.00) A( 30, 2 217, 107 255 0, 0, 0, 0 0.00,0.00) ...
20 B( 154, 101 215, 135 255 0, 0, 0, 0 0.00,0.00) A( 19, 1 223, 116 255 0, 0, 0, 0 0.00,0.00) ...
21 B( 172, 105 224, 134 255 0, 0, 0, 0 0.00,0.00) A( 11, 0 230, 123 255 0, 0, 0, 0 0.00,0.00) ...
22 B( 187, 107 231, 132 255 0, 0, 0, 0 0.00,0.00) A( 5, 0 235, 130 255 0, 0, 0, 0 0.00,0.00) ...
23 B( 195, 109 235, 131 255 0, 0, 0, 0 0.00,0.00) A( 1, 0 239, 134 255 0, 0, 0, 0 0.00,0.00) ...
24 * B( 199, 110 237, 131 255 0, 0, 0, 0 0.00,0.00) A( 0, 0 240, 135 255 0, 0, 0, 0 0.00,0.00) pip
As you can see the triple verbose mode (using option -vvv
) prints out a list of loaded composites and found transitions too, like option -l
does.
Additionally it prints out:
- the composites used to request the transition
pip -> pip
including a mark(swapped)
at the right margin indicates that this transition has the same begin and end frame and so it will be swapped, - the searched transitions (in this case there is only one),
- the long table which shows the calculated animation for this transition and all it's properties,
- the flipping point at
--- FLIP SOURCES ---
from which on the letters for A and B are swapped and - also the
*
signs which mark the used key frames from the composites out of the configuration.
To examine the automatically generated composites and transitions you can print out the transition table with -m
:
▶ python3 testtransition.py -m
transition table:
fs-a pip sbs sbsp fs-b ^sbsp ^sbs
fs-a Φ(def(fs-a/fs-a)) fs-a-pip fs-a-sbs fs-a-sbsp fs-fs ^fs-b-sbsp ^fs-b-sbs
pip fs-a-pip⁻¹ Φ(pip-pip) def(pip/sbs) def(pip/sbsp) fs-b-pip⁻¹ def(pip/^sbsp) def(pip/^sbs)
sbs fs-a-sbs⁻¹ def(sbs/pip) Φ(sbs-sbs) def(sbs/sbsp) fs-b-sbs⁻¹ def(sbs/^sbsp) Φ(_sbs-sbs⁻¹)
sbsp fs-a-sbsp⁻¹ def(sbsp/pip) def(sbsp/sbs) Φ(def(sbsp/sbsp)) fs-b-sbsp⁻¹ Φ(def(sbsp/^sbsp)) def(sbsp/^sbs)
fs-b Φ(fs-fs⁻¹) Φ(fs-b-pip) fs-b-sbs fs-b-sbsp Φ(^fs-fs) ^fs-a-sbsp ^fs-a-sbs
^sbsp ^fs-b-sbsp⁻¹ def(^sbsp/pip) def(^sbsp/sbs) Φ(def(^sbsp/sbsp)) ^fs-a-sbsp⁻¹ Φ(def(^sbsp/^sbsp)) def(^sbsp/^sbs)
^sbs ^fs-b-sbs⁻¹ def(^sbs/pip) Φ(_sbs-sbs) def(^sbs/sbsp) ^fs-a-sbs⁻¹ def(^sbs/^sbsp) Φ(^sbs-sbs)
The table has rows of all configured start target composites and columns of end target composites. Every cell includes the available transitions.
The program consists of several functions which are called from a main block:
read_argumentc()
init_log()
render_sequence(*read_config("composite.ini"))
render_sequence()
takes exactly what read_config()
is delivering.
Reads command line arguments like described above.
def read_argumentc():
Fills global Args
with the parser result.
Initializes debug logging.
def init_log():
Global log
gets the logger instance.
Read from the given file.
def read_config(filename):
filename
is the name of the configuration file.
Renders pictures of all composites
and saves them into PNG files.
def render_compositec(size, composites):
Produces images of the given size
.
Render all transitions between all items in the given sequence by using safe_transition_gif()
(see below).
def render_sequence(size, fps, targets, transitions, composites):
Sequence is defined by the names listed in targets
.
Produces images of the given size
.
Calculate with fps
frames per second and use the transitions
and composites
dictionaries to find matching transitions.
Generates an animated GIF of the given name of an animation by using draw_transition()
(see below)
def save_transition_gif(filename, size, name, animation, time):
filename
is the name of the resulting file, size
it's dimensions, name
the displayed title, animation
the transition to render and time
the duration of that whole animation in the GIF.
Function that draws one composite and returns an image.
def draw_composite(size, composite, swap=False):
Produces images of composite
in the given size
which can be drawn swapped by using swap
.
Internal function that draws one transition and returns a list of images.
def draw_transition(size, transition, name=None):
Produces images of transition
in the given size
.
To get out video transition effect within voctomix the configuration needs a format update and the compositor must be extended by the ability to switch the compositing scenario quickly frame by frame synchronized with the play time.
...in RECT and CROP so we do not hurt someone's feelings.
- May be have just one
configure()
inTransitions
which returns both composites and transitions so that you only need to import the Transitions interface instead of additionally the composites interface. - Decide in which way three source scenarios like c(A1,B) ↔ c(A2,B) or c(A,B1) ↔ c(A,B2) can profite from any kind of specialized transitions.
- What about unlimited sources?
- add additional composite operations (like visual mirroring)?