SCRIPTING VIDEO WITH FREEJ
FreeJ is an asynchronous video rendering engine, it can be scripted using javascript syntax in an object oriented way, to control its operations thru a procedural list of commands and actions.
This way we can start talking about "procedural video" as an evolution of the current non/linear paradigm widely spread in video production.
Far from starting with such an high theoretical approach, this document aims to be a small and effective introduction to the first free software implementation of such a powerful functionality. It will not cover the programming syntax, but simply describe the objects that are made available to script FreeJ. Knowledge of generic object oriented programming syntax is suggested but not strictly necessary to make the first steps in the wonderful world of Procedural Video Scripting.
This document is somehow outdated, a full reference documentation for the scripting language is available on http://freej.dyne.org/docs/scripting
let's get started!
Layers and Effects are the object classes we can deal with. Once they exist, they will provide methods to control their operations.
EXAMPLE:
my_text_layer = new TextLayer(); // create an new TextLayer object (1) add_layer(my_text_layer); // make the new layer shown (2) my_text_layer.print("hello world!"); // print a message on the layer (3)
n this example (1) we first create a new instance of the TxtLayer() class, which provides the Truetype rendering text layer; (2) then we add it to the list of layers processed by the engine; (3) at last we use the print() specific method to print something on the screen.
Now try your first script by writing the three lines above in a file and then execute the file with 'freej -j myfile'
there you are?
then consider in *NIX systems you can use the interpreter header #!/usr/local/bin/freej -j at the beginning of your script, then by making it executable you'll have a self executing freej script!
Generic and specific Layer methods
Every layer class inherits methods from the Layer superclass, providing generic methods common to all of them. Generic methods are available to change Layer attributes like: position, blit method, rotation, zoom, spin etc.
Specific methods are found only on their layer, they can control special operations that a specific layer provides, like: printing a word on the text layer, appending a line to the scroll layer, skipping to a keyframe in a movie layer, etc.
Layer generic methods
The following methods are available to every *Layer object
- activate()
- deactivate()
- get_name()
- get_filename()
- set_blit("alpha") // see list of blits
- get_blit()
- set_blit_value(0.5) // floating point from 0.0 to 1.0
- get_blit_value()
- set_position(100, 200) // width and height in pixels, origin to upper left corner
- get_x_position()
- get_y_position()
- add_effect(effect_object) // pass an Effect object (see script example on how to create it)
- rotate(360) // degrees of rotation
- layer_zoom(1.5, 2.0) // magnification floating point multipliers: 0 (shrink) - 1 (normal) - 2 (double)
- layer_spin(0.5) // floating point spin rotation 0 (left) - 1 (static) - 2 (right)
- layer_list_effects() // returns an array of strings with the name of effects applied
EXAMPLE:
Layer.set_position(int x, int y) // coords of the upper left corner .set_blit("name") // must be an existing layer .set_blit_val(int val) // usually a value between 0 and 255 .rotate(double val) // usually between 0 and 360 .zoom(double x, double y) // floating point multiplier, // 1.0 means no zoom, 2.0 means double size .spin(double rotation, double zoom) // the layer will start rotating // and/or zooming (0 means stop)
Specific Layer Types
new CamLayer(400, 300, "/dev/video") new TextLayer(640, 480, "poetry.txt") (*) new MovieLayer("movie.avi") // if no size is specified, use the one of the video new ImageLayer("photo.png") new VScrollLayer("book.txt") (*) new ParticleLayer() // doesn't need a file, use the size of the screen new GeometryLayer(640, 480) (*) = the filename can be also omitted, the layer is then used with its own methods to feed the data to be processed. i.e. TxtLayer.print("string") or VScrollLayer.append("phrase")
the constructor initialization consists of an open() on the file and it can return NULL in case of failure. In case the object returned is not NULL, it can be initialized using the init() call.
MovieLayer
- forward()
- rewind()
- mark_in()
- mark_out() // starts looping between mark_in and mark_out
- pause()
TextLayer methods
- font("filename.ttf") // full path to a truetype font
- size(50) // reasonable sizes from 10 to 200
- print("hello world) // add a word or phrase to the text
- advance() // go to the next word
- blink() // switch blinking on/off
- blink_on() // blink on
- blink_off() // blink off
Blinking means that the words are cycled thru one by one while the text is blinking. Control can be gained also over the speed and timing (todo)
CamLayer methods
CamLayer only supports Video4Linux version 1 *no* v4l2
- chan(0) // 0 is TV tuner, 1 is composite video, 2 is s-video (usually..)
- band() // see freej/src/tvfreq.c
- freq() // see freej/src/tvfreq.c
Hint: If CamLayer fails with your device, try MovieLayer(w, h, '/dev/video') instead!
VScrollLayer methods
- append("next line that is going to scroll up thru the screen");
- speed(2) // how many pixels to advance up on every frame refresh
- linespace(3) // how many pixels spacing between lines
- kerning(1) // horizontal pixel spacing between letters
GeometryLayer
- clear(0x00000000)
- color(r,g,b,a) // can also be one hexadecimal number 32bit BGRA
- pixel(x, y) // cartesian coordinates in pixels, origin is up left corner
- hline(x, y1, y2) // horizontal line from y1 to y2
- vline(x1, x2, y) // vertical line from x1 to x2
- rectangle(x1, y1, x2, y2) // rectangle or box
- rectangle_fill(x1, y1, x2, y2) // rectangle filled with color
- line(x1, y1, x2, y2) // line
- aaline(x1, y1, x2, y2) // anti-aliased line (edges look better)
- circle(xc, yc, radius) // concentrical circle
- aacircle(xc, yc, radius) // anti-aliased circle
- circle_fill
- ellipse(xc, yc, radius_x, radius_y)
- aaellipse
- ellipse_fill
- pie(xc, yc, radius, start, end) // a piece of the pie
- pie_fill
- trigon(x1, y1, x2, y2, x3, y3) // three vertices joined in a triangle
- aatrigon
- trigon_fill);
EXAMPLE:
geo = new GeometryLayer(640,480); add_layer(geo); // the following calls are all valid: // color takes RGBA .. // geo.color(0xff, 0xee, 0xdd, 0xff); // .. or RGB .. // geo.color(0xff, 0xee, 0xdd); // .. or the 32bit hexcode in BGRA geo.color(0xddeeffff); geo.rectangle_fill(10,10,630,470); // and you can also specify the color directly as a last argument to functions: // geo.rectangle_fill(10,10,630,470,0xddeeffff); // will work as well. run(3); quit();