Nodes is a new commission created for the Peer to Peer: UK/HK online festival which ran from 11th – 14th November, created as a reflection on the interconnectedness of the global live coding community.
Live coding is a performative practice where artists make music and visual art live using programming. This happens primarily at events such as Algoraves, but there is an equally active online community which organises regular performances, conferences, workshops and more.
Moving beyond e-mail and social media platforms, people within the community have built their own tools which allow for real time communication and collaboration across borders and time zones. In this way the local nodes the global live coding community are able to stay connected.
Many thanks to Dr Charlotte Frost from Furtherfield for the nomination. Nodes was commissioned on the occasion of Peer to Peer: UK/HK online Festival 2020 by Centre for Chinese Contemporary Art, Open Eye Gallery and University of Salford Art Collection.
I really liked the texture I had used on the face and decided to make some random animations (similar to the ones I did for Improviz) and use the same texture. I did some post processing using Natron (e.g. the pixealation and desaturation).
This ongoing adventure to create a typewriter text effect has had a lot of twists and turns over the years. Back in 2011 I used Pure Data to achieve this effect. Fast forward to 2019 and I experimented with Kdenlive and Natron before settling on Animation Nodes. In April 2020 update on this I detailed how I used Animation Nodes and attempted to use Aegisub to create this effect. Around the same time I had started experimenting with expressions in Natron to achieve the same effect.
The value of a parameter can be set by Python expressions. An expression is a line of code that can either reference the value of other parameters or apply mathematical functions to the current value.
The expression will be executed every times the value of the parameter is fetched from a call to getValue(dimension) or get().
In theory with Natron expressions I could created a counter that would increment on every frame and type words out character by character. Y’know, like a typewriter. I’m forever learning Python so after a lot of effort, and a lot of help from people on the Natron forum I came up with the following solution. In the Text node I entered the following expression:
originalText = original.text.get()
output = " "
ptr = 0
slowFac = 4
for i in range(frame/slowFac, len(originalText)+1):
if frame/slowFac < len(originalText):
ret = originalText[0:ptr]
The typewriter text effect starts from 01:04. The same Natron user also posted an alternative solution.
I noticed a bug which meant that I couldn’t change the speed that the letters typed out at. One method of speeding up the text would be to use ret = text[:frame*2-1] or a different multiplier. However, I wanted something a little bit more precise, so I thought about using the Retime node. Unfortunately there was a bug which prevented this. The workaround of using a Constant node worked. In the end it got fixed, but not in time for making that Design Yourself video.
In June I was asked if I could make an intro video for Network music Festival. The organisers wanted around 10 slides of text to appear throughout the video. Some had only several words on them but some had large blocks of text.
I already decided that I wanted to use the typewriter text effect to make the text appear and then to hold that text for a couple of seconds. This presented an interesting problem. Without a Retime node the text appears one character per frame. With a large block of text 250 characters in length (including spaces) this would take, well, 240 frames to appear, which at 24 fps would be 10 seconds. The organisers wanted the video to be about a minute long, so having one slide take up 10 seconds would be far too long.
What I needed was a method for making an arbitrary amount of text to appear within a specific time/frame count. My final Natron expression (after a bit of bug fixing) looked like this.
text = Source.text.get()
# what frame to start triggering the write-on effect
trigger = 15
# how many frames it'll take to write the full text
length = 46
# map values. Taken from herehttps://stackoverflow.com/a/1969274
def translate(value, leftMin, leftMax, rightMin, rightMax):
# Figure out how 'wide' each range is
leftSpan = leftMax - leftMin
rightSpan = rightMax - rightMin
# Convert the left range into a 0-1 range (float)
valueScaled = float(value - leftMin) / float(leftSpan)
# Convert the 0-1 range into a value in the right range.
return rightMin + (valueScaled * rightSpan)
if frame >= trigger:
letter = int(ceil(translate(frame-trigger, 1, length, 1, len(text))))
letter = 0
This expression does several things. It first allows a user to specify at which frame the text will appear (trigger). Then, no matter how much input text there is it will be mapped to the length value. Oddly Python doesn’t have a built in mapping function so I had to use the one from here. Unfortunately it doesn’t work as expected if your Text node has keyframed text changes. So, for that you’ll have to have multiple Text nodes. Here’s the finished Network Music Festival video.