Skip to content

Examples

Each one is a complete script: paste it into a cue’s Script tab, tick Enabled, and press Compile.

Say what the cue is doing

function onStart() {
    log.info('started, and it lasts', this.duration.get(), 'seconds');
}

function onEnd() {
    log.info('done after', time.toFixed(2), 'seconds');
}

Duck a sound part-way through

An audio cue that drops to a quarter of its level ten seconds in, and comes back up five seconds later.

function onStart() {
    after(10, function () {
        this.level.set(0.25);
    });
    after(15, function () {
        this.level.set(1);
    });
}

Fade a picture in by hand

onTick is called with the seconds since the last frame, so a ramp is a running total. (For a plain fade-in, the cue’s own Fade in setting is simpler — this is the shape to copy when the ramp is not plain.)

const LENGTH = 3;
let elapsed = 0;

function onTick(delta) {
    if (elapsed >= LENGTH) return;
    elapsed += delta;
    // Ease out, rather than the straight line a normal fade-in gives.
    const t = Math.min(1, elapsed / LENGTH);
    this.level.set(1 - (1 - t) * (1 - t));
}

Flash a text cue

every gives the callback its run index, which makes alternating trivial.

function onStart() {
    every({ interval: 0.4, delay: 0 }, function (index) {
        this.textColor.set(index % 2 === 0 ? '#ff2d2d' : '#ffffff');
    });
}

Count down on screen

const FROM = 10;

function onStart() {
    this.text.set(String(FROM));
    every({ interval: 1 }, function (index) {
        const left = FROM - (index + 1);
        this.text.set(left > 0 ? String(left) : 'GO');
    });
}

Drift a title across the output

offsetX is a fraction of the output width, so this moves the text from the left edge to the right over twenty seconds.

const SPEED = 0.05; // fractions of the width per second

function onStart() {
    this.offsetX.set(-0.5);
}

function onTick(delta) {
    const next = this.offsetX.get() + SPEED * delta;
    this.offsetX.set(Math.min(0.5, next));
}

Breathe the colour of an image

function onTick() {
    // A slow sine between 0.7 and 1.3.
    this.brightness.set(1 + Math.sin(time * 2) * 0.3);
}

Drain the saturation as a video plays

function onTick() {
    const total = this.duration.get();
    if (!total) return; // it never ends on its own; nothing to scale against
    this.saturation.set(1 - Math.min(1, time / total));
}

Announce a playlist as it moves

let last = 0;

function onTick() {
    const index = this.index.get();
    if (index !== last && index !== 0) {
        last = index;
        log.info('item', index, 'of', this.count.get(), '— pass', this.pass.get());
    }
}

Do something only on the first pass

function onStart() {
    every({ interval: 5 }, function (index) {
        if (index > 2) return; // three runs, then quietly nothing
        log.info('reminder', index + 1);
    });
}

Guard against a property a cue does not have

Handy when the same script is pasted onto several cue types.

function onStart() {
    if (this.mirrorX) this.mirrorX.set(true);
    if (this.audioLevel) this.audioLevel.set(0.5);
}

A random colour on every beat

function onStart() {
    every(0.5, function () {
        this.textColor.set(random.color({ saturation: [0.6, 1], value: 1 }));
    });
}

Shake a text cue

function onTick() {
    const shake = random.vec2(-0.01, 0.01);
    this.offsetX.set(shake.x);
    this.offsetY.set(shake.y);
}

Pick a line at random, without repeating the last one

const LINES = ['Doors open', 'Five minutes', 'Standing by', 'Curtain'];
let last = null;

function onStart() {
    every(4, function () {
        let line = random.element(LINES);
        while (LINES.length > 1 && line === last) line = random.element(LINES);
        last = line;
        this.text.set(line);
    });
}